更新时间:2023-04-07 GMT+08:00
分享

Agent Lite SDK使用指南(C)(联通用户专用)

非联通用户请查看设备接入服务

按照本文档的指导,开发者可以体验直连设备通过集成Agent Lite快速接入平台,体验“数据上报”“命令接收”“添加非直连设备”等功能。

Agent Lite以SDK的形式嵌入第三方软件中。本文档以Agent Lite Linux Demo为例,指导开发者使用Agent Lite SDK中的接口,实现“直连设备登录”“数据上报”“命令下发”等功能。

  • 开发者可以基于Agent Lite Linux Demo开发,也可参考Agent Lite Linux Demo,自行集成Agent Lite SDK(Linux)。
  • Agent Lite Linux Demo使用的IDE工具为Visual Studio。开发者可以使用其他IDE工具。

使用必读

开发环境要求

操作系统

工具链

当前支持的系统:

  • ARM Linux (Embedded Linux)
  • MIPS Linux (Embedded Linux)
  • x86 Linux
  • x86_64 Linux
  • x86 Windows
  • x86_64 Windows

需要支持以下工具链之一:

  • gcc-linaro-arm-linux-gnueabihf-raspbian
  • arm-none-linux-gnueabi
  • arm-linux-uclibceabi

Demo工程目录结构及文件说明

目录结构

目录

说明

Demo

├─demo.c

├─demo.h

├─*.h

├─libcrypto.so/libssl.so

├─libuspsdk.so

└─conf

demo.c

demo源文件

demo.h

demo头文件

*.h

Agent Lite头文件

libcrypto.so/libssl.so

openssl库文件

libuspsdk.so

Agent Lite编译后的库文件

conf

存放TLS证书文件

如果开发者没有设备,可以直接在X86 Linux系统进行开发。

交叉编译环境检测

  1. 准备网关或设备。本文档将以树莓派为例,说明如何集成网关。
  2. 将Agent Lite SDK (Linux)解压到本地。

  3. 用sftp工具把mytest测试工具上传到树莓派上。

    因为使用的设备是树莓派,所以使用RaspberryPi目录下的mytest测试工具。开发者可以选择根据实际情况选择不同目录下的mytest测试工具进行测试,尽量选择与自己的系统信息相近的目录下的测试工具进行测试。

  4. 修改所有文件的权限,进入mytest所在目录,运行“mytest”

    1
    2
    3
    cd /opt/agentLite
    chmod -R 777 *
    ./mytest
    

    如果最后出现“AUTO TEST END SUCC”字样,说明通过检测。

导入样例代码

在交叉编译环境检测通过后,再进行设备集成开发。下面将以Agent Lite Gateway Demo(C)中的样例代码为例,说明如何进行Agent Lite SDK的集成。

  1. Agent Lite Demo(C-Linux)压缩包中的Agent Lite Gateway Demo(C)解压到本地。

  2. 将SDK库中的头文件和so库都放到“Agent Lite Gateway Demo(C)/linux/demo”目录下。

    因为使用的设备是树莓派,所以使用RaspberryPi目录下的库。

  3. 打开Visual Studio,选择File > Open > Project/Solution

  4. 进入“Agent Lite Gateway Demo(C)/linux”目录,选择“agentLiteDemo.sln”,点击“打开”按钮即可。

    在Solution Explorer窗口中,双击打开“demo.c”文件。

初始化

在发起业务前,需要先初始化Agent Lite相关资源,调用API接口IOTA_Init(),初始化Agent Lite资源。具体API接口的参数使用请参考Agent Lite API接口文档。可参考demo.c中main()方法对IOTA_Init()的调用。

1
IOTA_Init(const CONFIG_PATH,const HW_NULL);
  • “CONFIG_PATH”为工作路径,不能为空,该参数必须带结束符‘\0’。
  • 第二个参数为打印日志路径,当它为空时,打印路径默认为工作路径。开发者也可以自己定义打印日志路径,该参数必须带结束符‘\0’。

