W801通过一机一密的方式连接阿里云物联网平台并实现反向控制

发布于 2022-04-19 13:35:41

—————————

5.12更新:
需要注意调用cJSON_Print函数将JSON体转化为字符串时,会开辟内存,转化后使用完毕后需要调用cJSON_free函数将内存释放掉,否则会导致内存泄漏。一旦内存泄漏会导致系统宕机。

—————————

一.项目概述

本项目使用了W801以一机一密的方式连接至阿里云物联网平台,定时发送数据并实现了反向控制。

二.项目前的准备

因为使用阿里云物联网平台,因此需要提前创建好一个设备,这个网上的示例和阿里云自己的文档已经十分完整,因此不多赘述,可以自行查阅。创建完设备的MQTT链接参数是用来进行链接的关键,如下图所示。
1.png

三.MQTT连接的注意点与修改

概述:SDK中提供的MQTT链接示例基本是可用的,但是连接阿里云时需要做如下修改。
【1】修改MQTT链接参数,同时要添加Username以及password的宏定义,订阅和发布的topic根据自己的设备来添加
2.png
【2】修改MQTT的client,username等的数组长度,SDK中的数据范围太小,而阿里云的链接参数由于经过加密因此比较长无法满足要求,需要对以下几个位置进行修改。
3.png
【3】修改原MQTTdemo里面的mqtt_demo_init函数,原函数没有账户密码登录的步骤,但是提供了相应函数,因此需要进行补充。
5.png

四.MQTT连接并实现定时上传

【1】概述:在原demo上修改,添加了一个硬件定时器,定时5s后在中断服务函数,向队列里添加一个MQTT_MSG_PUBLISH_CB标志,主循环读取到这个标志后会进行mqtt消息发送,这边还涉及到一个数据处理成为JSON格式,我这里只发送一个温度信息,格式为{"temperature":"20"},用的就是cJSON库,这个参考下网上其他文章即可。
【2】代码如下:

//mqtt消息发送函数
static int mqtt_msg_pub(void)
{
    char *temperature_msg;
    temperature_msg = datatoJSON(temp_label, temperature);
    mqtt_publish(&mqtt_demo_mqtt_broker, (const char *)MQTT_DEMO_RX_PUB_TOPIC,  (const char *)temperature_msg, strlen(temperature_msg), 0);
    tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_LOOP, 0);
    
    cJSON_free(temperature_msg);
    return 0;
}
//demo中原来的主循环
static void mqtt_demo_task(void *p)
{
    int ret;
    void *msg;
    struct tls_ethif *ether_if = tls_netif_get_ethif();

    if (ether_if->status)
    {
        wm_printf("sta ip: %v\n", ether_if->ip_addr.addr);
        tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_START, 0);
    }

    for ( ; ; )
    {
        ret = tls_os_queue_receive(mqtt_demo_task_queue, (void **)&msg, 0, 0);
        if (!ret)
        {
            switch((u32)msg)
            {
            case MQTT_DEMO_CMD_START:
                do
                {
                    ret = mqtt_demo_init();
                    if (ret)
                        break;
                    tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_LOOP, 0);
                    timer_pub();
                }
                while (0);
                break;
            case MQTT_DEMO_CMD_HEART:
                //wm_printf("send heart ping\r\n");
                mqtt_ping(&mqtt_demo_mqtt_broker);
                break;
            case MQTT_DEMO_CMD_LOOP:
                mqtt_demo_loop();
                break;
            case MQTT_MSG_PUBLISH_CB:   //添加一个新的标志,读取到这个标志时候,进行消息发送
                mqtt_msg_pub();
                break;
            default:
                break;
            }
        }
    }
}

//中断函数中向队列添加标志
static void timer_pub_irq(u8 *arg)
{
    //printf("timer irq\n");
    tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_MSG_PUBLISH_CB, 0);
}

//上传数据硬件定时器
int timer_pub(void)
{
    u8 timer_id;
    struct tls_timer_cfg timer_cfg;
    
    timer_cfg.unit = TLS_TIMER_UNIT_MS;
    timer_cfg.timeout = 5000;
    timer_cfg.is_repeat = 1;
    timer_cfg.callback = (tls_timer_irq_callback)timer_pub_irq;
    timer_cfg.arg = NULL;
    timer_id = tls_timer_create(&timer_cfg);
    tls_timer_start(timer_id);
    
    return WM_SUCCESS;
}

四.阿里云反向控制

【1】阿里云实际上可以采用物模型进行反向控制,但是那个相对比较麻烦,这里我采用一个比较通用的办法,w801订阅了一个topic接受该topic命令并解析,再进行对应操作。这一部分逻辑与我前一篇文章,蓝牙反向控制相似,这里给出链接可以作为参考。
w801通过蓝牙更新wifi并自动重连
【2】代码:

static int mqtt_demo_loop(void)
{    
    int packet_length = 0;
    int counter = 0;
    
    counter++;
    packet_length = mqtt_demo_read_packet(0, 1);
    
    if(packet_length > 0)
    {
        if (MQTTParseMessageType(mqtt_demo_packet_buffer) == MQTT_MSG_PUBLISH)
        {
            uint8_t topic[100], *msg;
            uint16_t len;
            len = mqtt_parse_pub_topic(mqtt_demo_packet_buffer, topic);
            topic[len] = '\0'; // for printf
            len = mqtt_parse_publish_msg(mqtt_demo_packet_buffer, &msg);
            msg[len] = '\0'; // for printf
            //wm_printf("recvd: %s >>> %s\n", topic, msg);
            aliyun_cmd_excute(msg);
        }

        tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_LOOP, 0);
    }
    else if (packet_length == MQTT_DEMO_READ_TIMEOUT)
    {
        tls_os_queue_send(mqtt_demo_task_queue, (void *)MQTT_DEMO_CMD_LOOP, 0);
    }
    else if(packet_length == -1)
    {
        wm_printf("mqtt error:(%d), stop mqtt demo!\n", packet_length);
        tls_os_timer_stop(mqtt_demo_heartbeat_timer);
        mqtt_demo_close_socket(&mqtt_demo_mqtt_broker);
    }
    
    return 0;
}

int aliyun_cmd_excute(char *cmd)
{
    //解析Json字符串
    cJSON *str_json, *str_cmd;
    str_json = cJSON_Parse(cmd);
    if (!str_json)
    {
        printf("[INFO]: JSON格式错误: %s\r\n", cJSON_GetErrorPtr());
    }
    else
    {
        str_cmd = cJSON_GetObjectItem(str_json, "cmd");
        if (str_cmd->type == cJSON_Number)
        {
            //printf("[INFO]: cmd: %d\r\n", str_cmd->valueint);
            if (str_cmd->valueint == 1)
            {
                temperature++;
                printf("[CMD_ALIYUN]: Temperature rise by aliyun, the current temp is %d\n",temperature);
            }
            else if (str_cmd->valueint == 2)
            {
                temperature--;
                printf("[CMD_ALIYUN]: Temperature drops by aliyun, the current temp is %d\n",temperature);
            }
        }
    }
    cJSON_delete(str_json);
    
    return WM_SUCCESS;
}

五.实验结果

6.png
7.png
8.png
9.png

1 条评论

发布
问题