RTOS SDK对接
本文档描述智能家居插件在 RTOS 平台 SDK 的对接方式。 RTOS 版本以 静态库 libjdsmart_demo.a 的形式,在编译期直接链接进固件运行。
对接完成后即可支持:设备登录、发现设备、控制设备、以及设备状态反馈。
| 版本 | 改动记录 |
|---|---|
| V1.0.0 | 初始版本 |
| V1.1.0 | 补充设备品类与子类说明;完善协议、事件、组包 API 与指令集描述;新增平台工具接口(HTTP / MD5 / MQTT / UART) |
智能家居 SDK 对接方式,适用于有嵌入式 C 开发能力的公司,可支持设备登录、发现设备、控制设备以及设备状态反馈。
demo插件源码 点击下载
一. 工程结构
libdemo/
├── Makefile # RTOS 静态库编译脚本(riscv64-unknown-elf 工具链)
├── libjdsmart_demo.a # 编译产物:静态库
├── include/ # 对接头文件
│ ├── device_sdk_plugin.h # 插件 API / 设备类型 / 属性 / 动作 / 事件定义
│ ├── device_sdk_music.h # 音乐播放及设备状态反馈命令定义,目前未使用,不用管
│ ├── smarthome_packet.h # 设备发现协议的组包 API
│ ├── smarthome_common.h # 平台数据目录宏(含 OS_RTOS)
│ ├── smarthome_priv.h # 私有结构体:device_info_t / 设备映射表
│ ├── cJSON.h # JSON 解析/生成
│ └── tkc/ # 基础工具库(动态数组、字符串、内存等)
├── src/
│ ├── smarthome_demo.c # 对接实现(需实现的核心业务代码)
│ ├── smarthome_packet.c # 组包 API 实现
│ └── smarthome_utils.h # 平台工具函数声明(demo 未使用,无需关注)
└── smarthome_utils/ # 预留目录(libdemo 中为空,无需关注)
对接方需要重点关注 include/ 下的头文件与 src/smarthome_demo.c。所有 smarthome_xxx() 函数即为 SDK 约定的对接接口。
二. 编译环境
RTOS 版本使用 Makefile 构建,产物为静态库 libjdsmart_demo.a。工具链在 Makefile 首行配置:
全志R128源码编译工具链路径 点击下载
COMPILE_PREX := /home/virtual_tmp/mm/riscv64-elf-x86_64-20201104/bin/riscv64-unknown-elf-
CC := $(COMPILE_PREX)gcc
AR := $(COMPILE_PREX)ar
# 自动收集 src 下所有 .c/.cpp/.cc 源文件
LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH)/src -name "*.c" -o -name "*.cpp" -o -name "*.cc")
# 目标:静态库,使用 $(AR) 打包(而非动态库的链接)
all: libjdsmart_demo.a rm_objs
libjdsmart_demo.a: $(OBJS)
$(AR) rcs $@ $^
%.o:%.c
$(CC) -Wall -c $(CFLAGS) $< -o $@
对接步骤:
- 将
COMPILE_PREX修改为实际使用的 RISC-V 交叉编译器路径前缀; - 执行
make(或make PLATFORM=tina以启用 Tina 平台相关宏),生成libjdsmart_demo.a; - 在固件工程中链接该静态库,并把
include/目录加入头文件搜索路径。
三. 对接流程
smarthome_preinit() 预初始化:保存回调 listener,解析入参
│
smarthome_init() 初始化:解析 deviceID,创建设备列表,启动加载线程
│
smarthome_get_state() 中控查询插件状态(IDLE / LOGGED ...)
smarthome_get_pluginfo() 中控获取插件信息(appid、登录方式、flag 等)
│
├──► listener(PLUGIN_EVENT_ON_DEVICES_SYNC) 上报设备列表(发现协议)
│
smarthome_device_control() 中控下发控制指令 → 操作硬件 → 反馈状态
│
├──► listener(PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE) 上报属性变化
│
smarthome_reset() 重置 / 解除绑定
核心思想:中控通过调用 smarthome_xxx() 接口驱动插件;插件通过 listener 回调把设备列表、状态、属性变化上报给中控。
从用户视角看,整体演示流程为:
登录 → 发现设备及场景 → 显示设备及场景 → 界面点击或语控场景及设备
设备发现完成后,即可在桌面左屏看到设备、右屏看到场景,然后点击或语音控制设备或场景。
四. API 说明
对接插件需要实现如下函数,函数原型定义于 include/device_sdk_plugin.h,参考实现见 src/smarthome_demo.c。
回调函数类型:
typedef void (*callback_func)(void* context, int code, void* result);
4.1 smarthome_preinit — 预初始化
最早被调用,用于保存应用层回调 listener(需本地长期保存,后续所有上报都通过它),并解析入参。
/**
* @brief 预初始化
* @param params: {"feature":0, "switchs_count":2}
* @param listener: 应用层回调函数,需本地保存
*/
int smarthome_preinit(char* params, callback_func listener);
参考实现(smarthome_demo.c):
int smarthome_preinit(char* params, callback_func listener) {
g_context = (smarthome_context_t*)malloc(sizeof(smarthome_context_t));
memset(g_context, 0, sizeof(smarthome_context_t));
g_context->listener = listener; // 关键:保存回调
if (params && strlen(params) > 0) {
cJSON* root = cJSON_Parse(params);
if (root != NULL) {
cJSON *obj = cJSON_GetObjectItem(root, "switchs_count");
if (obj) g_context->switchs_count = obj->valueint;
cJSON_Delete(root);
}
}
return 0;
}
4.2 smarthome_init — 初始化
解析本机 deviceID,创建设备容器,并启动设备加载流程。
/**
* @param params: {
* "uuid": "AIS后台绑定的插件设备id",
* "key": "AIS后台绑定的插件设备key",
* "deviceID": "本机设备唯一ID"
* }
*/
int smarthome_init(char* params, callback_func listener);
参考实现:
int smarthome_init(char* params, callback_func listener) {
g_context->devices = darray_create(50, (tk_destroy_t)plug_device_destroy, plug_device_compare);
cJSON* root = cJSON_Parse(params);
if (root != NULL) {
cJSON* jobj_deviceID = cJSON_GetObjectItem(root, "deviceID");
strncpy(g_context->device_id, jobj_deviceID->valuestring, sizeof(g_context->device_id) - 1);
cJSON_Delete(root);
} else {
return -1;
}
pthread_t t1;
pthread_create(&t1, NULL, &smart_demo_start, NULL); // 异步加载设备
return 0;
}
说明:平台支持 pthread,在任务/线程中调用
parse_config_file()加载设备,加载完成后置状态为PLUGIN_STATE_LOGGED并调用notify_devices_change()上报设备列表。demo 中uuid/key为 AIS 后台绑定预留(authType为 none 时不用),当前仅使用deviceID。
4.3 smarthome_get_state — 获取状态
返回当前插件状态,供中控判断登录/加载进度。
int smarthome_get_state();
返回值取自 enum SS_PLUGIN_STATE:
| 状态 | 值 | 含义 |
|---|---|---|
| PLUGIN_STATE_FAIL | -1 | 失败 |
| PLUGIN_STATE_IDLE | 0 | 空闲 |
| PLUGIN_STATE_INITED | 1 | 已初始化 |
| PLUGIN_STATE_GET_CODE | 2 | 获取二维码 |
| PLUGIN_STATE_GET_TOKEN | 3 | 获取 token |
| PLUGIN_STATE_LOGGED | 4 | 已登录 |
| PLUGIN_STATE_BINDED | 5 | 已绑定 |
4.4 smarthome_get_pluginfo — 获取插件信息
返回一段 JSON 字符串,描述插件版本、appid、登录方式、登录提示语及功能 flag。
char* smarthome_get_pluginfo();
参考实现:
char* smarthome_get_pluginfo() {
cJSON* root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "version", PLUGIN_PROTOCOL_VERSION);
cJSON_AddStringToObject(root, "appid", "xxx.com"); // 厂商 appid,建议为域名
cJSON_AddNumberToObject(root, "state", g_context->state);
cJSON_AddStringToObject(root, "authType", AUTH_TYPE_NONE); // 授权类型, 保持, 不要修改
cJSON_AddStringToObject(root, "loginType", LOGIN_TYPE_QRCODE); // 登录方式
cJSON_AddStringToObject(root, "loginTitle", "设备绑定");
cJSON_AddStringToObject(root, "loginHint", "手机APP扫一扫");
if (g_context->qr_url && strlen(g_context->qr_url) > 0)
cJSON_AddStringToObject(root, "loginUrl", g_context->qr_url);
int flag = 0;
flag |= PLUG_FLAG_LOAD_OFFLINE; // 支持离线加载
cJSON_AddNumberToObject(root, "flag", flag);
char* info = cJSON_PrintUnformatted(root);
cJSON_Delete(root);
return info; // 调用方负责 free
}
flag 标志位定义(可按需组合):
| 标志 | 说明 |
|---|---|
| PLUG_FLAG_LOAD_OFFLINE | 支持离线加载 |
| PLUG_FLAG_STATE_FEEDBACK | 开关按钮待设备状态反馈后再改变 |
| PLUG_FLAG_SMART_BUS | 插件占用 RS485 设备,用于 485 插件对接开发 |
| PLUG_FLAG_NO_SMART_BUS | 禁用 RS485 相关 UI 显示 |
| PLUG_FLAG_PAIRD_DEVICES | 插件含设备发现并自动配对功能 |
另外支持两个可选项(demo 中有注释示例):
| 字段 | 说明 |
|---|---|
| custom_model | 自定义设备名称,最长 32 字节,在"设置 > 关于本机 > 设备名称"处显示 |
4.5 smarthome_device_control — 设备控制
中控下发控制指令时调用。入参为 JSON,需解析后驱动实际硬件,并回调上报执行结果与属性变化。
/**
* @param params: {
* "id":"vdevo161103533857949", // 设备id
* "type":"aircondition", // 设备类型
* "sub_type":"unknown", // 设备子类型
* "action":"SetTemperature", // 动作
* "value":"19" // 值
* }
* @param callback: (void* context, int code, void* result)
* code: 0 正常, -1 异常; 异常时 result 传文本用于显示
*/
int smarthome_device_control(const char* params, callback_func callback);
参考实现(以灯具为例,展示解析 → 驱动 → 反馈的完整链路):
int smarthome_device_control(const char* params, callback_func callback) {
cJSON* root = cJSON_Parse(params);
if (root != NULL) {
char* id = cJSON_GetObjectItem(root, "id")->valuestring;
device_info_t *device = find_device_by_id(id);
if (device) {
char* action = cJSON_GetObjectItem(root, "action")->valuestring;
char* type = cJSON_GetObjectItem(root, "type")->valuestring;
char* value = NULL;
cJSON *jobj = cJSON_GetObjectItem(root, "value");
if (jobj) value = jobj->valuestring;
if (my_streq(type, DEVICE_TYPE_LIGHT)) {
if (my_streq(action, DEVICE_ACTION_TURN_ON)) {
// leshi_ble_set_onoff(...); // 调用实际硬件驱动
device->status = 1;
notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_POWERSTATE,
DEVICE_PROPERTIES_VALUE_ON);
} else if (my_streq(action, DEVICE_ACTION_SET_BRIGHTNESS)) {
device->data.light.brightness = atoi(value);
notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_BRIGHTNESS, value);
} else if (my_streq(action, DEVICE_ACTION_SET_COLOR_TEMPERATURE)) {
device->data.light.color_temp = atoi(value);
int max = 6400, min = 2700;
int dst = (max - min) * device->data.light.color_temp / 100 + min; // 百分比转开尔文
notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_COLOR_TEMPERATURE, value);
}
}
// ... 空调 / 窗帘 / 开关 / 浴霸 / 风扇灯 等类型见源码
}
cJSON_Delete(root);
}
return 0;
}
src/smarthome_demo.c中已给出 light、switch、aircondition、curtain、bath_heater、music_player、hanger、fan 等设备类型的完整控制分支,对接时把其中注释掉的leshi_ble_xxx()替换为自有硬件驱动即可。
4.6 smarthome_device_discover — 发现设备
int smarthome_device_discover(int method, callback_func callback);
中控需要刷新设备列表时调用(初始化加载流程中也会调用一次)。method、callback 为预留参数,demo 中为空实现。
说明:RTOS 版设备的加载在
smarthome_init启动的线程中完成。设备列表发生变化时(增加/删除设备、改名等),插件应主动通过PLUGIN_EVENT_ON_DEVICES_SYNC重新上报完整设备列表,无需等待中控调用本接口。
4.7 smarthome_reset — 重置 / 解除绑定
int smarthome_reset();
参考实现:
int smarthome_reset() {
g_context->state = PLUGIN_STATE_IDLE;
notify_gw_status(PLUGIN_STATE_IDLE, "网关已重置");
return 0;
}
解除绑定/退出登录时通常需要重启应用,可调用
g_listener(NULL, PLUGIN_EVENT_REQ_REBOOT, NULL);。
4.8 smarthome_ioctl — 扩展命令
用于设备发现、调试信息、产测等扩展场景。
int smarthome_ioctl(char* cmd, char* key, char* value);
支持的 cmd(见源码):
| cmd | 说明 |
|---|---|
| discovery_device | 进入设备发现(需设置 PLUG_FLAG_PAIRD_DEVICES) |
| discovery_device_exit | 退出发现界面 |
| get_debug_info | 返回调试信息(纯文本或输入对话框,通过 PLUGIN_EVENT_ON_DEBUG_INFO 上报) |
| test_mode_start | 启动产测,通过 PLUGIN_EVENT_ON_TEST_RESULT 返回结果 |
4.9 smarthome_slave_report — 子设备状态上报
插件作为子设备时,把按键、继电器等硬件事件上报给中控/服务器。
int smarthome_slave_report(const char* params, callback_func callback);
params 中 i0 为命令字,取值定义于 device_sdk_music.h(如 DEVICE_REPORT_KEY_EVENT=254 按键事件、DEVICE_REPORT_DEVICE_PROP=250 属性上报)。
参考实现(按键事件):
int smarthome_slave_report(const char* params, callback_func callback) {
cJSON* root = cJSON_Parse(params);
if (root != NULL) {
int cmd = cJSON_GetObjectItem(root, "i0")->valueint;
switch (cmd) {
case DEVICE_REPORT_KEY_EVENT: {
unsigned char did = cJSON_GetObjectItem(root, "i1")->valueint;
device_info_t *device = find_device_by_type_id(LETS_OEM_ZHINENG_SW, did);
if (device && device->data.smart_switch.mode == LETS_SWITCH_MODE_NORMAL) {
device->status = !device->status;
slave_on_dp_cb(device->id - 1 + DEVICE_SWICTH_1, device->status); // 操作继电器
notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_POWERSTATE,
device->status ? DEVICE_PROPERTIES_VALUE_ON : DEVICE_PROPERTIES_VALUE_OFF);
}
} break;
default: break;
}
cJSON_Delete(root);
}
return 0;
}
五. 回调事件(listener)
插件通过 listener(context, event, result) 向中控上报事件,事件定义于 enum SS_PLUGIN_EVENT:
| 事件 | 值 | 说明 | result 内容 |
|---|---|---|---|
| PLUGIN_EVENT_ON_GW_RESET | 1 | 网关重置 | - |
| PLUGIN_EVENT_ON_GW_STATUS | 2 | 网关/登录状态变化 | plugin_ret_t{code,msg} |
| PLUGIN_EVENT_ON_GW_URL | 3 | 网关 URL | URL 字符串 |
| PLUGIN_EVENT_ON_DEVICES_SYNC | 4 | 上报设备列表 | 发现协议 JSON 字符串(见 7.2) |
| PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE | 5 | 设备属性变化 | 属性 JSON 字符串(见 7.3) |
| PLUGIN_EVENT_ON_DEVICE_DISCOVERY | 6 | 设备发现进度提示 | {"version":1,"msg":"正在搜索..."} |
| PLUGIN_EVENT_ON_DEBUG_INFO | 7 | 调试信息/输入对话框 | JSON |
| PLUGIN_EVENT_REQ_REBOOT | 1000 | 请求重启应用 | NULL |
| PLUGIN_EVENT_SLAVE_CONTROL | 1001 | 子设备继电器控制 | {"i0":..,"i1":..} |
| PLUGIN_EVENT_ON_VOICE_RESP | 1002 | 语音应答 | 预留 |
| PLUGIN_EVENT_ON_CLOCK_UPDATE | 1003 | 闹钟更新 | 预留 |
| PLUGIN_EVENT_ON_UI_TOAST | 1004 | UI 提示 | {"version":1,"msg":"..."} |
| PLUGIN_EVENT_ON_HOTEL_RESET | 1005 | 酒店模式重置 | 预留 |
| PLUGIN_EVENT_ON_TEST_RESULT | 1006 | 产测结果 | >0 成功 / <0 失败 |
| PLUGIN_EVENT_ON_UI_DIALOG | 1007 | UI 对话框 | JSON |
| PLUGIN_EVENT_ON_UI_STRING | 1008 | UI 字符串 | JSON |
demo 中实际使用的事件:ON_GW_STATUS、ON_DEVICES_SYNC、ON_DEVICE_PROP_CHANGE、ON_DEVICE_DISCOVERY、ON_DEBUG_INFO、ON_UI_TOAST、ON_TEST_RESULT、SLAVE_CONTROL、REQ_REBOOT;其余为预留。
上报网关状态:
static void notify_gw_status(int code, char* msg) {
plugin_ret_t ret;
ret.code = code;
ret.msg = msg;
g_context->listener(NULL, PLUGIN_EVENT_ON_GW_STATUS, &ret);
}
上报属性变化:
static void notify_prop_change(char *id, char *prop, const char *value) {
char* tmpl = "{\"version\":1,\"deviceId\":\"%s\",\"name\":\"%s\",\"value\":\"%s\"}";
char result[160];
snprintf(result, 160, tmpl, id, prop, value);
g_context->listener(NULL, PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE, result);
}
也可使用组包库中的 smarthome_packet_smart_prop(id, name, value) 生成同样的 JSON(见第六章)。
上报设备列表(组包 + 同步):
static void notify_devices_change() {
if (g_context->listener == NULL) return;
smarthome_packet_devicelist_t* packet_devicelist = smarthome_packet_devicelist_new();
convert_devices_pack(g_context, packet_devicelist); // 遍历本地设备组包
char* result = smarthome_packet_devicelist_pack(packet_devicelist);
free(packet_devicelist);
g_context->listener(NULL, PLUGIN_EVENT_ON_DEVICES_SYNC, result);
if (result != NULL) free(result);
}
六. 设备组包 API
smarthome_packet.h / smarthome_packet.c 提供了一套基于 cJSON 的组包接口,用于生成"设备发现协议" JSON,避免手工拼接字符串。
| API | 说明 |
|---|---|
| smarthome_packet_devicelist_new() | 创建设备列表容器 |
| smarthome_packet_devicelist_add_device(devlist, dev) | 把设备加入列表(dev 所有权转移,内部会释放,勿重复 free) |
| smarthome_packet_devicelist_pack(devlist) | 打包为 JSON 字符串(含 version/name/devices,调用方负责 free) |
| smarthome_packet_device_new_object(id, name, online) | 创建单个设备对象(自动带 actions/properties 数组) |
| smarthome_packet_device_set_type(dev, type) | 设置设备类型(deviceType) |
| smarthome_packet_device_set_sub_type(dev, sub_type) | 设置设备子类型(deviceSubType),可选 |
| smarthome_packet_device_set_zone(dev, zone) | 设置房间名(zone),可选 |
| smarthome_packet_device_add_action(dev, action) | 添加动作 |
| smarthome_packet_device_create_action_instructions(dev, action) | 添加带枚举的动作,返回 instructions 数组 |
| smarthome_packet_device_append_action_instruction(instr, value, desc) | 向 instructions 追加一个枚举项(code 与 value 相同) |
| smarthome_packet_device_add_property(dev, name, value) | 添加属性 |
| smarthome_packet_device_delete_object(dev) | 释放设备对象(add_device 之后由内部调用) |
| smarthome_packet_smart_prop(id, name, value) | 组装单条属性变化 JSON(属性上报用) |
组包示例(空调设备,含模式/风速枚举),摘自 convert_devices_pack():
case DEVICE_AIR_CONDITION:
device_type = DEVICE_TYPE_AIRCONDITION;
smarthome_packet_device_add_action(dev_pack, DEVICE_ACTION_TURN_ON);
smarthome_packet_device_add_action(dev_pack, DEVICE_ACTION_TURN_OFF);
// SetMode 动作 + 枚举项
instructions = smarthome_packet_device_create_action_instructions(dev_pack, DEVICE_ACTION_SET_MODE);
for (int i = 0; i < sizeof(MAP_AIS_DEMO_MODE)/sizeof(map_smart_ais_demo_t); i++) {
map_smart_ais_demo_t *m = &MAP_AIS_DEMO_MODE[i];
if (m->key == NULL) break;
smarthome_packet_device_append_action_instruction(instructions, m->key, m->desc);
}
smarthome_packet_device_add_property(dev_pack, DEVICE_PROPERTIE_POWERSTATE, DEVICE_PROPERTIES_VALUE_OFF);
smarthome_packet_device_add_property(dev_pack, DEVICE_PROPERTIE_TEMPERATURE, "16");
smarthome_packet_device_add_property(dev_pack, DEVICE_PROPERTIE_WINDSPEED, DEVICE_WINDSPEED_AUTO);
break;
七. 协议描述
7.1 对接基本要求
- 能够提供所有设备列表数据,设备信息中包含设备 ID、设备名、设备类型;
- 能够提供所有场景列表数据,场景信息中包含场景 ID、场景名;
- 能够提供所有房间列表数据,房间信息中包含房间 ID、房间名。
7.2 设备发现协议
由 notify_devices_change() 通过 PLUGIN_EVENT_ON_DEVICES_SYNC 上报。根字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| version | int | 协议版本,固定为 1 |
| name | string | 固定为 "DiscoveryDevicesResponse" |
| devices | array | 设备对象数组 |
设备对象字段:
| 字段 | 必填 | 说明 |
|---|---|---|
| deviceId | 是 | 设备唯一 ID。demo 约定 类型:序号:校验 的十六进制格式(如 08:01:03),中控按 : 分段解析 |
| deviceName | 是 | 设备名称,同时用于语音匹配,建议使用"房间+设备"或常用说法,如"客厅灯" |
| online | 是 | 1 在线 / 0 离线 |
| deviceType | 是 | 设备类型,见第八章 |
| deviceSubType | 否 | 设备子类型,见 8.x 各品类说明(多路开关必填) |
| zone | 否 | 房间名,如"客厅" |
| icon / iconPath | 否 | 图标 |
| actions | 是 | 支持的动作数组,决定中控面板形态与语音支持范围 |
| actions[].action | 是 | 动作名,见 9.1 |
| actions[].instructions | 否 | 动作枚举项(模式、风速等离散值动作需要) |
| instructions[].value / code | 是 | 枚举值,控制时作为 value 原样下发 |
| instructions[].desc | 是 | 枚举描述(如"制冷"),用于语音与界面显示 |
| properties | 否 | 属性数组 {name, value},上报当前状态初始值 |
上报示例:
{
"version": 1,
"name": "DiscoveryDevicesResponse",
"devices": [
{
"deviceId": "vdevo162130282208556",
"deviceName": "彩光灯",
"online": 1,
"actions": [
{ "action": "TurnOn" },
{ "action": "TurnOff" },
{
"action": "SetMode",
"instructions": [
{ "value": "lightWhite", "code": "lightWhite", "desc": "白光" },
{ "value": "lightColour", "code": "lightColour", "desc": "彩光" },
{ "value": "lightScene", "code": "lightScene", "desc": "情景" }
]
},
{ "action": "SetBrightness" },
{ "action": "SetColorTemperature" },
{ "action": "SetColor" },
{
"action": "SetScene",
"instructions": [
{ "value": "light_scene_1", "code": "light_scene_1", "desc": "晚安" },
{ "value": "light_scene_2", "code": "light_scene_2", "desc": "阅读" }
]
}
],
"properties": [
{ "name": "powerstate", "value": "on" },
{ "name": "mode", "value": "lightWhite" },
{ "name": "brightness", "value": "18" },
{ "name": "color_temperature","value": "10" },
{ "name": "color_hsv", "value": "{\"h\":0,\"s\":0,\"v\":1}" }
],
"zone": "阳台",
"deviceType": "light",
"deviceSubType": "unknown"
},
{
"deviceId": "SN8hzCSAbWrCtjIE",
"deviceName": "晨起",
"deviceType": "smartscene",
"actions": [ { "action": "TurnOn" } ]
}
]
}
7.3 设备响应协议
设备属性变化时,通过 PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE 上报,格式:
| 字段 | 说明 |
|---|---|
| version | 固定为 1 |
| deviceId | 设备 ID |
| name | 属性名,见 9.2 |
| value | 属性值 |
{ "version": 1, "deviceId": "vdevo162088709984066#1", "name": "online", "value": "1" }
常见控制/反馈示例:
// 电源状态
{ "version":1, "deviceId":"vdevo162088709984066#1", "name":"powerstate", "value":"on" }
// 亮度(0~100)
{ "id":"vdevo162192408876410", "type":"light", "sub_type":"", "action":"SetBrightness", "value":"53" }
// 颜色(h:0~360, s:0~1, v:0~1)
{ "id":"vdevo162130282208556", "type":"light", "sub_type":"", "action":"SetColor",
"value":"{\"h\":359.37,\"s\":0.75,\"v\":1}" }
// 色温(0~100)
{ "id":"vdevo161847485227864", "type":"light", "sub_type":"", "action":"SetColorTemperature", "value":"50" }
// 空调温度
{ "id":"vdevo161103533857949", "type":"aircondition", "sub_type":"", "action":"SetTemperature", "value":"20" }
// 空调风速
{ "id":"vdevo161103533857949", "type":"aircondition", "sub_type":"", "action":"SetWindSpeed", "value":"low" }
// 模式
{ "version":1, "deviceId":"vdevo161103533857949", "name":"mode", "value":"heat" }
// 摆风(switch_horizontal 左右,switch_vertical 上下)
{ "version":1, "deviceId":"vdevo161103533857949", "name":"switch_horizontal", "value":"on" }
八. 支持的设备品类
中控按 设备类型(deviceType)→ 设备子类型(deviceSubType)→ 上报的动作(actions) 三级来识别设备、渲染对应控制面板并支持语音控制。对接方按实际硬件能力上报对应的类型、子类型与动作即可。
8.1 智能设备类
设备类型宏定义于 include/device_sdk_plugin.h。demo 中各品类的组包逻辑见 convert_devices_pack(),控制分支见 smarthome_device_control()。
| 名称 | 功能 | 宏 | 类型 | 子类型 |
|---|---|---|---|---|
| 灯具 | 开关、亮度、冷暖(色温)、彩光、情景模式 | DEVICE_TYPE_LIGHT | light | 按动作区分子类(见 8.1.1) |
| 开关 | 开关;多路开关支持分路控制 | DEVICE_TYPE_SWITCH | switch | 单路 / switchs_2 ~ switchs_6 |
| 插座 | 开关 | DEVICE_TYPE_OUTLET | outlet | 同开关,多孔可用 switchs_N |
| 排插 | 开关 | DEVICE_TYPE_SOCKETS | sockets | 同开关,多孔可用 switchs_N |
| 窗帘 | 打开、关闭、暂停、百分比、角度 | DEVICE_TYPE_CURTAIN | curtain | 按动作区分子类(见 8.1.4) |
| 空调 | 开关、温度、模式、风速、摆风 | DEVICE_TYPE_AIRCONDITION | aircondition | 空调 / temperature_ctrl 温控器 / floor_heat 地暖 |
| 浴霸 | 开关、照明、换气/送风/睡眠、风量 | DEVICE_TYPE_BATH_HEATER | bath_heater | |
| 音乐播放器 | 播放、暂停、切歌、音量调节 | DEVICE_TYPE_MUSIC_PLAYER | music_player | |
| 晾衣架 | 升降、暂停、照明 | DEVICE_TYPE_HANGER | hanger | |
| 风扇(风扇灯) | 风扇开关、照明、摆风、风速 | DEVICE_TYPE_FAN | fan | |
| 场景 | 场景执行 | DEVICE_TYPE_SMARTSCENE | smartscene |
8.1.1 灯具(light)
灯具不使用 deviceSubType 区分,中控根据上报的动作组合识别灯具子类,并显示对应的控制面板:
| 子类 | 需上报的动作 | 控制面板 |
|---|---|---|
| 普通灯(仅开关) | TurnOn / TurnOff | 单开关 |
| 调光灯 | 再上报 SetBrightness | 亮度滑条 |
| 色温灯 | 再上报 SetColorTemperature | 亮度 + 色温 |
| 彩光灯 | 再上报 SetColor | 彩光(HSV)面板 |
| 情景灯 | 再上报 SetScene(配合 mode 属性) | 情景模式 |
| 动作 | value | 说明 |
|---|---|---|
| TurnOn / TurnOff | 无 | 开灯 / 关灯 |
| SetBrightness | 0~100 | 设置亮度,回读 brightness |
| AdjustUpBrightness / AdjustDownBrightness | 无 | 亮度 ±10 |
| SetColorTemperature | 0~100 | 色温百分比,按 colortemp_range_min~max 线性换算为开尔文(demo 为 2700K~6400K) |
| AdjustUpColorTemperature / AdjustDownColorTemperature | 无 | 色温 ±10 |
| SetColor | {"h":0~360,"s":0~1,"v":0~1} |
HSV 彩光 |
| SetScene | light_scene_N(如 light_scene_1 晚安) | 情景模式,见 7.2 示例,demo 控制分支未实现,可按需扩展 |
反馈属性:powerstate(on/off)、brightness(0~100)、color_temperature(0~100)、color_hsv、mode(lightWhite 白光 / lightColour 彩光 / lightScene 情景)。
组包时通过
colortemp_range_min/colortemp_range_max/colortemp_range_step属性告知中控色温范围(见 7.2 示例)。
8.1.2 开关(switch)
按 deviceSubType 区分子类:
| 子类 | 说明 | 控制方式 |
|---|---|---|
| 不上报 / switchs_1 | 单路开关 | TurnOn / TurnOff,反馈 powerstate |
| switchs_2 ~ switchs_6 | N 路开关,中控显示 N 位面板 | SetSwitchN(N 为第几路,value 取 on/off),反馈 switchsN 与 powerstate |
| 自身开关(本地类型 LETS_OEM_ZHINENG_SW) | 走本机继电器 | 同单路;通过 ais_relay 属性标识对应继电器路数 |
多路开关组包时需通过属性 subdev_name_switch_1 ~ subdev_name_switch_N 上报各按键名称;设置 switchs_ 子类型后面板上不显示总电源键,中控按 N 路自动生成各路开关,无需上报 TurnOn/TurnOff 动作。
多路开关组包示例(以二路开关为例):
smarthome_packet_device_t* dev_pack = smarthome_packet_device_new_object("b2:02:11", "二路开关", 1);
smarthome_packet_device_set_type(dev_pack, DEVICE_TYPE_SWITCH);
smarthome_packet_device_set_sub_type(dev_pack, "switchs_2"); // 关键:N 路填 switchs_N
// 各按键名称(可选,用于界面显示与语音匹配)
smarthome_packet_device_add_property(dev_pack, "subdev_name_switch_1", "开关一键");
smarthome_packet_device_add_property(dev_pack, "subdev_name_switch_2", "开关二键");
smarthome_packet_device_add_property(dev_pack, DEVICE_PROPERTIE_POWERSTATE, DEVICE_PROPERTIES_VALUE_OFF);
smarthome_packet_devicelist_add_device(devlist, dev_pack);
对应上报的发现协议 JSON:
{
"deviceId": "b2:02:11",
"deviceName": "二路开关",
"online": 1,
"deviceType": "switch",
"deviceSubType": "switchs_2",
"properties": [
{ "name": "subdev_name_switch_1", "value": "开关一键" },
{ "name": "subdev_name_switch_2", "value": "开关二键" },
{ "name": "powerstate", "value": "off" }
]
}
中控下发的控制指令(smarthome_device_control() 的 params,动作为 SetSwitch + 路数,value 取 on/off):
{ "id":"b2:02:11", "type":"switch", "sub_type":"switchs_2", "action":"SetSwitch1", "value":"on" }
{ "id":"b2:02:11", "type":"switch", "sub_type":"switchs_2", "action":"SetSwitch2", "value":"off" }
控制分支参考实现(解析路数 → 操作硬件 → 反馈分路与总电源状态):
} else if (!strncmp(action, "SetSwitch", strlen("SetSwitch"))) { // 多路开关
int index = atoi(action + strlen("SetSwitch")); // 第几路,从 1 开始
unsigned char is_on = my_streq(value, DEVICE_PROPERTIES_VALUE_ON);
// 按位记录各路状态(device->status 的 bit0~bitN 对应第 1~N 路)
if (is_on) {
device->status |= 1 << (index - 1);
} else {
device->status &= ~(1 << (index - 1));
}
// TODO: 操作实际硬件,如继电器
// leshi_ble_set_data_short(LETS_OEM_86_SW, did + (index - 1), seq + (index - 1), 1, is_on);
// 反馈分路状态:属性名为 switchs + 路数(switchs1、switchs2 ...)
char prop_id[12] = {0};
snprintf(prop_id, sizeof(prop_id), "switchs%d", index);
notify_prop_change(device->device_id.str, prop_id,
is_on ? DEVICE_PROPERTIES_VALUE_ON : DEVICE_PROPERTIES_VALUE_OFF);
// 反馈总电源状态:任一路为 on 即 on
notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_POWERSTATE,
device->status ? DEVICE_PROPERTIES_VALUE_ON : DEVICE_PROPERTIES_VALUE_OFF);
}
对应的属性反馈:
{ "version":1, "deviceId":"b2:02:11", "name":"switchs1", "value":"on" }
{ "version":1, "deviceId":"b2:02:11", "name":"powerstate", "value":"on" }
8.1.3 插座(outlet)/ 排插(sockets)
TurnOn / TurnOff,反馈 powerstate。多孔排插可参照多路开关,使用 switchs_N 子类型分路控制(中控对 switch 与 sockets 同样识别 switchs_ 子类型)。宏已在头文件中定义,demo 未提供示例设备,实现方式可参照开关。
8.1.4 窗帘(curtain)
中控根据上报的动作组合识别窗帘子类:
| 子类 | 需上报的动作 | 控制面板 |
|---|---|---|
| 普通窗帘 | TurnOn / TurnOff | 开关式 |
| 带暂停窗帘 | 再上报 Pause | 开 / 关 / 暂停 |
| 带行程窗帘 | 再上报 SetProgress | 百分比滑条 |
| 角度帘(梦幻帘) | 再上报 SetProgress + SetAngle | 行程 + 角度面板 |
| 动作 | value | 说明 |
|---|---|---|
| TurnOn | 无 | 打开窗帘(本地指令 0x00) |
| TurnOff | 无 | 关闭窗帘(本地指令 0x02) |
| Pause | 无 | 暂停(本地指令 0x01) |
| SetProgress | 0~100 | 开合百分比 |
| SetAngle | 0~100 | 叶片角度(角度帘用;宏值 "SetAngle" 未包含在 device_sdk_plugin.h,需自行 #define) |
反馈属性:progress(0~100)、powerstate(progress>0 时为 on)。
8.1.5 空调(aircondition)
按 deviceSubType 区分子类:
| 子类 | deviceSubType | 控制面板 |
|---|---|---|
| 空调 | 不上报 / unknown | 空调面板(温度、模式、风速、摆风) |
| 温控器 | temperature_ctrl | 上报 SetWindSpeed 则显示空调面板,否则显示温控器面板 |
| 地暖 | floor_heat | 温控器面板 |
| 动作 | value | 说明 |
|---|---|---|
| TurnOn / TurnOff | 无 | 开 / 关空调 |
| SetTemperature | 16~32 | 温度(℃),越界自动钳位(MIN_TEMP/MAX_TEMP) |
| AdjustUpTemperature / AdjustDownTemperature | 无 | 温度 ±1℃ |
| SetMode | cold 制冷 / heat 制热 / auto 自动 / airsupply 送风 / dehumidification 除湿 等 | 模式,demo 枚举映射见 MAP_AIS_DEMO_MODE |
| SetWindSpeed | auto 自动 / low 低风 / medium 中风 / high 高风 / strong 强风 等 | 风速,demo 枚举映射见 MAP_AIS_DEMO_WINDSPEED |
反馈属性:powerstate、temperature、mode、windspeed;摆风属性 switch_horizontal(左右)/ switch_vertical(上下),取值 on/off,对应动作 SwitchHorizontal / SwitchVertical。
8.1.6 浴霸(bath_heater)
| 动作 | value | 说明 |
|---|---|---|
| TurnOn / TurnOff | 无 | 开 / 关浴霸 |
| SwitchLight | on / off | 照明灯 |
| SetMode | exhaustWind 排风 / airsupply 送风 / sleep 睡眠 | 换气模式 |
| SetWindSpeed | high 高风 / low 低风 | 风量档位 |
反馈属性:powerstate、switch_light、mode、windspeed。
8.1.7 音乐播放器(music_player)
| 动作 | 说明 |
|---|---|
| TurnOn / TurnOff | 电源 |
| Play / Pause | 播放 / 暂停 |
| Next / Prev | 下一曲 / 上一曲 |
| AdjustUpVolume / AdjustDownVolume | 音量 ± |
反馈属性:powerstate、播放状态(device_sdk_music.h 中定义,当前未使用)。
8.1.8 晾衣架(hanger)
| 动作 | 说明 |
|---|---|
| TurnOn | 上升(收纳) |
| TurnOff | 下降 |
| Pause | 暂停 |
| SwitchLight | on / off 照明灯 |
| SetProgress | 升降位置百分比 |
反馈属性:powerstate、switch_light、progress。demo 控制分支已实现照明 / 暂停 / 进度,升降动作需对接方在 TurnOn / TurnOff 分支中补充硬件驱动。
8.1.9 风扇(fan)
demo 本地类型为风扇灯(LETS_OEM_FAN_LIGHT),风扇与照明一体。
| 动作 | value | 说明 |
|---|---|---|
| TurnOn / TurnOff | 无 | 风扇开 / 关 |
| SwitchLight | on / off | 灯光 |
| SwitchHorizontal | on / off | 左右摆风 |
| SetWindSpeed | auto / low / medium / high / strong | 风速 |
反馈属性:powerstate、switch_light、switch_horizontal、windspeed、progress。
8.1.10 场景(smartscene)
场景只需上报 TurnOn 动作,中控点击或语控"执行场景"时下发 TurnOn。
说明:以上动作 / 属性宏均定义于
include/device_sdk_plugin.h,模式与风速的取值枚举详见第九章。
九. 指令集、属性与枚举定义
以下宏均定义于 include/device_sdk_plugin.h。
9.1 设备动作(action)
| 宏 | 值 | 说明 |
|---|---|---|
| DEVICE_ACTION_TURN_ON | TurnOn | 打开 |
| DEVICE_ACTION_TURN_OFF | TurnOff | 关闭 |
| DEVICE_ACTION_PAUSE | Pause | 暂停 |
| DEVICE_ACTION_TURN_UP | TurnUp | 上升 |
| DEVICE_ACTION_TURN_DOWN | TurnDown | 下降 |
| DEVICE_ACTION_SET_MODE | SetMode | 设置模式 |
| DEVICE_ACTION_SET_SCENE | SetScene | 设置情景 |
| DEVICE_ACTION_SET_TEMPERATURE | SetTemperature | 设置温度 |
| DEVICE_ACTION_ADJUST_UP_TEMPERATURE | AdjustUpTemperature | 温度 + |
| DEVICE_ACTION_ADJUST_DOWN_TEMPERATURE | AdjustDownTemperature | 温度 - |
| DEVICE_ACTION_SET_WINDSPEED | SetWindSpeed | 设置风速 |
| DEVICE_ACTION_SET_BRIGHTNESS | SetBrightness | 设置亮度 |
| DEVICE_ACTION_ADJUST_UP_BRIGHTNESS | AdjustUpBrightness | 亮度 + |
| DEVICE_ACTION_ADJUST_DOWN_BRIGHTNESS | AdjustDownBrightness | 亮度 - |
| DEVICE_ACTION_SET_COLOR_TEMPERATURE | SetColorTemperature | 设置色温 |
| DEVICE_ACTION_ADJUST_UP_COLOR_TEMPERATURE | AdjustUpColorTemperature | 色温 + |
| DEVICE_ACTION_ADJUST_DOWN_COLOR_TEMPERATURE | AdjustDownColorTemperature | 色温 - |
| DEVICE_ACTION_SET_COLOR | SetColor | 设置颜色 |
| DEVICE_ACTION_SET_PROGRESS | SetProgress | 设置进度(百分比) |
| DEVICE_ACTION_SWITCH_HORIZONTAL | SwitchHorizontal | 左右摆风 |
| DEVICE_ACTION_SWITCH_VERTICAL | SwitchVertical | 上下摆风 |
| DEVICE_ACTION_SWITCH_LIGHT | SwitchLight | 灯光 |
| DEVICE_ACTION_SWITCH_STERILIZE | SwitchSterilize | 消毒 |
| DEVICE_ACTION_SWITCH_AIRDRY | SwitchAirdry | 风干 |
| DEVICE_ACTION_SWITCH_DRYING | SwitchDrying | 烘干 |
| DEVICE_ACTION_PLAY | Play | 播放 |
| DEVICE_ACTION_NEXT | Next | 下一曲 |
| DEVICE_ACTION_PREV | Prev | 上一曲 |
| DEVICE_ACTION_ADJUST_UP_VOLUME | AdjustUpVolume | 音量 + |
| DEVICE_ACTION_ADJUST_DOWN_VOLUME | AdjustDownVolume | 音量 - |
| DEVICE_ACTION_SET_BATTERY_PERCENTAGE | SetBatteryPercentage | 设置电量 |
多路开关的分路控制动作为
SetSwitchN(N 为第几路,如 SetSwitch1、SetSwitch2),该动作由中控按子类型自动生成,无对应宏。
9.2 设备属性(property)
| 宏 | 值 | 说明 |
|---|---|---|
| DEVICE_PROPERTIE_POWERSTATE | powerstate | 电源状态 |
| DEVICE_PROPERTIE_MODE | mode | 模式 |
| DEVICE_PROPERTIE_TEMPERATURE | temperature | 温度 |
| DEVICE_PROPERTIE_CURRENT_TEMPERATURE | current_temperature | 当前温度 |
| DEVICE_PROPERTIE_WINDSPEED | windspeed | 风速 |
| DEVICE_PROPERTIE_BRIGHTNESS | brightness | 亮度 |
| DEVICE_PROPERTIE_COLOR_HSV | color_hsv | 颜色(HSV) |
| DEVICE_PROPERTIE_COLOR_TEMPERATURE | color_temperature | 色温 |
| DEVICE_PROPERTIE_PROGRESS | progress | 进度 |
| DEVICE_PROPERTIE_SWITCH_HORIZONTAL | switch_horizontal | 左右摆风 |
| DEVICE_PROPERTIE_SWITCH_VERTICAL | switch_vertical | 上下摆风 |
| DEVICE_PROPERTIE_SWITCH_LIGHT | switch_light | 灯光 |
| DEVICE_PROPERTIE_SWITCH_STERILIZE | switch_sterilize | 消毒 |
| DEVICE_PROPERTIE_SWITCH_AIRDRY | switch_airdry | 风干 |
| DEVICE_PROPERTIE_SWITCH_DRYING | switch_drying | 烘干 |
| DEVICE_PROPERTIES_VALUE_ON / OFF | on/off | 开/关 |
demo 中使用的扩展属性(无宏,直接使用字符串):
| 属性 | 说明 |
|---|---|
| colortemp_range_min / max / step | 灯具色温范围与步进(K),见 8.1.1 |
| subdev_name_switch_1 ~ N | 多路开关各按键名称,见 8.1.2 |
| switchs1 ~ switchsN | 多路开关分路状态反馈(on/off),见 8.1.2 |
| ais_relay | 自身开关对应的中控继电器路数,见 8.1.2 |
9.3 模式与风速枚举
模式(smarthome_priv.h 中通过 MAP_AIS_DEMO_MODE 建立 AIS 值与本地编码的映射):
| 宏 | 值 | 说明 |
|---|---|---|
| DEVICE_MODE_COLD | cold | 制冷 |
| DEVICE_MODE_HEAT | heat | 制热 |
| DEVICE_MODE_AUTO | auto | 自动 |
| DEVICE_MODE_AIRSUPPLY | airsupply | 送风 |
| DEVICE_MODE_DEHUMIDIFICATION | dehumidification | 除湿 |
| DEVICE_MODE_MANUAL | manual | 手动 |
| DEVICE_MODE_ENERGY | energy | 省电 |
| DEVICE_MODE_COMFORTABLE | comfortable | 舒适 |
| DEVICE_MODE_HOLIDY | holiday | 节日 |
| DEVICE_MODE_ECO | eco | eco |
| DEVICE_MODE_SLEEP | sleep | 睡眠 |
| DEVICE_MODE_PROGRAM | program | 程控 |
| DEVICE_MODE_FLOOR_HEAT | floorHeat | 地暖 |
| DEVICE_MODE_AUXILIARY_HEAT | auxiliaryHeat | 辅热 |
| DEVICE_MODE_SILENT | silent | 静音 |
| DEVICE_MODE_EXHAUSTWIND | exhaustWind | 排风 |
风速(MAP_AIS_DEMO_WINDSPEED):
| 宏 | 值 | 说明 |
|---|---|---|
| DEVICE_WINDSPEED_AUTO | auto | 自动 |
| DEVICE_WINDSPEED_HIGH | high | 高风 |
| DEVICE_WINDSPEED_MIDDLE | medium | 中风 |
| DEVICE_WINDSPEED_LOW | low | 低风 |
| DEVICE_WINDSPEED_HEALTH | health | 健康 |
| DEVICE_WINDSPEED_NATURAL | natural | 自然 |
| DEVICE_WINDSPEED_STRONG | strong | 强力 |
| DEVICE_WINDSPEED_QUIET | quietWind | 静音风 |
| DEVICE_WINDSPEED_SLEEP | sleep | 睡眠 |
| DEVICE_WINDSPEED_COMFORTABLE | comfortableWind | 舒适风 |
映射表定义示例:
static map_smart_ais_demo_t MAP_AIS_DEMO_MODE[] = {
{DEVICE_MODE_COLD, "1", "制冷"},
{DEVICE_MODE_AIRSUPPLY, "2", "送风"},
{DEVICE_MODE_DEHUMIDIFICATION, "3", "除湿"},
{DEVICE_MODE_HEAT, "4", "制热"},
{NULL, NULL, NULL} // 结束哨兵
};
十. 数据结构
smarthome_priv.h 定义了设备信息结构体,对接方在本地维护设备列表时使用:
typedef struct {
str_t name; // 设备名
str_t device_id; // 设备id
str_t room_name; // 房间名
unsigned char type; // 设备类型(LETS_OEM_xxx)
unsigned char id;
unsigned char seq;
unsigned char flag; // bit0:online, bit2:local, bit4~7:switchs
unsigned char show;
device_status_t status;
unsigned char pic_id;
device_data_t data; // 联合体:按设备类型存放 brightness/temperature/...
} device_info_t;
device_data_t 为联合体,按设备类型复用内存(light / curtain / air_condition / fan_light / hanger / music_box / bath_heat / smart_switch)。
设备默认配置以文本形式存放(demo 中路径为 /data/plugin_devices_info,可按平台调整),格式为 type:id:seq^名称^pic_id,例如:
const char* DEFAULT_PLUG_DEVICE_INFO =
"22:01:00^回家^0\n" // 场景
"08:04:06^彩光灯^0\n" // 灯
"b0:01:07^窗帘^0\n" // 窗帘
"21:01:0B^空调^0^0\n" // 空调
"b2:01:10^一路开关^0\n"; // 开关
parse_config_file() 读取该配置,解析为 device_info_t 并加入设备列表,随后置状态为 PLUGIN_STATE_LOGGED 并调用 notify_devices_change() 上报。
十一. 平台工具接口
RTOS 平台提供如下工具接口,方便插件开发中使用。
11.1 解除绑定与重启
解除绑定/退出登录时通常需要重启应用,可调用:
g_context->listener(NULL, PLUGIN_EVENT_REQ_REBOOT, NULL);
11.2 UI 提示(toast)
void smarthome_plugin_toast(const char* msg) {
if (g_context->listener == NULL) return;
char toast[256];
snprintf(toast, sizeof(toast), "{\"version\":1,\"msg\":\"%s\"}", msg);
g_context->listener(NULL, PLUGIN_EVENT_ON_UI_TOAST, toast);
}
11.3 获取 IP / MAC 地址
平台已实现网络信息获取接口(声明于平台头文件 ssutils.h / ss_deviceinfo.h,插件中 extern 声明后可直接调用):
// 获取 IP 地址,name 为网卡节点名(RTOS 侧忽略该参数,固定取 WiFi STA 的 IP)
// 成功返回 0,ip 如 "192.168.1.100"
extern int ssutils_get_ip_address(char* name, char* ip);
// 获取 MAC 地址,name 为网卡节点名(RTOS 侧忽略该参数,固定取 WiFi STA 的 MAC)
// format=0: "aa:bb:cc:dd:ee:ff",缓冲区需 18 字节
// format=1: "aabbccddeeff",缓冲区需 13 字节
extern int ssutils_get_mac_addr(char* name, char* mac, int format);
// 便捷接口:获取无冒号格式 MAC(等价于 ssutils_get_mac_addr(name, sn, 1))
extern int ss_deviceinfo_get_mac(char* sn);
示例:
char ip[20] = {0};
char mac[18] = {0};
if (ssutils_get_ip_address("wlan0", ip) == 0) {
printf("ip: %s\n", ip);
}
if (ssutils_get_mac_addr("wlan0", mac, 0) == 0) {
printf("mac: %s\n", mac);
}
11.4 HTTP 请求
平台内置 HTTP 客户端(异步),插件可直接调用,回调在 HTTP 服务线程中执行:
typedef void (*cb_on_result)(void* context, int code, void* result);
// GET
void http_client_add_request_get(void* context, cb_on_result on_result, int req_type, const char* url);
void http_client_add_request_get_with_header(void* context, cb_on_result on_result, int req_type, const char* url);
// POST,data 为 JSON 字符串
void http_client_add_request_post_json(void* context, cb_on_result on_result, int req_type,
const char* url, const char* data, int size);
void http_client_add_request_post_json_with_header(void* context, cb_on_result on_result, int req_type,
const char* url, const char* data, int size);
// POST / PUT 原始数据
void http_client_add_request_post_data(void* context, cb_on_result on_result, int req_type,
const char* url, const char* data, int size);
void http_client_add_request_put_data(void* context, cb_on_result on_result, int req_type,
const char* url, const char* data, int size);
void http_client_add_request_put_stream(void* context, cb_on_result on_result, int req_type,
const char* url, const char* data, int size);
回调原型:响应到达后回调 on_result(context, size, data),data 为响应体(字符串),size 为长度,context 为调用时传入的用户指针(原样透传)。
示例(POST JSON,带 MD5 签名,见 11.5):
static void cb_config_data(void* context, int size, void* data) {
if (size <= 0 || data == NULL) {
LOGE("http response: size = 0\n");
return;
}
char* json_str = (char*)data; // 响应体,cJSON_Parse 解析
cJSON* json = cJSON_Parse(json_str);
// ... 处理响应
cJSON_Delete(json);
}
void http_request_config(void) {
const char* url = "http://xxxxx";
char post_data[128];
char md5[33] = {0};
// sign = md5(device_id + salt)
char sign_str[48] = {0};
snprintf(sign_str, sizeof(sign_str), "%s52S#8@8f5cLn", g_device_id);
get_buffer_md5sum_text(sign_str, strlen(sign_str), md5);
extern char* ss_device_info_get_pid();
snprintf(post_data, sizeof(post_data),
"{\"pid\":\"%s\",\"id\":\"%s\",\"sign\":\"%s\"}",
ss_device_info_get_pid(), g_device_id, md5);
http_client_add_request_post_json(NULL, cb_config_data, 0, url, post_data, strlen(post_data));
}
11.5 MD5
// 计算 buffer 的 MD5,result 输出为 32 字符文本形式(需 33 字节缓冲,含 '\0')
extern int get_buffer_md5sum_text(char* buffer, unsigned int size, unsigned char* result);
用法参考 11.4 示例中的签名计算。
11.6 MQTT
RTOS 平台提供轻量 MQTT 客户端(mqtt_client.h),内部以独立线程运行,接口如下:
typedef void (*cb_on_mqtt_connect)(int is_connected);
typedef void (*cb_on_mqtt_message)(char* topic, char* payload, int len);
// 启动 MQTT 服务并连接;sub_info 非空则自动订阅
// 返回 MQTT 实例指针,失败返回 NULL
struct cmd_mqtt_common* mqtt_client_start(char* init_config, char* sub_info,
cb_on_mqtt_connect on_mqtt_connect,
cb_on_mqtt_message on_mqtt_message);
void mqtt_client_subscribe(struct cmd_mqtt_common* inst, char* sub_info); // 订阅
int mqtt_client_publish(struct cmd_mqtt_common* inst, char* topic, char* message); // 异步发布
int mqtt_client_publish_sync(struct cmd_mqtt_common* inst, char* topic, char* message); // 同步发布
void mqtt_client_connect(struct cmd_mqtt_common* inst); // 连接
void mqtt_client_disconnect(struct cmd_mqtt_common* inst); // 断开
int mqtt_client_is_connecting(struct cmd_mqtt_common* inst);
void mqtt_client_stop(struct cmd_mqtt_common* inst); // 停止并释放资源
参数格式为空格分隔的 key=value 字符串(与串口调试命令一致):
| 参数串 | 支持的 key |
|---|---|
| init_config | host、port、client_id、username、password、alive(心跳秒数)、ssl(0/1)、clean(0/1)、will_topic、will_message |
| sub_info | qos、topic |
示例:
static void on_mqtt_connect(int is_connected) {
// is_connected == 1 连接成功,可在此订阅主题
}
static void on_mqtt_message(char* topic, char* payload, int len) {
printf("recv: %s %.*s\n", topic, len, payload);
}
void mqtt_demo(void) {
char config[80];
snprintf(config, sizeof(config), "host=%s port=%d alive=60 client_id=%s",
"192.168.0.117", 1883, "R1005538268211647727");
struct cmd_mqtt_common* mqtt =
mqtt_client_start(config, "", on_mqtt_connect, on_mqtt_message);
// 订阅(也可在连接成功回调中调用)
mqtt_client_subscribe(mqtt, "qos=0 topic=zhiju/zhiju_switch_wr10/R1009181328178345312/command/down");
// 发布
mqtt_client_publish(mqtt, "zhiju/zhiju_switch_wr10/R1009181328178345312/message/up", "{\"state\":1}");
}
11.7 UART 示例代码
串口收发示例代码:点击下载