RTOS SDK Integration

This document describes how the smart home plugin integrates with the RTOS platform SDK. The RTOS version is linked directly into the firmware at compile time in the form of a static library libjdsmart_demo.a.

After integration is complete, the following features are supported: device login, device discovery, device control, and device status feedback.

Version Change Log
V1.0.0 Initial version
V1.1.0 Added device category and sub-category descriptions; completed protocol, event, packet-building API and command set descriptions; added platform utility interfaces (HTTP / MD5 / MQTT / UART)

The smart home SDK integration method is suitable for companies with embedded C development capabilities, supporting device login, device discovery, device control, and device status feedback.

Demo plugin source code Download


1. Project Structure

libdemo/
├── Makefile                    # RTOS static library build script (riscv64-unknown-elf toolchain)
├── libjdsmart_demo.a           # Build artifact: static library
├── include/                    # Integration header files
│   ├── device_sdk_plugin.h     # Plugin API / device types / properties / actions / event definitions
│   ├── device_sdk_music.h      # Music playback and device status feedback command definitions, currently unused
│   ├── smarthome_packet.h      # Device discovery protocol packet-building API
│   ├── smarthome_common.h      # Platform data directory macros (including OS_RTOS)
│   ├── smarthome_priv.h        # Private structures: device_info_t / device mapping table
│   ├── cJSON.h                 # JSON parsing/generation
│   └── tkc/                    # Base utility library (dynamic arrays, strings, memory, etc.)
├── src/
│   ├── smarthome_demo.c        # Integration implementation (core business code to be implemented)
│   ├── smarthome_packet.c      # Packet-building API implementation
│   └── smarthome_utils.h       # Platform utility function declarations (unused in demo, no need to focus on)
└── smarthome_utils/            # Reserved directory (empty in libdemo, no need to focus on)

The integrator needs to focus on the header files under include/ and src/smarthome_demo.c. All smarthome_xxx() functions are the integration interfaces defined by the SDK.


2. Build Environment

The RTOS version uses Makefile for building, producing the static library libjdsmart_demo.a. The toolchain is configured in the first line of Makefile:

Allwinner R128 Source Code Compilation Toolchain Path Download

COMPILE_PREX := /home/virtual_tmp/mm/riscv64-elf-x86_64-20201104/bin/riscv64-unknown-elf-

CC := $(COMPILE_PREX)gcc
AR := $(COMPILE_PREX)ar

# Automatically collect all .c/.cpp/.cc source files under src/
LOCAL_SRC_FILES := $(shell find $(LOCAL_PATH)/src -name "*.c" -o -name "*.cpp" -o -name "*.cc")

# Target: static library, packaged using $(AR) (not dynamic library linking)
all: libjdsmart_demo.a rm_objs

libjdsmart_demo.a: $(OBJS)
    $(AR) rcs $@ $^

%.o:%.c
    $(CC) -Wall -c $(CFLAGS) $< -o $@

Integration steps:

  1. Modify COMPILE_PREX to the actual RISC-V cross-compiler path prefix you are using;
  2. Run make (or make PLATFORM=tina to enable Tina platform-related macros) to generate libjdsmart_demo.a;
  3. Link this static library in your firmware project, and add the include/ directory to the header file search path.

3. Integration Flow

smarthome_preinit()      Pre-initialization: save callback listener, parse parameters
        │
smarthome_init()         Initialization: parse deviceID, create device list, start loading thread
        │
smarthome_get_state()    Central controller queries plugin state (IDLE / LOGGED ...)
smarthome_get_pluginfo() Central controller gets plugin info (appid, login method, flag, etc.)
        │
        ├──► listener(PLUGIN_EVENT_ON_DEVICES_SYNC)   Report device list (discovery protocol)
        │
smarthome_device_control()  Central controller sends control commands → operate hardware → feedback status
        │
        ├──► listener(PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE)  Report property changes
        │
smarthome_reset()        Reset / unbind

Core concept: The central controller drives the plugin by calling smarthome_xxx() interfaces; the plugin reports device lists, status, and property changes to the central controller via listener callbacks.

From the user's perspective, the overall demo flow is:

Login → Discover devices and scenes → Display devices and scenes → Interface click or voice control of scenes and devices

After device discovery is complete, you can see devices on the left screen of the desktop and scenes on the right screen, then click or use voice to control devices or scenes.


4. API Description

The following functions need to be implemented by the integration plugin. Function prototypes are defined in include/device_sdk_plugin.h, and reference implementations can be found in src/smarthome_demo.c.

Callback function type:

typedef void (*callback_func)(void* context, int code, void* result);

4.1 smarthome_preinit — Pre-initialization

Called earliest, used to save the application-layer callback listener (must be saved locally for the long term, all subsequent reports go through it), and parse input parameters.

/**
 * @brief  Pre-initialization
 * @param  params: {"feature":0, "switchs_count":2}
 * @param  listener: Application-layer callback function, needs to be saved locally
 */
int smarthome_preinit(char* params, callback_func listener);

Reference implementation (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;   // Key: save callback

  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 — Initialization

Parse local deviceID, create device container, and start device loading process.

/**
 * @param  params: {
 *                    "uuid":     "Plugin device id bound to AIS backend",
 *                    "key":      "Plugin device key bound to AIS backend",
 *                    "deviceID": "Unique device ID of this device"
 *                }
 */
int smarthome_init(char* params, callback_func listener);

Reference implementation:

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);  // Async device loading
  return 0;
}

