首先看效果(不太清晰)  


视频演示效果


其次我讲一下大概的实现过程:前端用uniapp,(后来软工学长告诉我如果不是跨端开发的话完全可以不用uniapp,如果你要开发微信小程序就用微信开发者工具,如果你要开发移动端app就用安卓studio,因为我是自己琢磨的,当时只知道uniapp),和物联网平台通信用到了后端,以python的flask框架写的后端代码,发送命令后ESP32接收报文,解析并作出相应操作(本文是点灯,如果有其它外设可以扩展功能),同时上报设置属性到物联网平台。

具体流程如下:

1.后端代码编写

要下载阿里云物联网的pythonSDK,python的web框架——flask框架(因为我不太懂前端,因此用的是python,如果熟悉前端的话可以用node.js),这样的话我们就可以编写后端代码,用于和阿里云服务器平台通信了

安卓 阿里物联网sdk 阿里物联网app_安卓 阿里物联网sdk

 后端功能代码示例如图所示,我截取的是检查设备是否在线函数:

安卓 阿里物联网sdk 阿里物联网app_安卓 阿里物联网sdk_02

其实后端功能代码我们完全可以通过阿里云平台的API调试来剪取,具体获取方法如图:

安卓 阿里物联网sdk 阿里物联网app_阿里云_03

 然后就可以查看你需要的实例代码了,截取相应部分到你的代码文件里

安卓 阿里物联网sdk 阿里物联网app_物联网_04

 这样的话你就可以在你的相应文件里调试了,但是这时物联网平台的物模型属性值并不会改变,因为没有设备端上报。

2.编写前端接口

如图所示:

安卓 阿里物联网sdk 阿里物联网app_c语言_05

这里的url必须是你的后端代码设置的ip地址加上你对应功能函数的路由,上文我的chekline函数路由设置的Checkline,因此我这里写的就是/Checkline,同时method也要对照你功能函数写的。res其实就是后端函数的返回值,前端利用后端的返回值就牵扯到JSON数据的解析,我就不过多解释。 

3.设备端ESP32的程序编写:

其实这里又分了几步

①订阅主题

阿里云物联网平台提供了很多主题

安卓 阿里物联网sdk 阿里物联网app_安卓 阿里物联网sdk_06

安卓 阿里物联网sdk 阿里物联网app_物联网_07

我们这里只会用两个,一个是属性上报中的设备属性上报,用于设备的上报属性到物联网平台,另一个是属性设置,用于设备订阅主题,接收应用端发送的命令

这里我们就根据这里的主题名订阅主题,我ESP32的IDF代码如下: 

void mqtt_start()   //连接MQTT服务器
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .host = CONFIG_BROKER_URL,
        .port = 1883,
        .client_id = "<your clientid>",  //这些数据都可以在阿里云物联网平台看到
        .username = "<your username>",
        .password = "<your password>",
        .user_context = NULL,
    };
    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(client, MQTT_EVENT_ANY, mqtt_event_handler, NULL);
    esp_mqtt_client_start(client);
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)    //事件处理回调函数
{
    int msg_id;
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    switch (event_id)
    {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGW(TAG, "Connectted successfully!");
        ESP_LOGW(TAG, "Subscribing topic....");
        msg_id = esp_mqtt_client_subscribe(client, "<your topic>", 0);  //这里就是订阅主题函数
        ESP_LOGW(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGW(TAG, "Disconnectted...");
        esp_mqtt_client_reconnect(client);
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGW(TAG, "Error...");
        esp_mqtt_client_reconnect(client);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGW(TAG, "MQTT_EVENT_DATA");
        parse_info(event->data);   //调用解析函数
        break;
    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGW(TAG, "Subscribed successfully!");
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGW(TAG, "Published successfully!");
        break;
    default:
        break;
    }
}

②解析JSON数据

这里用到了ESP32的cJSON库,贴出我的代码,但是具体的物模型属性需要根据自己的进行修改

void parse_info(char *data)
{
    cJSON *root = cJSON_Parse(data);
    if (root == NULL)
    {
        ESP_LOGE(TAG, "JSON parsing failed!");
        return;
    }
    cJSON *paramsObj = cJSON_GetObjectItem(root, "params");
    if (paramsObj == NULL || !cJSON_IsObject(paramsObj))
    {
        ESP_LOGE(TAG, "Invalid params object!");
        cJSON_Delete(root);
        return;
    }
    // 获取temperature的值
    cJSON *Item = cJSON_GetObjectItem(paramsObj, "temperature");
    if (Item != NULL && cJSON_IsNumber(Item))
    {
        temperature = Item->valueint;
        ESP_LOGW(TAG, "Temperature: %u", temperature);
    }
    // 获取airmode的值
    Item = cJSON_GetObjectItem(paramsObj, "air_mode");
    if (Item != NULL && cJSON_IsNumber(Item))
    {
        air_mode = Item->valueint;
        ESP_LOGW(TAG, "Airmode: %u", air_mode);
    }
    // 获取灯的值
    Item = cJSON_GetObjectItem(paramsObj, "LED_state");
    if (Item != NULL && cJSON_IsNumber(Item))
    {
        light_state = Item->valueint;
        ESP_LOGW(TAG, "LED_state: %u", light_state);
    }
}

③设备做出响应

这样的话我们的动作状态的全局变量就相应的修改成了前端APP发来的理想值,可以通过轮询来检查这些数据的改变,同时检查到了改变的变量并会相应执行这样的动作,例如开灯啊,检查室内温度啊等等这样操作其实我们写起来都很容易,我就不具体贴出代码了。

④设备上报属性值

如果我们在执行操作过程中出现错误,打个比方,我们执行了开灯操作,但传感器检测到并没有开灯,这时我们就可以选择不上报属性,这样的话APP端询问物联网平台属性,如果没有改变则一直发命令等等,这些都是我的想法,我本身工程并没有搞得这么复杂。

一般来说执行操作是没有问题的,这样我们就需要把属性值上报给物联网平台。

我把这个函数贴出来:

esp_mqtt_client_publish(client, topic, "{\"params\":{\"<your property1>\":<value>,}}", strlen("{\"params\":{\"<your property2>\":<value>,}}"), 0, 0);

事实上,你这里会需要用到字符串剪切方法,因为你上报的数据一定是一串字符串,而C语言的快速字符串剪切有一个函数就是sprintf函数。

具体我也贴出我的代码:

char data[50];
sprintf(data, "{\"params\":{\"<property1>\":%u,\"<property2>\":%d}}",<property1val>, <property2val>);
esp_mqtt_client_publish(client, topic, data, strlen(data), 0, 0);

4.总结

这样的话,整个三端互通就完成了,你既可以在物联网平台监控属性,也可以在前端APP控制设备。目前我的项目存在的局限就是你的后端代码运行在电脑上的话,你的电脑必须一直在运行这个python文件才能与前端APP正常交接,而且是局域网IP,这要求你的设备和后端和前端必须在一个局域网内。这是存在的一个局限,但是其实可以买一个公网IP用于后端(记得学长是这么跟我说的)。

其实,我讲的很大概,因为主要是思路嘛,我是主要搞嵌入式的,对这个感兴趣才来搞着玩的。也没有前辈,网上资料也很少,我问客服(这里点名表扬阿里云的服务很好)和自己琢磨花费了大约一个月时间才搞懂,所以我觉得思路搞懂了,这些流程具体操作起来就很快了。