1.4.4.6 台灯接入实例
优质
小牛编辑
131浏览
2023-12-01
概述
本文档通过具体产品-台灯的开发,说明如何使用IoT模组基于HeyThings RTOS SDK进行开发,完成产品接入。 产品实现模式为:模组SDK + MCU
产品控制功能在MCU侧实现,IoT模组通过厂家私有串口协议与MCU通信。IoT模组为ESP32平台。
1. 开发准备
在开放平台注册产品id等信息,申请设备证书。
2. 目录结构
app_src/
├── protobuf-c //protobuf的C语言实现库
│ ├── protobuf-c.c
│ └── protobuf-c.h
├── app_main.c //应用层入口主程序文件
├── app_main.h
├── app_version.h //应用层软件版本号定义
├── debug_cli.c //终端调试命令任务
├── debug_cli.h
├── dev_abstract.c //设备抽模型接收回调,SDK命令处理入口
├── dev_abstract.h
├── devInfo.pb-c.c //设备基础信息服务protobuf定义
├── devInfo.pb-c.h
├── devInfo.proto
├── light.pb-c.c //智能灯控制服务protobuf定义
├── light.pb-c.h
├── light.proto
├── light_service.c //灯控制服务的模型封装和解析,即user helper
├── light_service.h
├── light_service_devinfo.c //灯基础信息服务的模型封装和解析
├── light_service_devinfo.h
├── light_service_upgrade.c //设备OTA升级服务的模型封装和解析
├── light_service_upgrade.h
├── ota_task.c //应用层实现的ota升级处理,平台相关
├── softwareUpdate.pb-c.c //设备OTA升级服务protobuf定义
├── softwareUpdate.pb-c.h
└── softwareUpdate.proto
3. 信息存储
ESP32模组存储分区示例如下:
序号 标签 用途 类型 子类型 偏移 长度
0 nvs SDK数据区 01 02 00009000 00008000 32k
1 dev_base 用户烧录信息 40 40 00011000 00002000 8k
2 user_base 用户PIN码区 40 41 00013000 00001000 4k
3 otadata OTA data 01 00 00014000 00002000 8K
4 phy_init RF data 01 01 00016000 00001000 4K
5 resv1 预留用户nvs分区 01 02 00018000 00048000 288K
6 ota_0 OTA app 00 10 00060000 001d0000 1.81M
7 ota_1 OTA app 00 11 00230000 001d0000 1.81M
SDK数据区:存储SDK内部运行时信息
出厂烧录信息:包含用户烧录信息 和 用户PIN码区, 主要存储设备证书、PIN码等 预留用户nvs分区: 预留给用户使用,用户可使用ESP32平台的API访问。
4. 用户实现的函数
- HeyThings SDK回调函数设置
/**
* @brief : callback function implement by user app.
*/
static oc_handler_t handler = {
.cmd_set_handle = cmd_set_user_cb, //属性设置处理
.cmd_array_add_handle = cmd_array_add_user_cb, //数组类型属性添加元素
.cmd_array_del_handle = cmd_array_del_user_cb, //数组类型属性删除元素
.cmd_array_update_handle = cmd_array_update_user_cb,//数组类型属性更新元素
.cmd_action_call = cmd_action_call_cb, //设备动作处理
.cmd_get_cmd_cb = cmd_get_user_cb, //属性获取处理
.dev_provision_confirm = wait_user_confirm_cb, //业务层确认配网回调处理
.event_handle = demo_user_event_handle, //SDK状态事件处理
.init_complete_cb = init_complete_cb_func //SDK初始化完成回调
};
- 属性操作的回调实例,用户可以直接使用,只需完成实际设备操作
/**
* @brief entry function to handle service.light
* @param siid [service id]
* @param iid [property id]
* @param properties [property data]
* @return int [handle result, 0 on success; -1 on error]
*/
int service_light_cmd_set_handle(int siid, int iid, void* properties)
{
Iot__Service__Light__Properties* p = (Iot__Service__Light__Properties*)properties;
int ret = 0;
int field_index = get_field_index_by_iid(ServiceLight, IID_CNT, iid);
if(field_index < 0) {
printf("ERROR: not find this iid in the service. siid=%d iid=%d\n", siid, iid);
return -1;
}
printf("in service_light_cmd_set_handle siid=%d iid=%d\n", siid, iid);
switch(iid) {
case 1:
/* set switch_ */
// ret = user_handle_set_prop_switch_(siid, p->switch_);
printf("set light switch : %d\n", p->switch_);
serviec_light_property_switch__changed(siid, p->switch_); //demo just response had done
break;
case 2:
/* set brightness */
// ret = user_handle_set_prop_brightness(siid, p->brightness);
break;
case 3:
// ret = user_handle_set_prop_colortemperature(siid, p->colortemperature);
break;
case 4:
// ret = user_handle_set_prop_workmode(siid, p->lightmode);
break;
case 5:
// ret = user_handle_set_autoColorTemperature(siid, p->autocolortemperature);
break;
case 6:
if(p->colorrgb) {
// ret = user_handle_set_prop_rgb(siid, p->colorrgb);
} else {
printf("ignore this cmd, rgb is empty\n");
}
break;
case 7:
// ret = user_handle_set_colorSaturation(siid, p->colorsaturation);
break;
case 8:
//reserved.
break;
case 9:
// ret = user_handle_set_prop_autobrightness(siid, p->autobrightness);
break;
case 10:
// ret = user_handle_set_prop_lightlanguagemode(siid, p->lightlanguagemode);
break;
default:
break;
}
return ret;
}
- 状态通知的接口示例,各属性变化,调用相应的接口函数通知到SDK
/**
* @brief notify sdk the property.switch_ changed, sdk will notify all observer
* @param siid [service id]
* @param switch_ [switch state]
*/
void serviec_light_property_switch__changed(int siid, int switch_)
{
Iot__Service__Light__Properties tmp_light = IOT__SERVICE__LIGHT__PROPERTIES__INIT;
tmp_light.switch_ = switch_;
//save new value.
struct light_service_instance* p_instance = get_light_instance_by_siid(siid);
if(p_instance) {
p_instance->service.switch_ = switch_;
}
inner_service_light_property_change(siid, ServiceLight[0].iid, &tmp_light);
printf("report : sii=%d (%s) = %d\n", siid, iid_string(ServiceLight[0].iid), switch_);
}
- 用户应用层入口函数,提供回调函数,启动SDK主循环
/**
* @brief The appliction entry function to calls IoT WiFi SDK
* @return int [start result]
*/
int user_sdk_main(void)
{
int ret;
printf("user app start. build at %s %s.\n", __DATE__, __TIME__);
start_uart_debug_cli();
// start iot wifi sdk and will never exit.
ret = iot_sdk_start(&iot_sdk_callback_handler, dev_odos, secert_mode, &g_dev_info);
if(ret < 0) {
// here means iot_sdk_start has fail.
printf("FATAL ERROR, reboot after 10 seconds.\n");
}
return -1;
}
5. 代码编译
乐鑫esp-idf平台下使用idf.py编译。
学习使用esp-idf
ESP-IDF是ESP32芯片的官方开发框架,新版本的ESP8266也已经使用该框架。关于esp-idf的基础开发环境搭建及其SDK的使用说明请参考ESP官方文档资源。
https://github.com/espressif/esp-idf
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/index.html
在可以编译烧录并运行乐鑫SDK的example(如get-started/hello_world)后再来编译使用本例程。
使用idf.py工具编译烧录
HeyThings SDK APP demo在ESP平台下使用的是其cmake编译系统,编译工具为idf.py
。
编译调试的路径:HeyThings_SDK_app_demo
cd
到该路径下,执行命令
编译:idf.py build
运行:idf.py flash
查看:idf.py monitor
或者组合命令:idf.py build flash monitor