ESP8266官方V3.1 SDK连云篇02-小程序监控esp8266

前言:

两个月前,我们完成了连接腾讯云的工作,当时配网引导页面,就只是配置下引导页面,如今配网引导页面可以选择不同配网方式,然后再进行引导页面设置,对此,腾讯云维护的qcloud-iot-esp-wifi SDK也进行了不小的更新,本文我们将同步腾讯云更新的SDK,并实现微信小程序控制设备的目标。

一、基础知识

1.设备配网方式

正式更新SDK之前,咱们先修改下后台配网页面,点击交互开发,进入如下页面

然后点击配网引导一行配置按钮,然后选择首选配网方式为SmartConfig,次选配网方式暂时不用,接着点击保存按钮
在这里插入图片描述

然后进行首选配网方式引导页配置,使用默认即可,点击保存
在这里插入图片描述

2.SDK更新说明

上一节中的代码结构如下,将腾讯云SDK内嵌到了ESP8266_RTOS_SDK中
在这里插入图片描述
由于腾讯云更新比较频繁,按照之前的方式,每次更新SDK都需要不少工作量,因此,本节开始,我们将腾讯云Demo SDK和ESP8266_RTOS_SDK独立起来,腾讯云提供demo SDK不再内嵌到ESP8266_RTOS_SDK中,如此一来,之后如果需要更新腾讯云固件,直接替换就行了。
在这里插入图片描述
Makefile代码也稍作修改如下,重新制定下IDF路径也就是ESP8266_RTOS_SDK的路径。

#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := esp8266-qcloud-iot
IDF_DIR := ESP8266_RTOS_SDK
PWD := /home/Administrator
export IDF_PATH ?= $(PWD)/$(IDF_DIR)
SDKCONFIG_DEFAULTS := $(PWD)/qcloud-iot-esp8266-demo/sdkconfig.qcloud
include $(IDF_PATH)/make/project.mk

二、核心代码

1.腾讯云SDK更新

首先直接将腾讯云提供的Deo和SDK全部复制到和ESP8266_RTOS_SDK 在/home/Administrator文件夹下,然后修改Makefile内容如上图,全部复制过去,然后修改components/qcloud_iot/qcloud_iot_c_sdk/platform/HAL_Device_freertos.c中产品参数配置,将product_id等信息修改为自己创建的即可
在这里插入图片描述

2.配网方式修改

打开qcloud_demo_task()函数中start_smartconfig(),注释掉softAP配网函数start_softAP(“ESP8266-SAP”, “12345678”, 0);

void qcloud_demo_task(void* parm)
{
    bool wifi_connected = false;
    Log_i("qcloud_demo_task start");
#if CONFIG_WIFI_CONFIG_ENABLED
    /* to use WiFi config and device binding with Wechat mini program */
    int wifi_config_state;
    //int ret = start_softAP("ESP8266-SAP", "12345678", 0);
    int ret = start_smartconfig();
    if (ret) {
        Log_e("start wifi config failed: %d", ret);
    } else {
        /* max waiting: 150 * 2000ms */
        int wait_cnt = 150;
        do {
            Log_d("waiting for wifi config result...");
            HAL_SleepMs(2000);            
            wifi_config_state = query_wifi_config_state();
        } while (wifi_config_state == WIFI_CONFIG_GOING_ON && wait_cnt--);
    }
    wifi_connected = is_wifi_config_successful();
    if (!wifi_connected) {
        Log_e("wifi config failed!");
        // setup a softAP to upload log to mini program
        start_log_softAP();
    }
#else
    /* init wifi STA and start connection with expected BSS */
    esp_wifi_initialise();
    /* 20 * 1000ms */
    wifi_connected = wait_for_wifi_ready(CONNECTED_BIT, 20, 1000);
#endif
    if (wifi_connected) {
        setup_sntp();
        Log_i("WiFi is ready, to do Qcloud IoT demo");
        Log_d("timestamp now:%d", HAL_Timer_current_sec());
#ifdef CONFIG_QCLOUD_IOT_EXPLORER_ENABLED
        qcloud_iot_explorer_demo(CONFIG_DEMO_EXAMPLE_SELECT);
#else
        qcloud_iot_hub_demo();
#endif
    } else {
        Log_e("WiFi is not ready, please check configuration");
    }
    Log_w("qcloud_demo_task quit");
    vTaskDelete(NULL);
}

