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

2 条评论

发布
问题