LiteOS雲端對接教程09-LiteOS基於LWM2M對接華爲OC平臺實戰

1. LiteOS OC lwm2m 抽象組件

概述

爲了適應各種各樣的使用lwm2m接入華爲OC的模式,特採用該層次接口,對上提供應用所需的接口,對下允許接入方式的靈活適配。

oclwm2magent是處理使用lwm2m協議對接華爲OC的流程抽象層,允許使用流程進行對接,也允許使用NB芯片內置的流程進行對接。對於應用程序開發者而言,無需關注對接流程的實現細節,僅僅需要調用該模塊提供的api即可。

OC lwm2m AL的api接口聲明在中,使用相關的接口需要包含該頭文件。

配置並連接

對接服務器的所有信息保存在結構體oc_config_param_t中,其定義在oc_lwm2m_al.h中,如下:

typedef struct
{
    en_oc_boot_strap_mode_t  boot_mode;       ///< bootmode,if boot client_initialize, then the bs must be set
    oc_server_t              boot_server;     ///< which will be used by the bootstrap, if not, set NULL here
    oc_server_t              app_server;      ///< if factory or smart boot, must be set here
    fn_oc_lwm2m_msg_deal     rcv_func;        ///< receive function caller here
    void                    *usr_data;        ///< used for the user
}oc_config_param_t;

其中boot_mode是對接模式,對應華爲平臺的三種模式:

typedef enum
{
    en_oc_boot_strap_mode_factory = 0,
    en_oc_boot_strap_mode_client_initialize,
    en_oc_boot_strap_mode_sequence,
} en_oc_boot_strap_mode_t;

app_server參數是服務器信息,定義如下:

typedef struct
{
    char *ep_id;                  ///< endpoint identifier, which could be recognized by the server
    char *address;                ///< server address,maybe domain name
    char *port;                   ///< server port
    char *psk_id;                 ///< server encode by psk, if not set NULL here
    char *psk;
    int   psk_len;
} oc_server_t;

參數說明如下:

  • ep_id:設備標識符
  • address:服務器地址
  • port:服務器端口
  • psk_id:DTLS使用,不使用的話設置爲NULL

rcv_func是回調函數的函數指針,當設備接收到lwm2m消息後回調:

typedef int (*fn_oc_lwm2m_msg_deal)(void *usr_data, en_oc_lwm2m_msg_t type, void *msg, int len);

在配置結構體完成之後,調用配置函數進行配置並連接,API如下:

/**
 * @brief the application use this function to configure the lwm2m agent
 * @param[in] param, refer to oc_config_param_t
 * @return  the context, while NULL means failed
 */
void* oc_lwm2m_config(oc_config_param_t *param);

函數參數很清楚,將存放對接信息的結構體指針傳入即可,其中handle是oc lwm2m handle指針,後續使用。

數據上報

連接成功之後,因爲平臺部署了編解碼插件,直接向華爲雲平臺上報二進制數據即可,oc_lwm2m提供的API如下:

/**
 * @brief the application use this function to send the message to the cdp
 * @param[in] hanlde, returned by the config
 * @param[in] buf the message to send
 * @param[in] len the message length
 * @param[in] timeout block time
 *
 * @return 0 success while <0 failed
 */
int oc_lwm2m_report(void *context, char *buf, int len, int timeout);

命令接收

當OC平臺發佈該主題數據時,oc_lwm2m組件會拉起接收回調函數將數據保存,進而用戶解析接收到的數據即可。

oc_lwm2m組件自動初始化

在SDK目錄中的IoT_LINK_1.0.0iot_linklink_main.c中可以看到自動初始化函數:

2. 配置準備

Makefile配置

因爲本次實驗用到的組件較多:

  • AT框架
  • ESP8266設備驅動
  • 串口驅動框架
  • SAL組件
  • lwm2m組件
  • oc_lwm2m組件

這些實驗代碼全部編譯下來,有350KB,而小熊派開發板所使用的主控芯片STM32L431RCT6的 Flash 僅有256KB,會導致編譯器無法鏈接出可執行文件,所以要在makefile中修改優化選項,修改爲-Os參數,即最大限度的優化代碼尺寸,並去掉-g參數,即代碼只能下載運行,無法調試,如圖:

ESP8266設備配置

在工程目錄中的OS_CONFIG/iot_link_config.h文件中,配置ESP8266設備的波特率和設備名稱:

WIFI對接信息配置

SDK:C:UsersAdministrator.icodesdkIoT_LINK_1.0.0(其中Administrator是實驗電腦的用戶名)。