Note: The platform supports pthread. Devices are loaded by calling parse_config_file() in a task/thread. After loading is complete, the state is set to PLUGIN_STATE_LOGGED and notify_devices_change() is called to report the device list. In the demo, uuid / key are reserved for AIS backend binding (not needed when authType is none); currently only deviceID is used.

4.3 smarthome_get_state — Get State

Returns the current plugin state for the central controller to determine login/loading progress.

int smarthome_get_state();

Return values are from enum SS_PLUGIN_STATE:

State Value Description
PLUGIN_STATE_FAIL -1 Failed
PLUGIN_STATE_IDLE 0 Idle
PLUGIN_STATE_INITED 1 Initialized
PLUGIN_STATE_GET_CODE 2 Getting QR code
PLUGIN_STATE_GET_TOKEN 3 Getting token
PLUGIN_STATE_LOGGED 4 Logged in
PLUGIN_STATE_BINDED 5 Binded

4.4 smarthome_get_pluginfo — Get Plugin Info

Returns a JSON string describing the plugin version, appid, login method, login prompt text, and feature flags.

char* smarthome_get_pluginfo();

Reference implementation:

char* smarthome_get_pluginfo() {
  cJSON* root = cJSON_CreateObject();

  cJSON_AddNumberToObject(root, "version", PLUGIN_PROTOCOL_VERSION);
  cJSON_AddStringToObject(root, "appid", "xxx.com");          // Vendor appid, recommended to be a domain name
  cJSON_AddNumberToObject(root, "state", g_context->state);
  cJSON_AddStringToObject(root, "authType", AUTH_TYPE_NONE);   // Auth type, keep as is, do not modify
  cJSON_AddStringToObject(root, "loginType", LOGIN_TYPE_QRCODE); // Login method
  cJSON_AddStringToObject(root, "loginTitle", "Device Binding");
  cJSON_AddStringToObject(root, "loginHint", "Scan with mobile 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;   // Supports offline loading
  cJSON_AddNumberToObject(root, "flag", flag);

  char* info = cJSON_PrintUnformatted(root);
  cJSON_Delete(root);
  return info;   // Caller is responsible for free
}

Flag definitions (can be combined as needed):

Flag Description
PLUG_FLAG_LOAD_OFFLINE Supports offline loading
PLUG_FLAG_STATE_FEEDBACK Switch button waits for device status feedback before changing
PLUG_FLAG_SMART_BUS Plugin occupies RS485 device, used for 485 plugin integration development
PLUG_FLAG_NO_SMART_BUS Disable RS485 related UI display
PLUG_FLAG_PAIRD_DEVICES Plugin has device discovery and auto-pairing functionality

Additionally, two optional fields are supported (demo has commented examples):

Field Description
custom_model Custom device name, max 32 bytes, displayed at "Settings > About This Device > Device Name"

4.5 smarthome_device_control — Device Control

Called when the central controller sends control commands. Parameters are in JSON format; parse them and drive the actual hardware, then callback to report execution results and property changes.

/**
 * @param  params: {
 *                    "id":"vdevo161103533857949",  // Device ID
 *                    "type":"aircondition",        // Device type
 *                    "sub_type":"unknown",         // Device sub-type
 *                    "action":"SetTemperature",    // Action
 *                    "value":"19"                  // Value
 *                }
 * @param  callback: (void* context, int code, void* result)
 *                  code: 0 = success, -1 = error; on error, result passes text for display
 */
int smarthome_device_control(const char* params, callback_func callback);

Reference implementation (using light as an example, showing the complete chain of parse → drive → feedback):

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(...);  // Call actual hardware driver
          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; // Percentage to Kelvin
          notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_COLOR_TEMPERATURE, value);
        }
      }
      // ... See source code for aircondition / curtain / switch / bath_heater / fan_light types
    }
    cJSON_Delete(root);
  }
  return 0;
}

Complete control branches for light, switch, aircondition, curtain, bath_heater, music_player, hanger, fan and other device types are already provided in src/smarthome_demo.c. During integration, simply replace the commented-out leshi_ble_xxx() calls with your own hardware drivers.

4.6 smarthome_device_discover — Device Discovery

int smarthome_device_discover(int method, callback_func callback);

Called when the central controller needs to refresh the device list (also called once during the initial loading process). method and callback are reserved parameters; the demo has empty implementations.

Note: RTOS device loading is completed in the thread started by smarthome_init. When the device list changes (devices added/removed, renamed, etc.), the plugin should proactively re-report the complete device list via PLUGIN_EVENT_ON_DEVICES_SYNC, without waiting for the central controller to call this interface.

4.7 smarthome_reset — Reset / Unbind

int smarthome_reset();

Reference implementation:

int smarthome_reset() {
  g_context->state = PLUGIN_STATE_IDLE;
  notify_gw_status(PLUGIN_STATE_IDLE, "Gateway has been reset");
  return 0;
}

When unbinding/logging out, the application usually needs to restart. You can call g_listener(NULL, PLUGIN_EVENT_REQ_REBOOT, NULL);.

4.8 smarthome_ioctl — Extended Commands

Used for extended scenarios such as device discovery, debug info, and production testing.

int smarthome_ioctl(char* cmd, char* key, char* value);