同时注意,替换掉qcloud_wifi_config.c中函数app_reply_dev_info中代码,主要修改内容是,直接自己组包,将配网结果信息返回给小程序,源代码中cJSON_PrintPreallocated出现错误,导致配网失败。

static int app_reply_dev_info(comm_peer_t *peer)
{
    int        ret;
    DeviceInfo devinfo;
    ret = HAL_GetDevInfo(&devinfo);
    if (ret) {
        Log_e("load dev info failed: %d", ret);
        app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ret);
        return -1;
    }
    cJSON *reply_json = cJSON_CreateObject();
    cJSON_AddNumberToObject(reply_json, "cmdType", (int)CMD_DEVICE_REPLY);
    cJSON_AddStringToObject(reply_json, "productId", devinfo.product_id);
    cJSON_AddStringToObject(reply_json, "deviceName", devinfo.device_name);
    cJSON_AddStringToObject(reply_json, "protoVersion", SOFTAP_BOARDING_VERSION);
    char json_str[256] = {0};
    // if (0 == cJSON_PrintPreallocated(reply_json, json_str, sizeof(json_str), 0)) {
    //     Log_e("cJSON_PrintPreallocated failed!");
    //     cJSON_Delete(reply_json);
    //     app_send_error_log(peer, CUR_ERR, ERR_APP_CMD, ERR_JSON_PRINT);
    //     return -1;
    // }
    /* append msg delimiter */
    // strcat(json_str, "\r\n");
    // cJSON_Delete(reply_json);
    snprintf(json_str, 256, "{\"cmdType\":2,\"productId\":\"%s\",\"deviceName\":\"%s\",\"protoVersion\":\"%s\"}",devinfo.product_id, devinfo.device_name, SOFTAP_BOARDING_VERSION);
    Log_d("============== json_str is %s\r\n", json_str);
    strcat(json_str, "\r\n");
    int udp_resend_cnt = 3;
udp_resend:
    ret = sendto(peer->socket_id, json_str, strlen(json_str), 0, peer->socket_addr, peer->addr_len);
    if (ret < 0) {
        Log_e("send error: %s", strerror(errno));
        push_error_log(ERR_SOCKET_SEND, errno);
        return -1;
    }
    /* UDP packet could be lost, send it again */
    /* NOT necessary for TCP */
    if (peer->socket_addr != NULL && --udp_resend_cnt) {
        HAL_SleepMs(1000);
        goto udp_resend;
    }
    HAL_Printf("Report dev info: %s", json_str);
    return 0;
}

3.驱动RGB三色灯

RGB三色灯内部原理图如下:
在这里插入图片描述

我们将RGB三色灯正极连接NodeMCU的VCC R、G、B三个引脚分别连接D0、D1、D2,只需要给D0 D1 D2高低电平即可点亮三色灯。

我们使用的是NodeMCU,引脚对应图如下,我们需要驱动RGB三色灯,注意D0对应GPIO16,D1和D2分别对应GPIO5 GPIO4。
在这里插入图片描述
点亮RGB三色灯

esp_err_t set_rgb_led_state(eRGBState rgb, uint32_t state)
{
    switch ( rgb )
    {
    case RGB_LED_RED:
        return gpio_set_level(GPIO_RGB_RED_LED, state);
        break;
    case RGB_LED_GREEN:
        return gpio_set_level(GPIO_RGB_GREEN_LED, state);
        break;
    case RGB_LED_BLUE:
        return gpio_set_level(GPIO_RGB_BLUE_LED, state);
        break;
    
    default:
        break;
    }
    return ESP_FAIL;
}