在SDK目錄中的iot_linknetworktcpipesp8266_socketesp8266_socket_imp.c文件中,配置連接信息:

之後修改同路徑下的esp8266_socket_imp.mk文件,如圖,將 TOPDIR 改爲 SDKDIR :

3. 上雲實驗

編寫實驗文件

在 Demo 文件夾下創建cloud_test_demo文件夾,在其中創建oc_lwm2m_demo.c文件。

編寫以下代碼:

#include <osal.h>
#include <oc_lwm2m_al.h>
#include <link_endian.h>
#include <string.h>

#define cn_endpoint_id        "867725038317248"
#define cn_app_server         "49.4.85.232"
#define cn_app_port           "5683"

#define cn_app_light           0
#define cn_app_ledcmd          1

#pragma pack(1)

typedef struct
{
    int8_t msgid;
    int16_t intensity;
}app_light_intensity_t;


typedef struct
{
    int8_t msgid;
    char led[3];
}app_led_cmd_t;

#pragma pack()

#define cn_app_rcv_buf_len 128
static int8_t          s_rcv_buffer[cn_app_rcv_buf_len];
static int             s_rcv_datalen;
static osal_semp_t     s_rcv_sync;

static void           *s_lwm2m_handle = NULL;

static int app_msg_deal(void *usr_data,en_oc_lwm2m_msg_t type, void *msg, int len)
{
    int ret = -1;

    if(len <= cn_app_rcv_buf_len)
    {
        memcpy(s_rcv_buffer,msg,len);
        s_rcv_datalen = len;

        osal_semp_post(s_rcv_sync);

        ret = 0;

    }
    return ret;
}


static int app_cmd_task_entry()
{
    int ret = -1;
    app_led_cmd_t *led_cmd;
    int8_t msgid;

    while(1)
    {
        if(osal_semp_pend(s_rcv_sync,cn_osal_timeout_forever))
        {
            msgid = s_rcv_buffer[0];
            switch (msgid)
            {
                case cn_app_ledcmd:
                    led_cmd = (app_led_cmd_t *)s_rcv_buffer;
                    printf("LEDCMD:msgid:%d msg:%s \n\r",led_cmd->msgid,led_cmd->led);
                    
                    if (led_cmd->led[0] == 'o' && led_cmd->led[1] == 'n')
                    {
                        printf("--------------- LED ON! --------------------\r\n");
                    }

                    else if (led_cmd->led[0] == 'o' && led_cmd->led[1] == 'f' && led_cmd->led[2] == 'f')
                    {
                        printf("--------------- LED OFF! --------------------\r\n");
                    }
                    else
                    {

                    }
                    break;
                default:
                    break;
            }
        }
    }

    return ret;
}



static int app_report_task_entry()
{
    int ret = 0;
    int lux = 0;

    oc_config_param_t      oc_param;
    app_light_intensity_t  light;

    memset(&oc_param,0,sizeof(oc_param));

    oc_param.app_server.address = cn_app_server;
    oc_param.app_server.port = cn_app_port;
    oc_param.app_server.ep_id = cn_endpoint_id;
    oc_param.boot_mode = en_oc_boot_strap_mode_factory;
    oc_param.rcv_func = app_msg_deal;

    s_lwm2m_handle = oc_lwm2m_config(&oc_param);
    if(NULL != s_lwm2m_handle)  
    {
        while(1)
        {
            lux  ;
            lux= lux000;

            light.msgid = cn_app_light;
            light.intensity = htons(lux);
            oc_lwm2m_report(s_lwm2m_handle,(char *)&light,sizeof(light),1000);
            osal_task_sleep(2*1000);
        }
    }

    return ret;
}

int standard_app_demo_main()
{
    osal_semp_create(&s_rcv_sync,1,0);

    osal_task_create("app_report",app_report_task_entry,NULL,0x1000,NULL,2);
    osal_task_create("app_command",app_cmd_task_entry,NULL,0x1000,NULL,3);

    return 0;
}

添加路徑

在user_demo.mk中添加如下:

    #example for oc_lwm2m_demo
    ifeq ($(CONFIG_USER_DEMO), "oc_lwm2m_demo")    
        user_demo_src  = ${wildcard $(TOP_DIR)/targets/STM32L431_BearPi/Demos/cloud_test_demo/oc_lwm2m_demo.c}
    endif

添加位置如下:

配置.sdkconfig

上報數據實驗結果

編譯,下載,在雲端的實驗現象如下:

命令下發實驗結果

在雲端下發“on”命令:

在串口助手中可以看到:

下發“off”命令:

在串口助手中可以看到:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章