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”命令:

    在串口助手中可以看到:

  • 相关阅读:
    not syncing: Attempted to kill init
    PhpStudy如何开启Apache的gzip压缩功能?
    去掉桌面图标快捷箭头
    PS中10种样式操作
    Mysql数据库报错1264
    宝塔建站
    VB错误说明
    Flash的swf文件破解
    PS快捷键
    Mysql双向同步热备份设置
  • 原文地址:https://www.cnblogs.com/bearpi/p/12383274.html
Copyright © 2011-2022 走看看