Supported cmds (see source code):

cmd Description
discovery_device Enter device discovery mode (requires setting PLUG_FLAG_PAIRD_DEVICES)
discovery_device_exit Exit discovery interface
get_debug_info Return debug info (plain text or input dialog, reported via PLUGIN_EVENT_ON_DEBUG_INFO)
test_mode_start Start production test, return results via PLUGIN_EVENT_ON_TEST_RESULT

4.9 smarthome_slave_report — Slave Device Status Report

When the plugin acts as a slave device, report hardware events such as button presses and relay states to the central controller/server.

int smarthome_slave_report(const char* params, callback_func callback);

In params, i0 is the command code, with values defined in device_sdk_music.h (e.g., DEVICE_REPORT_KEY_EVENT=254 for key events, DEVICE_REPORT_DEVICE_PROP=250 for property reports).

Reference implementation (key event):

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); // Operate relay
          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;
}

5. Callback Events (listener)

The plugin reports events to the central controller via listener(context, event, result). Events are defined in enum SS_PLUGIN_EVENT:

Event Value Description result Content
PLUGIN_EVENT_ON_GW_RESET 1 Gateway reset -
PLUGIN_EVENT_ON_GW_STATUS 2 Gateway/login status change plugin_ret_t{code,msg}
PLUGIN_EVENT_ON_GW_URL 3 Gateway URL URL string
PLUGIN_EVENT_ON_DEVICES_SYNC 4 Report device list Discovery protocol JSON string (see 7.2)
PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE 5 Device property change Property JSON string (see 7.3)
PLUGIN_EVENT_ON_DEVICE_DISCOVERY 6 Device discovery progress hint {"version":1,"msg":"Searching..."}
PLUGIN_EVENT_ON_DEBUG_INFO 7 Debug info / input dialog JSON
PLUGIN_EVENT_REQ_REBOOT 1000 Request app restart NULL
PLUGIN_EVENT_SLAVE_CONTROL 1001 Slave device relay control {"i0":..,"i1":..}
PLUGIN_EVENT_ON_VOICE_RESP 1002 Voice response Reserved
PLUGIN_EVENT_ON_CLOCK_UPDATE 1003 Clock update Reserved
PLUGIN_EVENT_ON_UI_TOAST 1004 UI toast {"version":1,"msg":"..."}
PLUGIN_EVENT_ON_HOTEL_RESET 1005 Hotel mode reset Reserved
PLUGIN_EVENT_ON_TEST_RESULT 1006 Production test result >0 success / <0 failure
PLUGIN_EVENT_ON_UI_DIALOG 1007 UI dialog JSON
PLUGIN_EVENT_ON_UI_STRING 1008 UI string JSON

Events actually used in the 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; the rest are reserved.

Report gateway status:

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);
}

Report property changes:

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);
}

You can also use smarthome_packet_smart_prop(id, name, value) from the packet library to generate the same JSON (see Chapter 6).

Report device list (packet building + sync):

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);           // Iterate local devices and build packets
  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);
}

6. Device Packet-Building API

smarthome_packet.h / smarthome_packet.c provide a set of cJSON-based packet-building interfaces for generating "device discovery protocol" JSON, avoiding manual string concatenation.

API Description
smarthome_packet_devicelist_new() Create device list container
smarthome_packet_devicelist_add_device(devlist, dev) Add device to list (dev ownership transfers, internally freed, do not double free)
smarthome_packet_devicelist_pack(devlist) Pack into JSON string (contains version/name/devices, caller responsible for free)
smarthome_packet_device_new_object(id, name, online) Create single device object (automatically includes actions/properties arrays)
smarthome_packet_device_set_type(dev, type) Set device type (deviceType)
smarthome_packet_device_set_sub_type(dev, sub_type) Set device sub-type (deviceSubType), optional
smarthome_packet_device_set_zone(dev, zone) Set room name (zone), optional
smarthome_packet_device_add_action(dev, action) Add action
smarthome_packet_device_create_action_instructions(dev, action) Add action with enums, returns instructions array
smarthome_packet_device_append_action_instruction(instr, value, desc) Append an enum item to instructions (code and value are the same)
smarthome_packet_device_add_property(dev, name, value) Add property
smarthome_packet_device_delete_object(dev) Free device object (called internally after add_device)
smarthome_packet_smart_prop(id, name, value) Assemble single property change JSON (for property reports)

Packet-building example (air conditioner device, with mode/wind speed enums), from 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 action + enum items
  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. Protocol Description

7.1 Integration Requirements

  1. Must be able to provide all device list data, with device info including device ID, device name, and device type;
  2. Must be able to provide all scene list data, with scene info including scene ID and scene name;
  3. Must be able to provide all room list data, with room info including room ID and room name.

7.2 Device Discovery Protocol

Reported by notify_devices_change() via PLUGIN_EVENT_ON_DEVICES_SYNC. Root fields:

Field Type Description
version int Protocol version, fixed at 1
name string Fixed as "DiscoveryDevicesResponse"
devices array Array of device objects

Device object fields:

Field Required Description
deviceId Yes Device unique ID. Demo uses hex format type:seq:check (e.g., 08:01:03), central controller parses by : delimiter
deviceName Yes Device name, also used for voice matching. Recommended format: "room+device" or common name, e.g., "Living Room Light"
online Yes 1 = online / 0 = offline
deviceType Yes Device type, see Chapter 8
deviceSubType No Device sub-type, see category descriptions in 8.x (required for multi-way switches)
zone No Room name, e.g., "Living Room"
icon / iconPath No Icon
actions Yes Supported action array, determines central controller panel shape and voice support scope
actions[].action Yes Action name, see 9.1
actions[].instructions No Action enum items (needed for discrete value actions like mode, wind speed)
instructions[].value / code Yes Enum value, sent as-is as value during control
instructions[].desc Yes Enum description (e.g., "Cooling"), used for voice and UI display
properties No Property array {name, value}, reports current state initial values

Report example:

{
    "version": 1,
    "name": "DiscoveryDevicesResponse",
    "devices": [
        {
            "deviceId": "vdevo162130282208556",
            "deviceName": "Color Light",
            "online": 1,
            "actions": [
                { "action": "TurnOn" },
                { "action": "TurnOff" },
                {
                    "action": "SetMode",
                    "instructions": [
                        { "value": "lightWhite",  "code": "lightWhite",  "desc": "White Light" },
                        { "value": "lightColour", "code": "lightColour", "desc": "Color Light" },
                        { "value": "lightScene",  "code": "lightScene",  "desc": "Scene" }
                    ]
                },
                { "action": "SetBrightness" },
                { "action": "SetColorTemperature" },
                { "action": "SetColor" },
                {
                    "action": "SetScene",
                    "instructions": [
                        { "value": "light_scene_1", "code": "light_scene_1", "desc": "Good Night" },
                        { "value": "light_scene_2", "code": "light_scene_2", "desc": "Reading" }
                    ]
                }
            ],
            "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": "Balcony",
            "deviceType": "light",
            "deviceSubType": "unknown"
        },
        {
            "deviceId": "SN8hzCSAbWrCtjIE",
            "deviceName": "Morning Rise",
            "deviceType": "smartscene",
            "actions": [ { "action": "TurnOn" } ]
        }
    ]
}

7.3 Device Response Protocol

When device properties change, report via PLUGIN_EVENT_ON_DEVICE_PROP_CHANGE, format:

Field Description
version Fixed at 1
deviceId Device ID
name Property name, see 9.2
value Property value
{ "version": 1, "deviceId": "vdevo162088709984066#1", "name": "online", "value": "1" }

Common control/feedback examples:

// Power state
{ "version":1, "deviceId":"vdevo162088709984066#1", "name":"powerstate", "value":"on" }

// Brightness (0~100)
{ "id":"vdevo162192408876410", "type":"light", "sub_type":"", "action":"SetBrightness", "value":"53" }

// Color (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}" }

// Color temperature (0~100)
{ "id":"vdevo161847485227864", "type":"light", "sub_type":"", "action":"SetColorTemperature", "value":"50" }

// Air conditioner temperature
{ "id":"vdevo161103533857949", "type":"aircondition", "sub_type":"", "action":"SetTemperature", "value":"20" }

// Air conditioner wind speed
{ "id":"vdevo161103533857949", "type":"aircondition", "sub_type":"", "action":"SetWindSpeed", "value":"low" }

// Mode
{ "version":1, "deviceId":"vdevo161103533857949", "name":"mode", "value":"heat" }

// Oscillation (switch_horizontal = left-right, switch_vertical = up-down)
{ "version":1, "deviceId":"vdevo161103533857949", "name":"switch_horizontal", "value":"on" }

8. Supported Device Categories

The central controller identifies devices, renders corresponding control panels, and supports voice control based on a three-level hierarchy: device type (deviceType) → device sub-type (deviceSubType) → reported actions (actions). Integrators should report the corresponding types, sub-types, and actions based on their actual hardware capabilities.

8.1 Smart Device Types

Device type macros are defined in include/device_sdk_plugin.h. Packet-building logic for each category in the demo can be found in convert_devices_pack(), and control branches in smarthome_device_control().

Name Function Macro Type Sub-type
Light On/off, brightness, color temperature, color, scene mode DEVICE_TYPE_LIGHT light Sub-types distinguished by actions (see 8.1.1)
Switch On/off; multi-way switch supports per-channel control DEVICE_TYPE_SWITCH switch Single-way / switchs_2 ~ switchs_6
Outlet On/off DEVICE_TYPE_OUTLET outlet Same as switch, multi-hole uses switchs_N
Power Strip On/off DEVICE_TYPE_SOCKETS sockets Same as switch, multi-hole uses switchs_N
Curtain Open, close, pause, percentage, angle DEVICE_TYPE_CURTAIN curtain Sub-types distinguished by actions (see 8.1.4)
Air Conditioner On/off, temperature, mode, wind speed, oscillation DEVICE_TYPE_AIRCONDITION aircondition AC / temperature_ctrl thermostat / floor_heat floor heating
Bath Heater On/off, lighting, exhaust/ventilation/sleep, wind speed DEVICE_TYPE_BATH_HEATER bath_heater
Music Player Play, pause, skip, volume DEVICE_TYPE_MUSIC_PLAYER music_player
Clothes Hanger Raise, lower, pause, lighting DEVICE_TYPE_HANGER hanger
Fan (Fan Light) Fan on/off, lighting, oscillation, wind speed DEVICE_TYPE_FAN fan
Scene Scene execution DEVICE_TYPE_SMARTSCENE smartscene