绑定和登录

设备或网关第一次接入物联网平台时需要进行绑定操作,从而将设备或网关与平台进行关联。开发者通过传入设备序列号以及设备信息,将设备或网关绑定到物联网平台。

设备或网关绑定成功后或重启后,需要进行登录的流程,在设备或网关成功登录物联网平台后,才可以进行其它服务操作,比如接入其他传感器,数据上报等等。如果设备或网关登录成功,那么设备或网关在平台的状态显示为已在线。

  1. 修改绑定参数。

    绑定时使用的设备固有信息(如设备型号等)是从“gwreginfo.json”文件中读取的,所以需要修改demo目录下“gwreginfo.json”文件中的如下信息:
    • “platformaddr”:物联网平台的设备对接地址(MQTTS),可参考平台对接信息获取。
    • “mac”:MAC地址,每个设备对应一个MAC地址,不可重复,所以建议使用IMEI或者MAC地址等天然的设备标识。测试时只要输入一个没有使用过的MAC地址即可。
      • 如果开发者通过“设备管理服务控制台”注册设备,则“mac”填写为设备注册时的“preSecret”(预置密钥)。
      • 如果通过开发中心注册设备,则“verifyCode”填写为设备注册时设置的“nodeId”(设备标识)。
    • “manufacturerId”(厂商Id)、“deviceType”(设备类型)、“model”(设备模型)和“protocolType”(协议类型)与Profile文件中的定义保持一致。

    “gwreginfo.json”文件中设备固有示例:

    {
        "mac":"1234567",
        "platformAddr":"127.0.0.1",
        "platformPort":8943,
        "manufacturerId":"Huawei",
        "deviceType":"Gateway",
        "model":"AgentLite01",
        "protocolType":"HuaweiM2M",
        "loglevel":255
    }

  2. 绑定设备。

    绑定前先调用API接口IOTA_ConfigSetXXX()设置物联网平台的IP与端口。

    1
    2
    IOTA_ConfigSetStr(EN_IOTA_CFG_IOCM_ADDR, const pucPlatformAddr);
    IOTA_ConfigSetUint(EN_IOTA_CFG_IOCM_PORT, uiPort);
    

    注册广播接收器对设备绑定结果进行相应处理。

    1
    HW_BroadCastReg(IOTA_TOPIC_BIND_RSP, Device_RegResultHandler);
    

    调用API接口IOTA_Bind()进行设备绑定,主要入参为MAC地址和必要的设备信息,包括“nodeId”(设备标识码)、“manufacturerId”(厂商Id)、“deviceType”(设备类型)、“model”(设备模型)和“protocolType”(协议类型),其中MAC地址与“nodeId”的值保持一致。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    HW_UINT DEVICE_BindGateWay()
    {
        ……
        stDeviceInfo.pcMac = HW_JsonGetStr(json, IOTA_DEVICE_MAC);
        stDeviceInfo.pcNodeId = stDeviceInfo.pcMac;
        stDeviceInfo.pcManufacturerId = HW_JsonGetStr(json, IOTA_MANUFACTURE_ID);
        stDeviceInfo.pcDeviceType = HW_JsonGetStr(json, IOTA_DEVICE_TYPE);
        stDeviceInfo.pcModel = HW_JsonGetStr(json, IOTA_MODEL);
        stDeviceInfo.pcProtocolType = HW_JsonGetStr(json, IOTA_PROTOCOL_TYPE);
        ……
        IOTA_ConfigSetStr(EN_IOTA_CFG_IOCM_ADDR, pucPlatformAddr);
        IOTA_ConfigSetUint(EN_IOTA_CFG_IOCM_PORT, uiPort);
        IOTA_Bind(stDeviceInfo.pcMac, &stDeviceInfo);
    }
    

    设备或网关绑定成功,后续就不需要再绑定了,除非设备或网关被删除,才需要重新绑定。

    设备绑定成功会收到广播,广播内容请参考Agent Lite API接口文档中设备绑定接口的返回结果说明和demo中Device_RegResultHandler函数的处理。Device_RegResultHandler把从广播中得到的网关设备信息保存在“gwbindinfo.json”文件中。

  3. 配置登录参数。

    登录前需要通过参数配置API接口IOTA_ConfigSetXXX()传入所需的登录信息。

    • “设备Id”“EN_IOTA_CFG_DEVICEID”),“appId”“EN_IOTA_CFG_APPID”)和“密码”“EN_IOTA_CFG_DEVICESECRET”)从绑定成功的广播中得到的。
    • “HTTP地址”“EN_IOTA_CFG_IOCM_ADDR”)和“MQTT地址”“EN_IOTA_CFG_MQTT_ADDR”)一般为同一个地址,可以从绑定成功的广播中得到。一般情况下,这个地址和Agent Lite设备或网关对接的平台地址一致。
    • 绑定成功的广播参数获取可以参考Device_RegResultHandler函数的处理。
    1
    2
    3
    4
    5
    6
    7
    IOTA_ConfigSetStr(EN_IOTA_CFG_DEVICEID, g_stGateWayInfo.pcDeviceID);  
    IOTA_ConfigSetStr(EN_IOTA_CFG_IOCM_ADDR, g_stGateWayInfo.pcIOCMAddr);
    IOTA_ConfigSetStr(EN_IOTA_CFG_APPID, g_stGateWayInfo.pcAppID);
    IOTA_ConfigSetStr(EN_IOTA_CFG_DEVICESECRET, g_stGateWayInfo.pcSecret);          
    IOTA_ConfigSetStr(EN_IOTA_CFG_MQTT_ADDR, g_stGateWayInfo.pcIOCMAddr);
    IOTA_ConfigSetUint(EN_IOTA_CFG_MQTT_PORT, g_stGateWayInfo.pcMqttPort);
    IOTA_ConfigSetUint(EN_IOTA_CFG_IOCM_PORT, g_stGateWayInfo.pcIOCMPort);
    

    注册广播接收器对设备登录结果进行相应处理。

    1
    HW_BroadCastReg(IOTA_TOPIC_CONNECTED_NTY, Device_ConnectedHandler);
    

  4. 设备登录。

    调用API接口LoginService.login()进行直连设备登录,具体API的参数使用参考Agent Lite API接口文档中设备登录接口的说明。

    1
    IOTA_Login();
    

