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 條評論

發布
問題