8.1.1 Light (light)

Lights do not use deviceSubType for distinction. The central controller identifies light sub-types based on the reported action combinations and displays the corresponding control panel:

Sub-type Required Actions Control Panel
Basic light (on/off only) TurnOn / TurnOff Single switch
Dimmable light Also report SetBrightness Brightness slider
Color temperature light Also report SetColorTemperature Brightness + color temperature
Color light Also report SetColor Color (HSV) panel
Scene light Also report SetScene (with mode property) Scene mode
Action Value Description
TurnOn / TurnOff None Light on / Light off
SetBrightness 0~100 Set brightness, read back brightness
AdjustUpBrightness / AdjustDownBrightness None Brightness +/-10
SetColorTemperature 0~100 Color temperature percentage, linearly mapped to Kelvin based on colortemp_range_min~max (demo: 2700K~6400K)
AdjustUpColorTemperature / AdjustDownColorTemperature None Color temperature +/-10
SetColor {"h":0~360,"s":0~1,"v":0~1} HSV color
SetScene light_scene_N (e.g., light_scene_1 Good Night) Scene mode, see 7.2 example, demo control branch not implemented, can be extended as needed

Feedback properties: powerstate(on/off), brightness(0~100), color_temperature(0~100), color_hsv, mode(lightWhite / lightColour / lightScene).

When building packets, inform the central controller of the color temperature range via colortemp_range_min / colortemp_range_max / colortemp_range_step properties (see 7.2 example).

8.1.2 Switch (switch)

Sub-types are distinguished by deviceSubType:

Sub-type Description Control Method
Not reported / switchs_1 Single-way switch TurnOn / TurnOff, feedback powerstate
switchs_2 ~ switchs_6 N-way switch, central controller displays N-channel panel SetSwitchN (N is channel number, value = on/off), feedback switchsN and powerstate
Local switch (LETS_OEM_ZHINENG_SW type) Uses local relay Same as single-way; identify corresponding relay channel via ais_relay property

For multi-way switch packet building, report each button name via properties subdev_name_switch_1 ~ subdev_name_switch_N; when setting switchs_ sub-type, the panel does not display a master power button — the central controller automatically generates per-channel switches based on N, no need to report TurnOn/TurnOff actions.

Multi-way switch packet building example (2-way switch):

smarthome_packet_device_t* dev_pack = smarthome_packet_device_new_object("b2:02:11", "2-Way Switch", 1);

smarthome_packet_device_set_type(dev_pack, DEVICE_TYPE_SWITCH);
smarthome_packet_device_set_sub_type(dev_pack, "switchs_2");   // Key: N-way uses switchs_N

// Button names (optional, for UI display and voice matching)
smarthome_packet_device_add_property(dev_pack, "subdev_name_switch_1", "Switch Button 1");
smarthome_packet_device_add_property(dev_pack, "subdev_name_switch_2", "Switch Button 2");

smarthome_packet_device_add_property(dev_pack, DEVICE_PROPERTIE_POWERSTATE, DEVICE_PROPERTIES_VALUE_OFF);

smarthome_packet_devicelist_add_device(devlist, dev_pack);

Corresponding discovery protocol JSON report:

{
    "deviceId": "b2:02:11",
    "deviceName": "2-Way Switch",
    "online": 1,
    "deviceType": "switch",
    "deviceSubType": "switchs_2",
    "properties": [
        { "name": "subdev_name_switch_1", "value": "Switch Button 1" },
        { "name": "subdev_name_switch_2", "value": "Switch Button 2" },
        { "name": "powerstate",           "value": "off" }
    ]
}

Central controller control commands (params of smarthome_device_control(), action is SetSwitch + channel number, 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" }

Control branch reference implementation (parse channel → operate hardware → feedback per-channel and master power status):

} else if (!strncmp(action, "SetSwitch", strlen("SetSwitch"))) {  // Multi-way switch
  int index = atoi(action + strlen("SetSwitch"));                 // Channel number, starting from 1
  unsigned char is_on = my_streq(value, DEVICE_PROPERTIES_VALUE_ON);

  // Record per-channel status by bits (bit0~bitN of device->status correspond to channel 1~N)
  if (is_on) {
    device->status |= 1 << (index - 1);
  } else {
    device->status &= ~(1 << (index - 1));
  }

  // TODO: Operate actual hardware, e.g., relay
  // leshi_ble_set_data_short(LETS_OEM_86_SW, did + (index - 1), seq + (index - 1), 1, is_on);

  // Feedback per-channel status: property name is switchs + channel number (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);

  // Feedback master power status: on if any channel is on
  notify_prop_change(device->device_id.str, DEVICE_PROPERTIE_POWERSTATE,
                     device->status ? DEVICE_PROPERTIES_VALUE_ON : DEVICE_PROPERTIES_VALUE_OFF);
}

Corresponding property feedback:

{ "version":1, "deviceId":"b2:02:11", "name":"switchs1",   "value":"on"  }
{ "version":1, "deviceId":"b2:02:11", "name":"powerstate", "value":"on"  }

8.1.3 Outlet (outlet) / Power Strip (sockets)

TurnOn / TurnOff, feedback powerstate. Multi-hole power strips can reference multi-way switches, using switchs_N sub-type for per-channel control (central controller also recognizes switchs_ sub-type for both switch and sockets). Macros are already defined in the header file; the demo does not provide example devices for these, implementation can reference the switch.

