zoukankan      html  css  js  c++  java
  • LiteOS云端对接教程09-LiteOS基于LWM2M对接华为OC平台实战

    1. LiteOS OC lwm2m 抽象组件

    概述

    为了适应各种各样的使用lwm2m接入华为OC的模式,特采用该层次接口,对上提供应用所需的接口,对下允许接入方式的灵活适配。

    oc_lwm2m_agent是处理使用lwm2m协议对接华为OC的流程抽象层,允许使用流程进行对接,也允许使用NB芯片内置的流程进行对接。对于应用程序开发者而言,无需关注对接流程的实现细节,仅仅需要调用该模块提供的api即可。

    OC lwm2m AL的api接口声明在<oc_lwm2m_al.h>中,使用相关的接口需要包含该头文件。

    配置并连接

    对接服务器的所有信息保存在结构体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_link etwork cpipesp8266_socketesp8266_socket_imp.c文件中,配置连接信息:

    之后修改同路径下的esp8266_socket_imp.mk文件,如图,将 TOP_DIR 改为 SDK_DIR :

    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 
    
    ",led_cmd->msgid,led_cmd->led);
                        
                        if (led_cmd->led[0] == 'o' && led_cmd->led[1] == 'n')
                        {
                            printf("--------------- LED ON! --------------------
    ");
                        }
    
                        else if (led_cmd->led[0] == 'o' && led_cmd->led[1] == 'f' && led_cmd->led[2] == 'f')
                        {
                            printf("--------------- LED OFF! --------------------
    ");
                        }
                        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= lux%10000;
    
                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”命令:

    在串口助手中可以看到:

  • 相关阅读:
    CSS3 target伪类简介
    不用position,让div垂直居中
    css3 在线编辑工具 连兼容都写好了
    a标签伪类的顺序
    oncopy和onpaste
    【leetcode】1523. Count Odd Numbers in an Interval Range
    【leetcode】1518. Water Bottles
    【leetcode】1514. Path with Maximum Probability
    【leetcode】1513. Number of Substrings With Only 1s
    【leetcode】1512. Number of Good Pairs
  • 原文地址:https://www.cnblogs.com/bearpi/p/12383274.html
Copyright © 2011-2022 走看看