编译并运行程序

绑定和登录功能完成后,可以先测试一下设备或网关是否能正常与平台对接,再进行后续功能开发。

  1. 用sftp工具把demo目录上传到树莓派上。

  2. 进行交叉编译。

    1. 进入“/opt/agentLite/demo/”路径。

      “/opt/agentLite/demo/”路径需要根据实际情况修改。

    2. 输入“chmod -R 777 *”命令修改权限。
    3. 输入“export LD_LIBRARY_PATH=./”设置程序共享库位置。
    4. 输入“gcc demo.c -L /opt/agentLite/demo/ -lpthread -ldl -lrt -luspsdk -lssl -lcrypto -o sdk.out”命令,如果交叉编译成功,会产生sdk.out库文件。

      “luspsdk”“lssl”“lcrypto”分别表示库文件“libuspsdk.so”“libssl.so”“libcrypto.so”,具体linux交叉编译命令gcc请开发者自行学习。

  3. 运行Demo。

    启动demo命令为“./ sdk.out”,输入该命令程序就能运行起来了。

    程序运行后,Agent Lite SDK就会主动发送绑定消息给平台。因为此时还没有使用应用侧接口在平台上注册此设备,所以会提示“The device has not registered yet”

上传Profile并注册设备

下载Profile开发示例,并上传模板中的profile文件:“Gateway_Huawei_AgentLite01.zip”“Motion_Huawei_test01.zip”

  1. 登录开发中心,创建一个项目,在该项目空间内,选择产品 > 产品开发,点击“新建产品”

  2. “创建产品”中,选择“本地导入产品创建”,单击“上传Profile”上传“Gateway_Huawei_AgentLite01.zip”“Motion_Huawei_test01.zip”

  3. 选择产品 > 设备管理,单击“添加真实设备”,进入“新建增实设备”页面。

  4. 根据向导注册设备。

    1. 选择产品。

      产品:AgentLite001

    2. 填写设备相关信息,单击“确定”
      • 设备名称:AgentLiteDevice
      • 设备标识:aaa123456,需要与AgentLiteDemo中网关的设备标识一致。
      • 接入方式:网关(Agentlite)

  5. 注册设备后,Agent Lite SDK发送bind消息,则在开发中心的产品 > 设备管理 > 设备列表界面可以看到设备状态变成“在线”

    如果demo日志中出现“Iota_BindDestroy”,说明Agent Lite SDK多次发送bind消息,并且没有收到正确响应,设备绑定已超时。这时需要再次运行“sdk.out”程序(先用“ctrl+c”退出,再用“./sdk.out”运行程序),Agent Lite SDK就会再发起bind消息。平台收到正确的bind消息后设备就会变成“在线”状态。