8.1.4 Curtain (curtain)

The central controller identifies curtain sub-types based on the reported action combinations:

Sub-type Required Actions Control Panel
Basic curtain TurnOn / TurnOff Switch type
Curtain with pause Also report Pause Open / Close / Pause
Curtain with position Also report SetProgress Percentage slider
Angle blind (dream curtain) Also report SetProgress + SetAngle Position + angle panel
Action Value Description
TurnOn None Open curtain (local command 0x00)
TurnOff None Close curtain (local command 0x02)
Pause None Pause (local command 0x01)
SetProgress 0~100 Open/close percentage
SetAngle 0~100 Blade angle (for angle blinds; macro value "SetAngle" not included in device_sdk_plugin.h, define yourself)

Feedback properties: progress(0~100), powerstate (on when progress>0).

8.1.5 Air Conditioner (aircondition)

Sub-types are distinguished by deviceSubType:

Sub-type deviceSubType Control Panel
Air conditioner Not reported / unknown AC panel (temperature, mode, wind speed, oscillation)
Thermostat temperature_ctrl Shows AC panel if SetWindSpeed reported, otherwise shows thermostat panel
Floor heating floor_heat Thermostat panel
Action Value Description
TurnOn / TurnOff None AC on / AC off
SetTemperature 16~32 Temperature (°C), auto-clamped on overflow (MIN_TEMP/MAX_TEMP)
AdjustUpTemperature / AdjustDownTemperature None Temperature +/-1°C
SetMode cold / heat / auto / airsupply / dehumidification Mode, demo enum mapping see MAP_AIS_DEMO_MODE
SetWindSpeed auto / low / medium / high / strong Wind speed, demo enum mapping see MAP_AIS_DEMO_WINDSPEED

Feedback properties: powerstate, temperature, mode, windspeed; oscillation properties switch_horizontal (left-right) / switch_vertical (up-down), values on/off, corresponding actions SwitchHorizontal / SwitchVertical.

8.1.6 Bath Heater (bath_heater)

Action Value Description
TurnOn / TurnOff None Bath heater on / off
SwitchLight on / off Lighting
SetMode exhaustWind / airsupply / sleep Ventilation mode
SetWindSpeed high / low Wind speed level

Feedback properties: powerstate, switch_light, mode, windspeed.

8.1.7 Music Player (music_player)

Action Description
TurnOn / TurnOff Power
Play / Pause Play / Pause
Next / Prev Next track / Previous track
AdjustUpVolume / AdjustDownVolume Volume +/-

Feedback properties: powerstate, playback status (defined in device_sdk_music.h, currently unused).

8.1.8 Clothes Hanger (hanger)

Action Description
TurnOn Raise (retract)
TurnOff Lower
Pause Pause
SwitchLight on / off lighting
SetProgress Raise/lower position percentage

Feedback properties: powerstate, switch_light, progress. Demo control branch already implements lighting / pause / progress; raise/lower actions need to be supplemented by the integrator in the TurnOn / TurnOff branches with hardware drivers.

8.1.9 Fan (fan)

Demo local type is fan light (LETS_OEM_FAN_LIGHT), fan and lighting integrated.

Action Value Description
TurnOn / TurnOff None Fan on / off
SwitchLight on / off Lighting
SwitchHorizontal on / off Left-right oscillation
SetWindSpeed auto / low / medium / high / strong Wind speed

Feedback properties: powerstate, switch_light, switch_horizontal, windspeed, progress.

8.1.10 Scene (smartscene)

Scenes only need to report the TurnOn action. When the central controller clicks or uses voice to "execute scene", it sends TurnOn.

Note: All action/property macros above are defined in include/device_sdk_plugin.h. Enum values for mode and wind speed are detailed in Chapter 9.


9. Command Set, Properties and Enum Definitions

The following macros are all defined in include/device_sdk_plugin.h.

9.1 Device Actions (action)

Macro Value Description
DEVICE_ACTION_TURN_ON TurnOn Turn on
DEVICE_ACTION_TURN_OFF TurnOff Turn off
DEVICE_ACTION_PAUSE Pause Pause
DEVICE_ACTION_TURN_UP TurnUp Raise
DEVICE_ACTION_TURN_DOWN TurnDown Lower
DEVICE_ACTION_SET_MODE SetMode Set mode
DEVICE_ACTION_SET_SCENE SetScene Set scene
DEVICE_ACTION_SET_TEMPERATURE SetTemperature Set temperature
DEVICE_ACTION_ADJUST_UP_TEMPERATURE AdjustUpTemperature Temperature +
DEVICE_ACTION_ADJUST_DOWN_TEMPERATURE AdjustDownTemperature Temperature -
DEVICE_ACTION_SET_WINDSPEED SetWindSpeed Set wind speed
DEVICE_ACTION_SET_BRIGHTNESS SetBrightness Set brightness
DEVICE_ACTION_ADJUST_UP_BRIGHTNESS AdjustUpBrightness Brightness +
DEVICE_ACTION_ADJUST_DOWN_BRIGHTNESS AdjustDownBrightness Brightness -
DEVICE_ACTION_SET_COLOR_TEMPERATURE SetColorTemperature Set color temperature
DEVICE_ACTION_ADJUST_UP_COLOR_TEMPERATURE AdjustUpColorTemperature Color temperature +
DEVICE_ACTION_ADJUST_DOWN_COLOR_TEMPERATURE AdjustDownColorTemperature Color temperature -
DEVICE_ACTION_SET_COLOR SetColor Set color
DEVICE_ACTION_SET_PROGRESS SetProgress Set progress (percentage)
DEVICE_ACTION_SWITCH_HORIZONTAL SwitchHorizontal Left-right oscillation
DEVICE_ACTION_SWITCH_VERTICAL SwitchVertical Up-down oscillation
DEVICE_ACTION_SWITCH_LIGHT SwitchLight Lighting
DEVICE_ACTION_SWITCH_STERILIZE SwitchSterilize Sterilize
DEVICE_ACTION_SWITCH_AIRDRY SwitchAirdry Air dry
DEVICE_ACTION_SWITCH_DRYING SwitchDrying Dry
DEVICE_ACTION_PLAY Play Play
DEVICE_ACTION_NEXT Next Next track
DEVICE_ACTION_PREV Prev Previous track
DEVICE_ACTION_ADJUST_UP_VOLUME AdjustUpVolume Volume +
DEVICE_ACTION_ADJUST_DOWN_VOLUME AdjustDownVolume Volume -
DEVICE_ACTION_SET_BATTERY_PERCENTAGE SetBatteryPercentage Set battery percentage

