The official series of coerced death! SDK framework based on sddc protocol_ sdk_ Lib parsing

Keywords: IoT

SDK framework based on sddc protocol_ sdk_ Lib parsing

Previously, when porting libsddc library, I felt that the official demo was too inefficient ( ̄.  ̄). I was tired of copying and pasting code, and wrote a BUG, and the other copied code cracked, so I wrote an sddc_sdk_lib library to make sddc access devices faster and more effective. This paper mainly explains the structure of this library and the new device quickly uses sddc to access Spirit 1 through this library, so as to become an intelligent device. ヽ(・ ω・ ´メ)

For the introduction of SDDC protocol, please refer to: It unifies the introduction of cross vendor discovery and control DDC protocol used in WiFi and ZigBee upper layer

Current sddc_sdk_lib supports three platforms, namely, MS-RTOS for Yihui information release, which proposes sddc protocol, ESP platform of Anxin based on FreeRTOS, and Arduino platform, which is popular recently (this is a good thing. After getting used to Arduino, I don't want to use the traditional platform at all), as usual The secret treasure house of inspiration desktop .

SDDC structure and definition of various equipment

In SDDC_ SDK_ In lib. H, the overall structure of SDDC is described as follows:

/*********************************************************************************************************
   SDDC Overall structure description
*********************************************************************************************************/
typedef struct {
    char             *token;
    DEV_INFO         *devinfo;
    IO_DEV_REGINFO   *io_dev_reg;
    int              io_dev_reg_num;
    NUM_DEV_REGINFO  *num_dev_reg;
    int              num_dev_reg_num;
    DEV_STATE_GET    *state_get_reg;
    int              state_get_reg_num;
    DIS_DEV_REGINFO  *dis_dev_reg;
    int              dis_dev_num;
} SDDC_CONFIG_INFO;

Where dev_ The content in info is the information reported to Spirit 1 through SDDC, such as device name, device type, description, etc

/*********************************************************************************************************
   SDDC Description of equipment information involved in information reporting
*********************************************************************************************************/
typedef struct {
    char      *name;
    char      *type;
    sddc_bool_t excl;
    char      *desc;
    char      *model;
    char      *vendor;
} DEV_INFO;

IO_DEV_REGINFO,NUM_DEV_REGINFO,DIS_DEV_REGINFO is the description of IO type, digital type and display type equipment, including object name and corresponding Set function;

/*********************************************************************************************************
   SDDC The registration structure of IO devices inside
*********************************************************************************************************/
typedef struct {
    char    *objname;
    Io_Set  IO_Fun;
} IO_DEV_REGINFO;

/*********************************************************************************************************
   SDDC The registration structure of digital equipment inside
*********************************************************************************************************/
typedef struct {
    char     *objname;
    Num_Set  Num_Fun;
} NUM_DEV_REGINFO;

/*********************************************************************************************************
   SDDC It displays the registration structure of class devices
*********************************************************************************************************/
typedef struct {
    char     *objname;
    Dis_Set  Dis_Fun;
} DIS_DEV_REGINFO;

DEV_STATE_GET is the set of get functions for all device objects;

/*********************************************************************************************************
   SDDC Result query class function registration structure
*********************************************************************************************************/
#define DEV_IO_TYPE       0
#define DEV_NUM_TYPE      1
#define DEV_DISPLAY_TYPE  2

typedef struct {
    char       *objname;
    int        type;
    STATE_GET  state_fun;
} DEV_STATE_GET;

SDDC protocol and extended structure implementation function

stay It unifies the introduction of cross vendor discovery and control DDC protocol used in WiFi and ZigBee upper layer This article introduces the specific protocol flow, following the official libsddc demo in SDDC_SDK_lib.c is about the implementation function of SDDC communication protocol, in which the connection related functions don't need to pay much attention. The main one is sddc_on_message_lib function, which is the entry of business communication with Spirit 1. Match get or set according to the method field in the message, and then call the corresponding processing function. Combined with the overall structure of SDDC, it can be seen that all types of devices share the same get interface, and the set interface has different processing functions according to different device types, In fact, the SDDC in the official demo_ on_ The message function abstracts all the messages that may be received, thus eliminating the steps of writing and parsing messages.

Super awesome, super convenient, isn't it? Next, let's accept the extended structure and use of the SDK:

/*********************************************************************************************************
** Function name: sddc_on_message_lib
** Function Description: callback function for processing messages received by SDDC protocol
** Input: SDDC structure
**           uid           ID of the message sent
**           message       Received message
**           len           packet length 
** Output: 0: processing failed, 1: Processing succeeded
** Global variables:
** Calling module: None
*********************************************************************************************************/
static sddc_bool_t sddc_on_message_lib(sddc_t *sddc, const uint8_t *uid, const char *message, uint32_t len)
{
    cJSON   *root    = cJSON_Parse(message);
    cJSON   *Json_method;
    uint8_t uimethod =DDC_METHOD_VALIDE;

    Json_method = cJSON_GetObjectItem(root, "method");
    if (NULL == Json_method) {
        return SDDC_FALSE;
    }

    if (cJSON_IsString(Json_method)) {
        if (strcmp(Json_method->valuestring,"set") == 0) {
            uimethod = DDC_METHOD_SET;
        } else if (strcmp(Json_method->valuestring,"get") == 0) {
            uimethod = DDC_METHOD_GET;
        } else {
            return SDDC_FALSE;
        }
    } else {
        return SDDC_FALSE;
    }

    if (uimethod == DDC_METHOD_VALIDE) {
        return SDDC_FALSE;
    }

    if (uimethod == DDC_METHOD_SET) {
        int i;

        /*
         *  The digital quantity and display quantity shall be queried and set first to prevent the switching quantity from being the enabling of the equipment
         */
        for (i=0; i<G_config->num_dev_reg_num; i++) {
            object_Number_Set(root, G_config->num_dev_reg->objname, G_config->num_dev_reg->Num_Fun);
        }

        for (i=0; i<G_config->dis_dev_num; i++) {
            object_Display_Set(root, G_config->dis_dev_reg->objname, G_config->dis_dev_reg->Dis_Fun);
        }

        for (i=0; i<G_config->io_dev_reg_num; i++) {
            object_IO_Set(root, G_config->io_dev_reg->objname, G_config->io_dev_reg->IO_Fun);
        }
    } else if (uimethod == DDC_METHOD_GET) {
        object_get(sddc, uid, root, G_config->state_get_reg, G_config->state_get_reg_num);
    } else {
        return SDDC_FALSE;
    }

    return SDDC_TRUE;
}

The library also provides an interface for actively reporting messages, as follows. Note that the format of input parameters should comply with the specification (key! Knock the blackboard!
):

/*********************************************************************************************************
** Function name: object_report
** Function Description: a reporting interface encapsulated for external users
** Input: reportlist the content list reported in the format of {obj:"LED1","LED2","TMP"}
** Output: 0: processing failed, 1: Processing succeeded
** Global variables:
** Calling module: None
*********************************************************************************************************/
int object_report(cJSON *reportlist)
{
    if (NULL == G_sddc) {
        return SDDC_FALSE;
    }

    return object_get(G_sddc, NULL, reportlist, G_config->state_get_reg, G_config->state_get_reg_num);
}

This function can be used to quickly implement the input parameters of a standard active reporting message interface:

/* 
 *  Active data reporting function
 */
static void report_sensor()
{  
    int sensorValue = 0;
    cJSON *value;
    cJSON *root;
    // char  *msg;
     
    value =  cJSON_CreateArray();
    root = cJSON_CreateObject();
    sddc_return_if_fail(value);
    sddc_return_if_fail(root);
            
    // Generate required parameters in format
    cJSON_AddItemToArray(value, cJSON_CreateString("Report data 1 "));    // The string here should correspond to the string in the system object state acquisition registration structure
    // cJSON_AddItemToArray(value, cJSON_CreateString("submit data 2")); / / add as many as you need to submit  
    cJSON_AddItemToObject(root, "obj", value);
      
    // Send data to EdgerOS
    // msg = cJSON_Print(root);
    // printf("trigger escalation:% s\n",msg);
    object_report(root);
      
    cJSON_Delete(value);
    cJSON_free(msg);
}

Fast access using DEMO

Next, let's teach you how to quickly use this SDK to develop access devices (✪ ω ✪).

First, define the contents of dev_info completed by the device, and then define different types of objects required by the device, either a device has only one object or a complex device corresponds to multiple objects. According to these, the construction of various types of objects and the registration of set and get functions are completed.

/*********************************************************************************************************
   Information definition of the current device
*********************************************************************************************************/
DEV_INFO    dev_info = {
            .name     = "InfraredSensor",                                     // Device name, which is the name you search for when you add a device
            .type     = "device",                                             // Equipment type. The application side needs to distinguish equipment types through this
            .excl     = SDDC_FALSE,
            .desc     = "Infrared sensor based on nodemcu",
            .model    = "1",
            .vendor   = "inspiration-desktop",                                // Your name
};

/*********************************************************************************************************
   IO Device object setting function and processing method registration
*********************************************************************************************************/
IO_DEV_REGINFO io_dev[] = { // Register IO(string type) message set processing function
		{"attr1", NULL},  
		{"attr2", NULL},  
};

/*********************************************************************************************************
   Registration of object function and processing method of digital quantity equipment
*********************************************************************************************************/
NUM_DEV_REGINFO num_dev[] = { // Register the message set processing function of digital quantity (int,float, etc.)
		{"attr1", NULL},  
		{"attr2", NULL},  
};

/*********************************************************************************************************
   Display device object function and processing method registration
*********************************************************************************************************/
DIS_DEV_REGINFO dis_dev[] = { // Register the message set processing function of the display device (screen, etc.)
		{"attr1", NULL},  
		{"attr2", NULL},  
};

/*********************************************************************************************************
   System object status get registration
*********************************************************************************************************/
DEV_STATE_GET  dev_state_get_reg[] = {
		{"attr1", DEV_IO_TYPE, gpio_dev_state_get},        // Register get handler
		{"attr2", DEV_IO_TYPE, gpio_dev_state_get},        // Register get handler
};

/*********************************************************************************************************
   System registration object aggregation
*********************************************************************************************************/
SDDC_CONFIG_INFO sys_cfg = {
        .token             = "12345678",
        .devinfo           = &dev_info,
        .io_dev_reg        = io_dev,
        .io_dev_reg_num    = MS_ARRAY_SIZE(io_dev),
        .num_dev_reg       = num_dev,
        .num_dev_reg_num   = MS_ARRAY_SIZE(num_dev),
        .state_get_reg     = dev_state_get_reg,
        .state_get_reg_num = MS_ARRAY_SIZE(dev_state_get_reg),
        .dis_dev_reg       = dis_dev,
        .dis_dev_num       = MS_ARRAY_SIZE(dis_dev),
};

As for the relevant set, get functions and initialization operations, different implementations need to be completed according to different devices. Then, execute sddc_lib_main in the main function with sys_cfg as a parameter to start SDDC and complete the relevant configuration. The following is the main function code on the Anxin platform based on FreeRTOS:

int app_main (int argc, char **argv)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    ESP_ERROR_CHECK(example_connect());

    gpio_dev_init();

    while (1) {
        sddc_lib_main(&sys_cfg);
    }

    return  (0);
}

