当前位置: 首页 > news >正文

ESP32学习笔记(基于IDF):OneNET物模型数据交互(控制小灯)

目录

  • 前言
  • 一、工程配置、代码编写
  • 二、比较重要的地方
  • 三、测试与实验

前言

ESP32学习笔记(基于IDF):ESP32接入OneNET
本文基于上篇笔记的延续,上篇笔记成功把ESP32连接上了OneNET,本篇文章尝试在OneNET平台上给ESP32下发指令,然后控制ESP32的小灯,然后实际上我的ESP32没有接小灯硬件,所以对下发的指令做打印处理,以演示效果,重点是把ESP32根OneNET的通路打通。

一、工程配置、代码编写

1、 在iot目录下新增onenet_dm.c和onenet_dm.h这两个文件
在这里插入图片描述
2、onenet_dm.c文件下,写入如下代码

#include "onenet_dm.h"
#include "esp_log.h"
#include <string.h>static int led_brightness = 0;   //LED亮度
static int led_status = 0;      //LED开关状态static int ws2812_red = 0;      //RGB红色通道
static int ws2812_green = 0;    //RGB绿色通道
static int ws2812_blue = 0;     //RGB蓝色通道void onenet_dm_init(void)
{}
void onenet_property_handle(cJSON* property)
{// {// "id": "123",// "version": "1.0",// "params": {//     "Brightness":"50"//     "LightSwitch":true//     "RGBColor":{//          "Red":100,//          "Green":100,//          "Blue":100,//      }// }// }// 先判断传入的property是否为空,避免空指针访问if (property == NULL) {ESP_LOGE("onenet", "property is NULL, skip handle");return;}//从CJSON中解析”param“字段cJSON* param_js = cJSON_GetObjectItem(property,"params");if (param_js == NULL) {ESP_LOGE("onenet", "params not found in property");return;}if(param_js){cJSON* name_js = param_js->child;while(name_js){if(strcmp(name_js->string,"Brightness") == 0){led_brightness = cJSON_GetNumberValue(name_js);ESP_LOGI("onenet", "Set Brightness to %d", led_brightness);}else if(strcmp(name_js->string,"LightSwitch") == 0)  //开关数据{if(cJSON_IsTrue(name_js)){led_status = 1;ESP_LOGI("onenet", "Turn LED ON");}else{led_status = 0;ESP_LOGI("onenet", "Turn LED OFF");}}else if(strcmp(name_js->string,"RGBColor") == 0){ws2812_red = cJSON_GetNumberValue(cJSON_GetObjectItem(name_js,"Red"));ws2812_green = cJSON_GetNumberValue(cJSON_GetObjectItem(name_js,"Green"));ws2812_blue = cJSON_GetNumberValue(cJSON_GetObjectItem(name_js,"Blue"));ESP_LOGI("onenet", "Set RGB to (%d, %d, %d)", ws2812_red, ws2812_green, ws2812_blue);}name_js = name_js->next;}}
}cJSON* onenet_property_upload(void)
{// {// "id": "123",// "version": "1.0",// "params": {//     "Brightness"://      {//           "value":50 //       }//     "LightSwitch"://       {//            "value":true//        }//     "RGBColor":{//          "value":{               //          "Red":100,//          "Green":100,//          "Blue":100,//          }//      }// }// }//创建根JSON对象cJSON* root = cJSON_CreateObject();cJSON_AddStringToObject(root,"id","123");cJSON_AddStringToObject(root,"version","1.0");cJSON* param_js = cJSON_AddObjectToObject(root,"params");//亮度cJSON* led_brightness_js = cJSON_AddObjectToObject(param_js,"Brightness");cJSON_AddNumberToObject(led_brightness_js,"value",led_brightness);//开关cJSON* lightness_js = cJSON_AddObjectToObject(param_js,"LightSwitch");cJSON_AddBoolToObject(lightness_js,"value",led_status);//RGB值cJSON* color_js = cJSON_AddObjectToObject(param_js,"RGBColor");cJSON* color_value_js = cJSON_AddObjectToObject(color_js,"value");cJSON_AddNumberToObject(color_value_js,"Red",ws2812_red);cJSON_AddNumberToObject(color_value_js,"Green",ws2812_green);cJSON_AddNumberToObject(color_value_js,"Blue",ws2812_blue);return root;
}