Per-channel control actions for multi-way switches are SetSwitchN (N is channel number, e.g., SetSwitch1, SetSwitch2). These actions are auto-generated by the central controller based on sub-type and have no corresponding macro.

9.2 Device Properties (property)

Macro Value Description
DEVICE_PROPERTIE_POWERSTATE powerstate Power state
DEVICE_PROPERTIE_MODE mode Mode
DEVICE_PROPERTIE_TEMPERATURE temperature Temperature
DEVICE_PROPERTIE_CURRENT_TEMPERATURE current_temperature Current temperature
DEVICE_PROPERTIE_WINDSPEED windspeed Wind speed
DEVICE_PROPERTIE_BRIGHTNESS brightness Brightness
DEVICE_PROPERTIE_COLOR_HSV color_hsv Color (HSV)
DEVICE_PROPERTIE_COLOR_TEMPERATURE color_temperature Color temperature
DEVICE_PROPERTIE_PROGRESS progress Progress
DEVICE_PROPERTIE_SWITCH_HORIZONTAL switch_horizontal Left-right oscillation
DEVICE_PROPERTIE_SWITCH_VERTICAL switch_vertical Up-down oscillation
DEVICE_PROPERTIE_SWITCH_LIGHT switch_light Lighting
DEVICE_PROPERTIE_SWITCH_STERILIZE switch_sterilize Sterilize
DEVICE_PROPERTIE_SWITCH_AIRDRY switch_airdry Air dry
DEVICE_PROPERTIE_SWITCH_DRYING switch_drying Dry
DEVICE_PROPERTIES_VALUE_ON / OFF on/off On/Off

Extended properties used in demo (no macros, use string literals directly):

Property Description
colortemp_range_min / max / step Light color temperature range and step (K), see 8.1.1
subdev_name_switch_1 ~ N Multi-way switch button names, see 8.1.2
switchs1 ~ switchsN Multi-way switch per-channel status feedback (on/off), see 8.1.2
ais_relay Central controller relay channel corresponding to local switch, see 8.1.2

9.3 Mode and Wind Speed Enums

Mode (in smarthome_priv.h, AIS values are mapped to local codes via MAP_AIS_DEMO_MODE):

Macro Value Description
DEVICE_MODE_COLD cold Cooling
DEVICE_MODE_HEAT heat Heating
DEVICE_MODE_AUTO auto Auto
DEVICE_MODE_AIRSUPPLY airsupply Ventilation
DEVICE_MODE_DEHUMIDIFICATION dehumidification Dehumidify
DEVICE_MODE_MANUAL manual Manual
DEVICE_MODE_ENERGY energy Energy saving
DEVICE_MODE_COMFORTABLE comfortable Comfort
DEVICE_MODE_HOLIDY holiday Holiday
DEVICE_MODE_ECO eco Eco
DEVICE_MODE_SLEEP sleep Sleep
DEVICE_MODE_PROGRAM program Program
DEVICE_MODE_FLOOR_HEAT floorHeat Floor heating
DEVICE_MODE_AUXILIARY_HEAT auxiliaryHeat Auxiliary heating
DEVICE_MODE_SILENT silent Silent
DEVICE_MODE_EXHAUSTWIND exhaustWind Exhaust

Wind speed (MAP_AIS_DEMO_WINDSPEED):

Macro Value Description
DEVICE_WINDSPEED_AUTO auto Auto
DEVICE_WINDSPEED_HIGH high High
DEVICE_WINDSPEED_MIDDLE medium Medium
DEVICE_WINDSPEED_LOW low Low
DEVICE_WINDSPEED_HEALTH health Health
DEVICE_WINDSPEED_NATURAL natural Natural
DEVICE_WINDSPEED_STRONG strong Strong
DEVICE_WINDSPEED_QUIET quietWind Quiet
DEVICE_WINDSPEED_SLEEP sleep Sleep
DEVICE_WINDSPEED_COMFORTABLE comfortableWind Comfort

Mapping table definition example:

