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工具。
使用必读
开发环境要求:
操作系统 |
工具链 |
---|---|
当前支持的系统:
|
需要支持以下工具链之一:
|
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系统进行开发。
交叉编译环境检测:
- 准备网关或设备。本文档将以树莓派为例,说明如何集成网关。
- 将Agent Lite SDK (Linux)解压到本地。
- 用sftp工具把mytest测试工具上传到树莓派上。
因为使用的设备是树莓派,所以使用RaspberryPi目录下的mytest测试工具。开发者可以选择根据实际情况选择不同目录下的mytest测试工具进行测试,尽量选择与自己的系统信息相近的目录下的测试工具进行测试。
- 修改所有文件的权限,进入mytest所在目录,运行“mytest”。
1 2 3
cd /opt/agentLite chmod -R 777 * ./mytest
如果最后出现“AUTO TEST END SUCC”字样,说明通过检测。
导入样例代码
在交叉编译环境检测通过后,再进行设备集成开发。下面将以Agent Lite Gateway Demo(C)中的样例代码为例,说明如何进行Agent Lite SDK的集成。
- 将Agent Lite Demo(C-Linux)压缩包中的Agent Lite Gateway Demo(C)解压到本地。
- 将SDK库中的头文件和so库都放到“Agent Lite Gateway Demo(C)/linux/demo”目录下。
因为使用的设备是树莓派,所以使用RaspberryPi目录下的库。
- 打开Visual Studio,选择
。
- 进入“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’。
绑定和登录
设备或网关第一次接入物联网平台时需要进行绑定操作,从而将设备或网关与平台进行关联。开发者通过传入设备序列号以及设备信息,将设备或网关绑定到物联网平台。
设备或网关绑定成功后或重启后,需要进行登录的流程,在设备或网关成功登录物联网平台后,才可以进行其它服务操作,比如接入其他传感器,数据上报等等。如果设备或网关登录成功,那么设备或网关在平台的状态显示为已在线。
- 修改绑定参数。
绑定时使用的设备固有信息(如设备型号等)是从“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 }
- 绑定设备。
绑定前先调用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”文件中。
- 配置登录参数。
登录前需要通过参数配置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);
- 设备登录。
调用API接口LoginService.login()进行直连设备登录,具体API的参数使用参考Agent Lite API接口文档中设备登录接口的说明。
1
IOTA_Login();
编译并运行程序
绑定和登录功能完成后,可以先测试一下设备或网关是否能正常与平台对接,再进行后续功能开发。
- 用sftp工具把demo目录上传到树莓派上。
- 进行交叉编译。
- 进入“/opt/agentLite/demo/”路径。
“/opt/agentLite/demo/”路径需要根据实际情况修改。
- 输入“chmod -R 777 *”命令修改权限。
- 输入“export LD_LIBRARY_PATH=./”设置程序共享库位置。
- 输入“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请开发者自行学习。
- 进入“/opt/agentLite/demo/”路径。
- 运行Demo。
启动demo命令为“./ sdk.out”,输入该命令程序就能运行起来了。
程序运行后,Agent Lite SDK就会主动发送绑定消息给平台。因为此时还没有使用应用侧接口在平台上注册此设备,所以会提示“The device has not registered yet”。
上传Profile并注册设备
下载Profile开发示例,并上传模板中的profile文件:“Gateway_Huawei_AgentLite01.zip”和“Motion_Huawei_test01.zip”。
- 登录开发中心,创建一个项目,在该项目空间内,选择“新建产品”。
,点击
- 在“创建产品”中,选择“本地导入产品创建”,单击“上传Profile”上传“Gateway_Huawei_AgentLite01.zip”和“Motion_Huawei_test01.zip”。
- 选择“添加真实设备”,进入“新建增实设备”页面。
,单击
- 根据向导注册设备。
- 注册设备后,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_ServiceDataReport或IOTA_MqttDataPub接口进行数据上报, 各个参数使用非直连设备的相关数据即可,此处不再复述。
设备数据上报成功后,可以在非直连设备的“历史数据” 中查看上报的数据。