/* demo for light logic conttrol */
static void deal_down_stream_user_logic(void *client, ProductDataDefine *light)
{
    int  i;
    char brightness_bar[]   = "||||||||||||||||||||";
    int  brightness_bar_len = strlen(brightness_bar);
    /* using console log to show brightness change */
    brightness_bar_len =
        (light->m_brightness >= 100) ? brightness_bar_len : (int)((light->m_brightness * brightness_bar_len) / 100);
    for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
        brightness_bar[i] = '-';
    }
    if (light->m_light_switch) {
        HAL_Printf("\n[  light is on  ]|[brightness:%s]|[%s]\n\n", brightness_bar, light->m_name);
    } else {
        HAL_Printf("\n[  light is off ]|[brightness:%s]|[%s]\n\n", brightness_bar, light->m_name);
    }
    /** hardware control **/
    if (light->m_light_switch) {
        // set_relay_led_state(RELAY_LED_ON);
        set_rgb_led_state(RGB_LED_GREEN, GPIO_SET);
        set_rgb_led_state(RGB_LED_BLUE, GPIO_SET);
        set_rgb_led_state(RGB_LED_RED, GPIO_CLEAR);
    } else {
        // set_relay_led_state(RELAY_LED_OFF);
        set_rgb_led_state(RGB_LED_GREEN, GPIO_SET);
        set_rgb_led_state(RGB_LED_BLUE, GPIO_SET);
        set_rgb_led_state(RGB_LED_RED, GPIO_SET);
    }
    switch (light->m_color)
    {
    case eCOLOR_RED:
        set_rgb_led_state(RGB_LED_GREEN, GPIO_SET);
        set_rgb_led_state(RGB_LED_BLUE, GPIO_SET);
        set_rgb_led_state(RGB_LED_RED, GPIO_CLEAR);
        break;
    case eCOLOR_GREEN:
        set_rgb_led_state(RGB_LED_RED, GPIO_SET);
        set_rgb_led_state(RGB_LED_BLUE, GPIO_SET);
        set_rgb_led_state(RGB_LED_GREEN, GPIO_CLEAR);
        break;
    case eCOLOR_BLUE:
        set_rgb_led_state(RGB_LED_RED, GPIO_SET);
        set_rgb_led_state(RGB_LED_GREEN, GPIO_SET);
        set_rgb_led_state(RGB_LED_BLUE, GPIO_CLEAR);
        break;
    default:
        break;
    }
#ifdef EVENT_POST_ENABLED
    if (eCHANGED == get_property_state(&light->m_light_switch)) {
        if (light->m_light_switch) {
            // memset(sg_message, 0, MAX_EVENT_STR_MESSAGE_LEN);
            // strcpy(sg_message,"light on");
            // sg_status = 1;
            *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 1;
            memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
            strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light on");
        } else {
            // memset(sg_message, 0, MAX_EVENT_STR_MESSAGE_LEN);
            // strcpy(sg_message,"light off");
            // sg_status = 0;
            *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
            memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
            strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light off");
        }
        // switch state changed set EVENT0 flag, the events will be posted by eventPostCheck
        IOT_Event_setFlag(client, FLAG_EVENT0);
    }
#endif
}

使用light_data_template_sample.c中文件,deal_down_stream_user_logic函数负责处理云端下发的命令,我们根据light->m_color数值,来控制RGB三色灯。

三、运行

烧录程序到设备中后,需要首先打开后台,查看配网二维码,使用小程序对设备进行配网,所谓配网,是指通过小程序将当前环境路由器SSID和密码下发给设备,然后设备就可以愉快的连上服务器进行之后的操作了。关于配网原理请查看官方文档:https://cloud.tencent.com/document/product/1081/43696 ,目前文档提供了三种配网协议说明,如下图
在这里插入图片描述

进入后台,点击批量投产,查看后台二维码
在这里插入图片描述
直接打开微信,使用扫一扫功能扫描二维码
在这里插入图片描述

这里出现了产品配网入口页面,重启NodeMCU lua V3,默认进入配网状态,然后点击小程序立即绑定按钮
在这里插入图片描述

然后勾选我已确认上述操作,点击下一步
在这里插入图片描述

输入SSID和密码后,点击下一步,然后耐心等待即可,注意这个过程手机需要连接到需要设置的WIFI热点
在这里插入图片描述

如果出现上述页面,则说明配网绑定已经成功了,接下来就可以进行远程监控了,点击完成按钮后,可以发现小程序主页上已经有了一个LED灯设备
在这里插入图片描述

点击图标,打开设备详情页
在这里插入图片描述

点击设置RGB三色灯颜色为绿色,可以看到设备Log打印{“color”:1}表示设备成功收到了云端下发的指令
在这里插入图片描述
{“color”:1}1代表颜色为绿色,至于为什么是1,我们可以回看产品定义中功能参数定义
在这里插入图片描述
设备收到指令后点亮RGB三色灯
在这里插入图片描述
至于红色和蓝色都是一样的,不再放图了。

四、结语

如您在使用过程中有任何问题,请加QQ群进一步交流。

QQ交流群:906015840 (备注:物联网项目交流)

源码获取:扫描下方二维码,关注公众号,回复"小程序控制esp8266"即可
在这里插入图片描述
一叶孤沙出品:一沙一世界,一叶一菩提

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

物联网客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值