数据上报和数据发布

设备或网关向物联网平台上报数据可以通过调用SDK的“设备服务数据上报”接口或“数据发布”接口:

  • “设备服务数据上报”接口:pcDeviceId、pcRequstId和pcServiceId由SDK组装为消息的header;pcServiceProperties由SDK组装为消息的body。消息组装格式为JSON。

    设备或网关登录成功后可以调用IOTA_ServiceDataReport接口上报数据

    • 当设备主动上报数据时,“pcRequstId”可以为空。
    • 当上报的数据为某个命令的响应时,“pcRequstId”必须与下发命令中的requstId保持一致。“pcRequestId”可以从广播中获取,请参考API文档中“设备命令接收”接口的“EN_IOTA_DATATRANS_IE_REQUESTID”参数。
    • “pcServiceID”要与Profile中定义的某个“serviceId”保持一致,否则无法上报数据。
    • “pcServiceData”实际上是一个JSON字符串,内容是健值对(可以有多组健值对)。每个健是Profile中定义的属性名(propertyName),值就是具体要上报的数据。
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    HW_VOID Gateway_DataReport(HW_CHAR **pcJsonStr)
    {
        HW_JSON json;
        HW_JSONOBJ hJsonObj;
    
        hJsonObj = HW_JsonObjCreate();
        json = HW_JsonGetJson(hJsonObj);
        HW_JsonAddUint(json, (HW_CHAR*)"storage", (HW_INT)10240);
        HW_JsonAddUint(json, (HW_CHAR*)"usedPercent", (HW_INT)20);
        *pcJsonStr = HW_JsonEncodeStr(hJsonObj);
        Device_ServiceDataReport(g_stGateWayInfo.pcDeviceID, "Storage", pcJsonStr);
        //another method
        //Device_ServiceDataReport(pcDeviceId, "Storage", "{\"storage\":20240,\"usedPercent\":20}");
    }
    HW_INT Device_ServiceDataReport(const HW_CHAR *pcSensorDeviceID, const HW_CHAR *pcServiceId, const HW_CHAR *pcServiceProperties)
    {
        HW_CHAR aszRequestId[BUFF_MAX_LEN];
    
        HW_GetRequestId(aszRequestId);
    
        if (HW_TRUE != g_uiLoginFlg)
        {
            //TODO e.g. resend service data
            HW_LOG_INF("Device_MApiMsgRcvHandler():GW discon,pcJsonStr=%s", pcServiceProperties);
            return HW_ERR;
        }
    
        IOTA_ServiceDataReport(HW_GeneralCookie(), aszRequestId, pcSensorDeviceID, pcServiceId, pcServiceProperties);
        return HW_OK;
    }
    

    注册广播接收器对网关数据上报结果进行相应处理。广播过滤参数为“IOTA_TOPIC_DATATRANS_REPORT_RSP/{deviceId}”

    1
    2
    sprintf(acBuf, "%s/%s", IOTA_TOPIC_DATATRANS_REPORT_RSP, g_stGateWayInfo.pcDeviceID);
    HW_BroadCastReg(acBuf, Device_ServiceDataReportResultHandler);
    

  • “数据发布”接口:topic固定为“/cloud/signaltrans/v2/categories/data”“pbstrServiceData”参数作为消息体(包括header和body),SDK只进行透传,不进行格式调整和组装。

    设备或网关登录成功后可以调用IOTA_MqttDataPub接口发布数据。

    • “pucTopic”为发布数据的topic。
    • “uiQos”为mqtt协议中的一个参数。
    • “pbstrServiceData”实际上是一个json字符串,内容是健值对(可以有多组健值对)。每个健是profile中定义的属性名(propertyName),值就是具体要上报的。
    1
    2
    3
    4
    5
    HW_INT Device_ServiceDataPub(const HW_UCHAR *pucTopic, HW_UINT uiQos, const HW_BYTES *pbstrServiceData)
    { 
        IOTA_MqttDataPub(HW_GeneralCookie(),pucTopic,uiQos,pbstrServiceData);
        return HW_OK;
    }
    

    注册广播接收器对网关数据上报结果进行相应处理。广播过滤参数为“IOTA_TOPIC_DATATRANS_PUB_RSP”

    1
    HW_BroadCastReg(IOTA_TOPIC_DATATRANS_PUB_RSP, Device_ServiceDataPubResultHandler);
    