3、onenet_dm.h文件下,写入如下代码

#ifndef _ONENET_DM_H
#define _ONENET_DM_H
#include "cJSON.h"void onenet_dm_init(void);
void onenet_property_handle(cJSON* property);cJSON* onenet_property_upload(void);#endif

4、然后onenet_mqtt.c文件较上一篇笔记有所改动,不过我这里就不单独贴改动部分了,也是直接贴全部源码
在这里插入图片描述

#include "onenet_mqtt.h"
#include "onenet_token.h"
#include "mqtt_client.h"
#include "esp_log.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "cJSON.h"
#include "onenet_dm.h"#define TAG "onenet"static esp_mqtt_client_handle_t mqtt_handle = NULL;static void onenet_property_ack(const char* id,int code,const char* msg);static void onenet_subscribe(void);static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{esp_mqtt_event_handle_t event = event_data;switch ((esp_mqtt_event_id_t)event_id) {case MQTT_EVENT_CONNECTED:ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");onenet_subscribe();cJSON* property_js = onenet_property_upload();char* data = cJSON_PrintUnformatted(property_js);onenet_post_property_data(data);cJSON_free(data);cJSON_Delete(property_js);break;case MQTT_EVENT_DISCONNECTED:ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");break;case MQTT_EVENT_SUBSCRIBED:ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);break;case MQTT_EVENT_UNSUBSCRIBED:ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);break;case MQTT_EVENT_PUBLISHED:ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);break;case MQTT_EVENT_DATA:ESP_LOGI(TAG, "MQTT_EVENT_DATA");printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);printf("DATA=%.*s\r\n", event->data_len, event->data);if(strstr(event->topic,"property/set")){cJSON* property = cJSON_Parse(event->data);cJSON* id_js = cJSON_GetObjectItem(property,"id");onenet_property_handle(property);onenet_property_ack(cJSON_GetStringValue(id_js),200,"success");cJSON_Delete(property);}break;case MQTT_EVENT_ERROR:ESP_LOGI(TAG, "MQTT_EVENT_ERROR");break;default:ESP_LOGI(TAG, "Other event id:%d", event->event_id);break;}
}esp_err_t onenet_start(void)
{esp_mqtt_client_config_t mqtt_config;memset(&mqtt_config,0,sizeof(esp_mqtt_client_config_t));mqtt_config.broker.address.uri = "mqtt://mqtts.heclouds.com";mqtt_config.broker.address.port = 1883;mqtt_config.credentials.client_id = ONENET_DEVICE_NAME;mqtt_config.credentials.username = ONENET_PRODUCT_ID;static char token[256];dev_token_generate(token,SIG_METHOD_SHA256,2232933411,ONENET_PRODUCT_ID,NULL,ONENET_PRODUCT_ACCESS_KEY);mqtt_config.credentials.authentication.password = token;//将鉴权信息打印出来ESP_LOGI(TAG,"onenet connect->clientId:%s,username:%s,password:%s",mqtt_config.credentials.client_id,mqtt_config.credentials.username,mqtt_config.credentials.authentication.password);mqtt_handle = esp_mqtt_client_init(&mqtt_config);esp_mqtt_client_register_event(mqtt_handle,ESP_EVENT_ANY_ID,mqtt_event_handler,NULL);return esp_mqtt_client_start(mqtt_handle);
}static void onenet_property_ack(const char* id, int code, const char* msg)
{char topic[128];snprintf(topic,128,"$sys/%s/%s/thing/property/set_reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);cJSON* reply_js = cJSON_CreateObject();cJSON_AddStringToObject(reply_js,"id",id);cJSON_AddNumberToObject(reply_js,"code",code);cJSON_AddStringToObject(reply_js,"msg",msg);char* data = cJSON_PrintUnformatted(reply_js);esp_mqtt_client_publish(mqtt_handle,topic,data,strlen(data),1,0);cJSON_free(data);cJSON_Delete(reply_js);
}static void onenet_subscribe(void)
{char topic[128];sniprintf(topic,128,"$sys/%s/%s/thing/property/post/reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);sniprintf(topic,128,"$sys/%s/%s/thing/property/set",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);
}esp_err_t onenet_post_property_data(const char* data)
{char topic[128];snprintf(topic,128,"$sys/%s/%s/thing/property/post",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);ESP_LOGI(TAG,"Upload topic:%s,payload:%s",topic,data);return esp_mqtt_client_publish(mqtt_handle,topic,data,strlen(data),1,0);
}

5、在onenet_mqtt.h文件下,写入如下代码
在这里插入图片描述

#ifndef _ONENET_MQTT_H_
#define _ONENET_MQTT_H_
#include "esp_err.h"//产品ID
#define ONENET_PRODUCT_ID            "E3Sgq5fGjC"  
//产品密钥
#define ONENET_PRODUCT_ACCESS_KEY    "a82bv2/LWRePdSfT+cmRDw2Jt+8bl3NZJxOxbdN3O6M="
//设备名称                  
#define ONENET_DEVICE_NAME           "esp32led01"esp_err_t onenet_start(void);esp_err_t onenet_post_property_data(const char* data);#endif

6、在onenet.c文件下,写入如下代码
在这里插入图片描述

#include <stdio.h>
#include "onenet_mqtt.h"
#include "wifi_manager.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "onenet_dm.h"static EventGroupHandle_t wifi_ev = NULL;
#define WIFI_CONNECT_BIT   BIT0/*** wifi事件回调函数* @param ev wifi事件* @return 无*/
static void wifi_state_callback(WIFI_STATE state)
{if(state == WIFI_STATE_CONNECTED){xEventGroupSetBits(wifi_ev,WIFI_CONNECT_BIT);}
}void app_main(void)
{// 1. 初始化 NVS 闪存(非易失性存储)// NVS 用于保存 Wi-Fi 密码、设备配置等需要断电后保留的数据nvs_flash_init();// 2. 创建事件组(用于同步 Wi-Fi 连接状态)// 事件组是 FreeRTOS 提供的同步机制,这里用于标记 Wi-Fi 是否连接成功wifi_ev = xEventGroupCreate();// 3. 初始化 Wi-Fi 管理器,并注册状态回调函数// wifi_manager_init:初始化 Wi-Fi 相关资源(如配置 Wi-Fi 模式、注册事件处理等)// wifi_state_callback:自定义回调函数,用于接收 Wi-Fi 连接/断开等状态通知onenet_dm_init();wifi_manager_init(wifi_state_callback);// 4. 调用 Wi-Fi 管理器连接指定的 Wi-Fi 热点// 参数:Wi-Fi 热点名称(SSID)为 "Lymow",密码为 "1415926535"wifi_manager_connect("Lymow","1415926535");//连接的WIFI用户名跟密码EventBits_t ev;while(1){//等待WIFI连接成功,然后才开始连接onenetev = xEventGroupWaitBits(wifi_ev,WIFI_CONNECT_BIT,pdTRUE,pdFALSE,pdMS_TO_TICKS(10*1000));if(ev & WIFI_CONNECT_BIT){// Wi-Fi 已就绪,启动 OneNet 平台连接(如 MQTT 连接)onenet_start();}}
}

7、CMakeLists.txt文件,配置如下
在这里插入图片描述

二、比较重要的地方

1、onenet_dm.c里面实现三个重要函数:1、初始化物模型数据 2、处理onenet下行数据 3、处理esp32上发数据

#ifndef _ONENET_DM_H
#define _ONENET_DM_H
#include "cJSON.h"void onenet_dm_init(void);      //初始化物模型数据
void onenet_property_handle(cJSON* property);    //处理onenet给ESP32下发的数据cJSON* onenet_property_upload(void);   //处理ESP32给onenet上报的数据#endif

在这里插入图片描述
2、onenet下行数据格式是这样的,所以我们需要按这个格式解析,可以对着这个格式看代码,代码里只关注了params这个参数,根据这个参数里对应的值来控制相应的硬件

在这里插入图片描述
3、ESP32上报的数据格式长这样,对着这个格式看上报函数的代码
在这里插入图片描述
4、这部分代码的作用是订阅OneNET平台的主题,订阅的两个主题分别是属性上报回复、属性设置指令

static void onenet_subscribe(void)
{char topic[128];sniprintf(topic,128,"$sys/%s/%s/thing/property/post/reply",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);sniprintf(topic,128,"$sys/%s/%s/thing/property/set",ONENET_PRODUCT_ID,ONENET_DEVICE_NAME);esp_mqtt_client_subscribe_single(mqtt_handle,topic,1);
}

三、测试与实验

1、在工程目录下输入以下指令,进行编译、下载、调试

idf.py flash monitor

在这里插入图片描述
2、下载完成后,可以看到,ESP32先向OneNET上报了一包小灯属性值,然后OneNET接到后则下发一包”成功收到“的消息提示
在这里插入图片描述
3、在OneNET平台上则可以看到ESP23上报上来的属性了
在这里插入图片描述
4、试试用OneNET平台下发指令去控制下等的明亮度
在这里插入图片描述
5、设置后,可以看到ESP32回复接收成功
在这里插入图片描述
6、查看ESP32调试台这边打印,则可以看到明亮度变成了29(以打印模拟硬件实现)
在这里插入图片描述

http://www.dtcms.com/a/541022.html

相关文章:

  • JavaScript逆向与爬虫实战——基础篇(css反爬之动态字体实现原理及绕过)
  • 浏览器在请求 js/css 静态文件时,服务器返回了 500 内部错误 500 Internal Server Error
  • CSS 实现酷炫的不规则圆角与斜角边框效果(四种方法详解)
  • 在线网站地图生成器自建购物网站多少钱
  • 网站开发的整个流程一家只做卫生巾的网站
  • xv6-riscv开发调试环境搭建(vscode+ubuntu)
  • 架构兜底五大手段:构建韧性系统的全面防御体系
  • 阿里巴巴有几个网站是做外贸的wordpress 禅意主题
  • 在 `PaddleOCR` 中配置自定义模型(如自己训练的检测/识别模型)
  • 云谷系统网站开发网站备案要收费吗
  • 前端页面初始化加载速度优化方案
  • 【数据库】金仓数据库构建集团化医院全栈信创“全链路解决方案”
  • MATLAB基于自适应动态特征加权的K-means算法
  • 我的Dify OCR 识别发票准确率测试工具
  • 免费域名申请网站大全封面型网站首页怎么做
  • 专业的网站建设化妆品备案
  • 详解使用CodeBuddy解决高难度项目问题
  • Days.js实时更新时间格式文案在切换全局语言之后的方案
  • 网站icp备案时间网站营销网站营销推广
  • 广州官方宣布网络公司网站优化网站建设
  • 【黑马点评|2 Redis缓存 面试题】
  • 大学学院教授委员会制度研究(二)理论基础与分析框架-杨立恒毕业论文
  • Nginx基础入门篇-基础配置
  • 雅可比SVD算法:高精度矩阵分解的经典方法
  • 在 Python 中测试中assert断言和 if分支的区别
  • 【题解】洛谷 P1169 [ZJOI2007] 棋盘制作 [思维 + dp]
  • 音频限幅器D2761使用手册
  • 网站金融模版wordpress轮播代码
  • 【工具推荐】电脑手机多端互通协作实用
  • 一般网站的跳出率dede做双语网站