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 $@

对接步骤:

  1. 将 COMPILE_PREX 修改为实际使用的 RISC-V 交叉编译器路径前缀;
  2. 执行 make(或 make PLATFORM=tina 以启用 Tina 平台相关宏),生成 libjdsmart_demo.a;
  3. 在固件工程中链接该静态库,并把 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 对接基本要求

  1. 能够提供所有设备列表数据,设备信息中包含设备 ID、设备名、设备类型;
  2. 能够提供所有场景列表数据,场景信息中包含场景 ID、场景名;
  3. 能够提供所有房间列表数据,房间信息中包含房间 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 示例代码

串口收发示例代码:点击下载


results matching ""

    No results matching ""