命令接收

当开发者希望设备或网关只接收topic为“/gws/deviceid/signaltrans/v2/categories/”的消息,且对消息中的header进行解析时,可以调用“设备命令接收”接口

应用服务器可以调用物联网平台的应用侧API接口给设备或网关下发命令,所以设备或网关需要随时检测命令下发的广播,以便在接收到命令时进行相应业务处理。

注册IOTA_TOPIC_SERVICE_COMMAND_RECEIVE/{deviceId}广播接收器对命令下发进行相应处理。

1
2
sprintf(acBuf, "%s/%s", IOTA_TOPIC_SERVICE_COMMAND_RECEIVE, g_stGateWayInfo.pcDeviceID);
HW_BroadCastReg(acBuf, Device_ServiceCommandReceiveHandler);

具体的处理函数Device_ServiceCommandReceiveHandler

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
HW_INT Device_ServiceCommandReceiveHandler(HW_UINT uiCookie, HW_MSG pstMsg)
{
    HW_CHAR *pcDevId;
    HW_CHAR *pcReqId;
    HW_CHAR *pcServiceId;
    HW_CHAR *pcMethod;
    HW_BYTES *pbstrContent;

    pcDevId = HW_MsgGetStr(pstMsg,EN_IOTA_DATATRANS_IE_DEVICEID);
    pcReqId = HW_MsgGetStr(pstMsg,EN_IOTA_DATATRANS_IE_REQUESTID);
    pcServiceId = HW_MsgGetStr(pstMsg,EN_IOTA_DATATRANS_IE_SERVICEID);
    pcMethod = HW_MsgGetStr(pstMsg,EN_IOTA_DATATRANS_IE_METHOD);
    pbstrContent = HW_MsgGetBstr(pstMsg,EN_IOTA_DATATRANS_IE_CMDCONTENT);

    HW_LOG_INF(" -------------- CommandReceiveHandler -------------- DeviceId=%s", pcDevId);

    if ((HW_NULL == pcDevId) ||(HW_NULL == pcReqId) ||(HW_NULL == pcServiceId) ||(HW_NULL == pcMethod))
    {
        HW_LOG_ERR("RcvCmd is invalid, pcDevId=%s, pcReqId=%s, pcServiceId=%s, pcMethod=%s.",
        pcDevId, pcReqId, pcServiceId, pcMethod);
        return HW_ERR;
    }

    if (0 == strncmp(METHOD_REMOVE_GATEWAY,pcMethod,strlen(METHOD_REMOVE_GATEWAY)))
    {
        IOTA_RmvGateWay();
    }

    return HW_OK;
}