For the Arduino platform, because the main function structure is divided into setup() and loop(), part of the code can not be invoked in the library, the specific code is as follows:

void setup() {
    byte mac[6];
    
    uart_dev_init();
    
    // Start WiFi and connect to the network
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
    {
        delay(500);
        Serial.print(".");
    }
  
    // Get and print IP address
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.print("'ip :");
    Serial.print(WiFi.localIP());
    Serial.println("' to connect"); 
  
    // Clear the state of the key state machine
    button.reset();
  
    // Create a key scanning thread, long press the IO0 key, and the ESP32 will enter the SmartConfig mode after releasing it
    sddc_printf("Press and hold the key to enter Smartconfig...\n");
    button.attachLongPressStop(esp_io0_key_task);
    xTaskCreate(esp_tick_task, "button_tick", ESP_TASK_STACK_SIZE, NULL, ESP_TASK_PRIO, NULL);

    // sddc protocol initialization
    sddc_lib_main(&sys_cfg);

    // Obtain and print the mac address of the network card
    WiFi.macAddress(mac);
    sddc_printf("MAC addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
              mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
    // Use the network card mac address to set the device unique ID UID
    sddc_set_uid(G_sddc, mac);
}

void loop() {
  
  // Run SDDC protocol cycle
    while (1) 
    {
        sddc_printf("SDDC running...\n");
        sddc_run(G_sddc);
        sddc_printf("SDDC quit!\n");
    }

    // Destroy SDDC protocol
    sddc_destroy(G_sddc);
}

This article is only for personal learning and use. If there are errors, please correct them ˙ ᗜ ˙ ) Thank you, boss!

Posted by David03 on Tue, 21 Sep 2021 18:28:08 -0700