static map_smart_ais_demo_t MAP_AIS_DEMO_MODE[] = {
    {DEVICE_MODE_COLD,             "1", "Cooling"},
    {DEVICE_MODE_AIRSUPPLY,        "2", "Ventilation"},
    {DEVICE_MODE_DEHUMIDIFICATION, "3", "Dehumidify"},
    {DEVICE_MODE_HEAT,             "4", "Heating"},
    {NULL, NULL, NULL}   // End sentinel
};

10. Data Structures

smarthome_priv.h defines the device info structure, used by integrators to maintain device lists locally:

typedef struct {
  str_t name;          // Device name
  str_t device_id;     // Device ID
  str_t room_name;     // Room name
  unsigned char type;  // Device 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;  // Union: stores brightness/temperature/... based on device type
} device_info_t;

device_data_t is a union that reuses memory based on device type (light / curtain / air_condition / fan_light / hanger / music_box / bath_heat / smart_switch).

Device default configuration is stored as text (demo path is /data/plugin_devices_info, adjustable per platform), format is type:id:seq^name^pic_id, for example:

const char* DEFAULT_PLUG_DEVICE_INFO =
    "22:01:00^Going Home^0\n"       // Scene
    "08:04:06^Color Light^0\n"     // Light
    "b0:01:07^Curtain^0\n"        // Curtain
    "21:01:0B^Air Conditioner^0^0\n"  // Air conditioner
    "b2:01:10^1-Way Switch^0\n";   // Switch

parse_config_file() reads this configuration, parses it into device_info_t and adds to the device list, then sets state to PLUGIN_STATE_LOGGED and calls notify_devices_change() to report.


11. Platform Utility Interfaces

The RTOS platform provides the following utility interfaces for convenient plugin development.

11.1 Unbind and Reboot

When unbinding/logging out, the application usually needs to restart. Call:

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 Get IP / MAC Address

The platform has implemented network information retrieval interfaces (declared in platform header files ssutils.h / ss_deviceinfo.h, can be called directly after extern declaration in the plugin):

// Get IP address, name is network interface name (ignored on RTOS side, always gets WiFi STA IP)
// Returns 0 on success, ip like "192.168.1.100"
extern int ssutils_get_ip_address(char* name, char* ip);

// Get MAC address, name is network interface name (ignored on RTOS side, always gets WiFi STA MAC)
// format=0: "aa:bb:cc:dd:ee:ff", buffer needs 18 bytes
// format=1: "aabbccddeeff", buffer needs 13 bytes
extern int ssutils_get_mac_addr(char* name, char* mac, int format);

// Convenience interface: get MAC without colons (equivalent to ssutils_get_mac_addr(name, sn, 1))
extern int ss_deviceinfo_get_mac(char* sn);

Example:

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 Requests

The platform has a built-in HTTP client (asynchronous). Plugins can call it directly; callbacks execute in the HTTP service thread:

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 is JSON string
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 raw data
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);

Callback prototype: after response arrives, callback on_result(context, size, data) is invoked, data is the response body (string), size is the length, context is the user pointer passed during the call (passed through unchanged).

Example (POST JSON, with MD5 signature, see 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;   // Response body, parse with cJSON_Parse
  cJSON* json = cJSON_Parse(json_str);
  // ... process response
  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

// Calculate MD5 of buffer, result output as 32-char text (needs 33-byte buffer, including '\0')
extern int get_buffer_md5sum_text(char* buffer, unsigned int size, unsigned char* result);

Usage reference: see signature calculation in 11.4 example.

11.6 MQTT

The RTOS platform provides a lightweight MQTT client (mqtt_client.h), running internally as a separate thread. Interfaces:

typedef void (*cb_on_mqtt_connect)(int is_connected);
typedef void (*cb_on_mqtt_message)(char* topic, char* payload, int len);

// Start MQTT service and connect; if sub_info is non-NULL, auto-subscribe
// Returns MQTT instance pointer, NULL on failure
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);  // Subscribe
int  mqtt_client_publish(struct cmd_mqtt_common* inst, char* topic, char* message);        // Async publish
int  mqtt_client_publish_sync(struct cmd_mqtt_common* inst, char* topic, char* message);   // Sync publish
void mqtt_client_connect(struct cmd_mqtt_common* inst);    // Connect
void mqtt_client_disconnect(struct cmd_mqtt_common* inst); // Disconnect
int  mqtt_client_is_connecting(struct cmd_mqtt_common* inst);
void mqtt_client_stop(struct cmd_mqtt_common* inst);       // Stop and release resources

Parameter format is space-separated key=value strings (consistent with serial debug commands):

Parameter Supported Keys
init_config host, port, client_id, username, password, alive (heartbeat seconds), ssl (0/1), clean (0/1), will_topic, will_message
sub_info qos, topic

Example:

static void on_mqtt_connect(int is_connected) {
  // is_connected == 1 means connection successful, can subscribe to topics here
}

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);

  // Subscribe (can also be called in the connection success callback)
  mqtt_client_subscribe(mqtt, "qos=0 topic=zhiju/zhiju_switch_wr10/R1009181328178345312/command/down");

  // Publish
  mqtt_client_publish(mqtt, "zhiju/zhiju_switch_wr10/R1009181328178345312/message/up", "{\"state\":1}");
}

11.7 UART Example Code

Serial communication example code: Download


results matching ""

    No results matching ""