在开发中心的产品 > 设备管理 界面中,单击非直连设备列后的“删除”按钮,这样就能在demo界面上看到广播接收时的日志打印命令下发。

非直连设备的删除需要网关的确认,正常业务情况下,网关又需要跟具体的设备确认,所以网关收到删除非直连设备的命令也不会立刻将设备删除。

添加非直连设备

在添加非直连设备前,确认非直连设备的profile已经上传,详见上传Profile并注册设备步骤。

在设备或网关登录成功后,可以调用IOTA_HubDeviceAdd接口添加非直连设备。

此处非直连设备的设备固有信息是测试数据。真实情况下,网关需要与具体的非直连设备交互,才能得到非直连设备的固有信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
HW_VOID AddSensors()
{
    ST_IOTA_DEVICE_INFO  stDeviceInfo = {0};
    FILE *fp = NULL;
    HW_CHAR szdeviceInfoFileName[BUFF_MAX_LEN] = {0};
    HW_INT  file_size;
    HW_CHAR *pcJsonStr;
    HW_JSONOBJ jsonObj;
    HW_JSON json;

    //get device info
    stDeviceInfo.pcNodeId = "SN Number_8532157";
    stDeviceInfo.pcManufacturerName = "Huawei";
    stDeviceInfo.pcManufacturerId = "Huawei";
    stDeviceInfo.pcDeviceType = "Motion";
    stDeviceInfo.pcModel = "test01";
    stDeviceInfo.pcProtocolType = "Z-Wave";

    IOTA_HubDeviceAdd(g_uiCookie, &stDeviceInfo);
    return;
}

注册广播接收器对添加设备结果进行相应处理。添加非直连设备成功后就能从广播中得到非直连设备的deviceId

1
HW_BroadCastReg(IOTA_TOPIC_HUB_ADDDEV_RSP, Device_AddResultHandler);

Demo在设备添加成功一段时间后会再调用删除设备接口进行设备删除。如果再次运行sdk.out前,还没执行删除设备接口,再次添加相同设备会失败。可以修改“NodeId”的值或者调用设备删除接口把原来的设备删除掉再进行测试。

非直连设备添加成功后可以在“设备列表”中看到新增一条记录。

非直连设备状态更新

非直连设备添加上时,一般情况下是“离线”状态。所以在非直连设备添加成功后,或者在非直连设备上报数据前,要调用IOTA_DeviceStatusUpdate()进行设备状态更新。

1
IOTA_DeviceStatusUpdate(g_uiCookie, g_cDeviceId, "ONLINE", "NONE");

AgentLiteDemo中只添加了一个非直连设备,所以IOTA_DeviceStatusUpdate中的g_cDeviceId直接使用全局变量。

注册广播接收器对非直连设备状态更新结果进行相应处理。

1
HW_BroadCastReg(IOTA_TOPIC_DEVUPDATE_RSP, Device_DevUpDateHandler);

非直连设备数据上报

请参考数据上报和数据发布章节,调用IOTA_ServiceDataReportIOTA_MqttDataPub接口进行数据上报, 各个参数使用非直连设备的相关数据即可,此处不再复述。

设备数据上报成功后,可以在非直连设备的“历史数据” 中查看上报的数据。

分享:

    相关文档

    相关产品