边缘应用 Link IoT Edge对接

更新时间:

本章主要介绍如何实现 Link IoT Edge平台的API接口调用。物联网边缘计算支持使用边缘端API管理接入到网关的设备,包括获取设备及设备列表、设置设备属性、订阅设备事件等。

1.Link IoT Edge平台概述

Link IoT Edge提供了设备接入和本地计算等能力,当Link IoT Edge被集成到第三方的业务系统中时,需要提供标准的协议接口,来方便其它应用程序访问设备和配置本地计算规则等能力。

MQTT的订阅/发布消息模型,允许应用程序灵活的订阅设备数据,当设备有数据上报时,消息会推送至应用程序,简化了应用程序的实现。

2. Topic定义规范

MQTT协议使用3.1版本,MQTT Broker默认随LE一同部署,应用程序通过访问LE的IP地址+8883端口接入到MQTT Broker。 MQTT客户端连接Broker的用户名和密码由用户在云端控制台配置并部署到边缘网关,目前密码配置露出在边缘分组配置页面。

LE的IP地址获取方法:

  • 当应用程序被LE托管,运行在容器模式时,应用可以通过读取环境变量 “FCBASE_IPADDR“获取LE容器当前的IP地址。

  • 当应用程序被LE托管,运行在进程模式时,使用“127.0.0.1”本机地址即可。

  • 当应用程序为第三方系统组件,没有被LE托管,访问运行LE的宿主机IP地址即可。

    从访问对象范围的角度主要分为两类,第一类是访问整个边缘(网关)分组,第二类是访问单个设备/网关。

2.1 MQTT主题格式

{srcApp}/{messageType}/{destApp}/{method}每级字段长度上限为128字节。

2.1.1 {srcApp}

{srcApp}表示发布消息的APP身份。如果消息是由linkedge发布,则对应的{srcApp}为linkedge,如果消息是由其它APP发布的,则{srcApp}是该APP的关键字名称,如ibms。主题中包含消息发布者的身份有以下优点:

  • 隔离广播域,避免应答消息被其它模块接收。

  • 溯源,排查问题时根据主题信息可以定位到请求发起者的身份。

  • 身份验证,{srcApp}字段可用于填写系统颁发的AppID,用于权限验证。

2.1.2 {messageType}

{messageType}表示消息的类型,目前仅支持三种:

  • request: 表明消息为请求消息。

  • response:表明消息为响应消息。

  • notify:表明消息为事件通知消息,此类消息用于广播推送,所有订阅该Topic的APP都可以收到推送信息。

2.1.3 {destApp}

{destApp}表示消息目标,用于指定请求的目标APP。如果请求linkedge的服务,则对应的{destApp}为linkedge,如果请求其它APP服务,则为该APP的关键字名称。当{messageType}为notify时,不需要{destApp}字段。

2.1.4 {method}

{method}表示方法名,例如,可用getDeviceList表示获取设备信息列表。

2.2 分组Topic格式

该类Topic用于访问整个边缘(网关)分组的服务,格式如下:

  • 请求Topic:{srcApp}/request/linkedge/{method}

  • 应答Topic:linkedge/response/{srcApp}/{method}

  • 事件通知Topic:linkedge/notify/{event-name}

样例:

ibms应用程序获取分组中所有的设备列表Topic:
请求Topic:ibms/request/linkedge/getDeviceList
应答Topic:linkedge/response/ibms/getDeviceList

子设备状态变更(下线->上线)Topic:
linkedge/notify/deviceStateChanged

2.3 网关Topic

该类Topic访问单台网关的服务,格式如下:

  • 请求Topic:{srcApp}/request/linkedge/{pk}/{dn}/{method}

  • 应答Topic:linkedge/response/{srcApp}/{pk}/{dn}/{method}

  • 事件通知Topic:linkedge/notify/{pk}/{dn}/{event-name}

{pk}和{dn}为目标网关的ProductKey和DeviceName。

以ibms应用程序获取网关的设备列表为例:

ibms应用程序获取网关的设备列表Topic:
请求Topic:ibms/request/linkedge/{pk}/{dn}/getDeviceList
应答Topic:linkedge/response/ibms/{pk}/{dn}/getDeviceList

某网关下子设备状态变更(下线->上线)Topic:
linkedge/notify/{pk}/{dn}/deviceStateChanged

2.3 基于MQTT的方法调用

2.3.1 订阅应答Topic

基于MQTT的方法调用,通常会定义一对“请求”和“应答”Topic。应用程序需要调用服务方法时,需要先订阅应答Topic,再向请求Topic发送请求,才能正常获取服务应答信息。为了便于代码实现,订阅应答Topic时,设备的PK,DN和方法都可以使用通配符,这样只需订阅一次应答Topic,后续请求设备服务无需再动态订阅应答Topic。下面的样例以读取设备属性为例,应答Topic配置为”thing/response/testApp/+/+/+”,只需订阅一次,后续访问任意设备的任何服务,都可以收到应答消息。

2.3.2 Payload通用字段说明

  • 请求Payload中必填的字段为“requestId”,类型为string,用作消息标识,相同APP源发出的请求消息的requestId应该各不相同,可用UUID、随机数或自增长数值等手段。如果请求消息中没有填写”requestId”,该请求将被丢弃。

  • 请求Payload的可选字段的“timeout”,类型为number,单位为秒,用于标识请求的超时时间,当LE处理请求超过该时间仍未完成,LE会回送TIMEOUT错误信息。默认值为4s,最少1s,最大120s。

  • 请求Payload的可选字段的“timestamp”,类型为number,单位为毫秒,用于标识请求的发起时间。

  • 请求Payload的可选字段的“version”,类型为string,用于标识请求的版本号,目前用作保留字段。

    /* 1.先订阅应答Topic,用户接收设备应答数据 */
    #./mosquitto_sub --psk-identity linkedge --psk 12345678 -p 8883 -t thing/response/testApp/+/+/+ -v &
    /* 2.发送设备方法调用get请求 */
    #./mosquitto_pub --psk-identity linkedge --psk 12345678 -p 8883 -t testApp/request/thing/a1Mtx4p2fHG/LightSensor/get -m "{\"params\":[\"MeasuredIlluminance\"],\"requestId\":\"ff8db62b-4d75-46c8-bf6a-1600d326a88b\"}"
    /* 3.mosquitto_sub输出设备应答信息 */
    thing/response/testApp/a1Mtx4p2fHG/LightSensor/get {"code":0,"message":"success","params":{"MeasuredIlluminance":1000},"requestId":"ff8db62b-4d75-46c8-bf6a-1600d326a88b"}

3. 云端依赖

3.1 配置MQTT用户名和密码

使用MQTT协议访问LE网关,用户首先要在云端边缘分组页面,配置分组访问的用户名和密码。用户程序中的MQTT客户端使用该用户名和密码访问LE。

3.2 选择分组代理网关

应用程序需要访问边缘分组的信息时,需要有一台网关(分组代理网关)负责查询、收集、汇总分组中所有的网关信息,并返回一条应答消息给应用程序。这时涉及如何选择分组中代理网关的问题,有两个策略:

  • 用户在页面选择“代理网关”。

  • 分组中网关根据一定策略协商出一台代理网关,如选择网关中IP地址最小的作为代理网关。

    跟智慧园区产品线同学确认,倾向于让用户指定“代理网关”,原因是“现场会在和外部应用一起在服务器上部署一个LE,最好指定这个LE。”

    为了更好的用户体验,当分组中只有一台网关时,该网关默认成为分组代理网关,响应所有分组请求消息

3.1 边缘网关Topic示例:

该类Topic用于访问整个边缘(网关)分组的服务,格式如下:

  • 请求Topic:{srcApp}/request/linkedge/{method}

  • 应答Topic:linkedge/response/{srcApp}/{method}

  • 事件通知Topic:linkedge/notify/{event-name}

ibms应用程序获取分组中所有的设备列表Topic:

请求Topic:ibms/request/linkedge/getDeviceList

应答Topic:linkedge/response/ibms/getDeviceList

子设备状态变更(下线->上线)Topic:linkedge/notify/deviceStateChanged

3.2 分组Topic格式示例:

该类Topic用于访问整个边缘(网关)分组的服务,格式如下:

  • 请求Topic:{srcApp}/request/linkedge/{method}

  • 应答Topic:linkedge/response/{srcApp}/{method}

  • 事件通知Topic:linkedge/notify/{event-name}

ibms应用程序获取分组中所有的设备列表Topic:

请求Topic:ibms/request/linkedge/getDeviceList

应答Topic:linkedge/response/ibms/getDeviceList

子设备状态变更(下线->上线)Topic:linkedge/notify/deviceStateChanged

4. 接口详细说明

4.1 设备读写

设备读写主要包含设备数据的订阅设备方法的调用两部分。

4.1.1 设备数据订阅

通过订阅设备数据上报的Topic,应用程序可以监听设备上报的属性值和事件信息。

  • 设备属性上报Topic:thing/notify/${pk}/${dn}/property

  • 设备事件上报Topic:thing/notify/${pk}/${dn}/${tsl.event.identifer}

数据发布Payload透传驱动上报数据:

# 示例1-设备属性上报:
Topic:thing/notify/${pk}/${dn}/property
Payload:
{
    "key1":{
        "value":"value1",
        "time":152444872****
    },
    "key2":{
        "value":"value2",
        "time":152444872****
    }
}
# 示例2-设备事件上报:
Topic:thing/notify/${pk}/${dn}/${tsl.event.identifer}
Payload:
{
    "params": {
        "value" : {
            "key1":"value1",
            "key2":"value2"
         },
         "time" : 152444872****
    }
}

4.1.2 设备方法调用

  • 设置设备属性,调用设备set方法Topic:{srcApp}/request/thing/${pk}/${dn}/set

  • 获取设备属性值,调用设备get方法Topic:{srcApp}/request/thing/${pk}/${dn}/get

  • 调用设备自定义方法Topic:{srcApp}/request/thing/${pk}/${dn}/${tsl.service.identifer}

设备配置Payload在驱动请求参数基础上增加了requestId字段,用于标识每次配置请求:

#示例-设置设备属性
Topic:testApp/request/thing/${productKey}/${deviceName}/set
Payload:
{
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9776", #[Required]
    "timeout":5,
    "params":{   #设备方法调用的参数[Required]
        "key1":"value1",
        "key2":"value2"
    }
}

#示例-获取设备属性
Topic:testApp/request/thing/${productKey}/${deviceName}/get
Payload:
{
    "requestId":"ff8db62b-4d75-46c8-bf6a-1600d326a88b", #[Required]
    "params":[      #设备方法调用的参数[Required]
        "key"
    ]
}
  • 设置设备属性应答Topic:thing/response/{srcApp}/${pk}/${dn}/set

  • 获取设备属性应答Topic:thing/response/{srcApp}/${pk}/${dn}/get

  • 调用设备自定义方法应答Topic:thing/response/{srcApp}/${pk}/${dn}/${tsl.service.identifer}

配置应答Payload在驱动应答消息基础上增加了requestId字段,用于匹配对应的配置请求:

#示例-设置设备属性应答数据
Topic:thing/response/{srcApp}/${pk}/${dn}/set
Payload:
{
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9776",
    "code":0,
    "message":"",
    "params":{}
}

#示例-获取设备属性应答数据
Topic:thing/response/{srcApp}/${pk}/${dn}/get
Payload:
{
    "requestId":"ff8db62b-4d75-46c8-bf6a-1600d326a88b",
    "code":0,
    "message":"success",
    "params":{
        "key":"value"
    }
}

4.2 设备状态查询

4.2.1 获取设备列表

  • 获取分组设备列表Topic:{srcApp}/request/linkedge/getDeviceList

  • 获取网关设备列表Topic:{srcApp}/request/linkedge/{pk}/{dn}/getDeviceList

  • 请求Payload:

{
  "requestId": "0bc458b5-47f6-472f-bd88-3624696e9777", # [Required]
  "timestamp": 157121985****, #ms [Optional]
  "timeout":3, # 最少1s,最多120s [Optional: default 4s]
  "version": "1.0" # [Optional]
}
  • 获取分组设备列表应答Topic:linkedge/response/{srcApp}/getDeviceList

  • 应答Payload

    {
      "params":[ #数组,包含所有网关下的子设备
          {
              "gwProductKey":"a1PQ9828qvr", #网关的productkey
              "gwDeviceName":"yinlong_gw_dev1",#网关的devicename
              "code":0,
              "message":"success",
              "deviceList":[ #设备列表
                  {
                      "productKey":"a1KRepmC2XJ", #设备的productkey
                      "deviceName":"modbus_tcp_dev_1", #设备的devicename
                      "localOnline":"false",  #设备与网关的连接状态
                      "cloudOnline":"false",  #设备与云端的连接状态
                      "activationState":"notActivated",#设备在云端是否被激活
                      "nickName":"xxx",  #设备别名
                      "tags":[ #设备包含的标签
    
                      ]
                  },
                  {
                      "productKey":"a1ZJTVsqj2y",
                      "deviceName":"lightDevNoSpecial",
                      "localOnline":"true",
                      "cloudOnline":"true",
                      "activationState":"activated",
                      "nickName":"xxx",  #设备别名
                      "tags":[
    
                      ]
                  },
                  {
                      "productKey":"a1ZJTVsqj2y",
                      "deviceName":"LightDev2",
                      "localOnline":"false",
                      "cloudOnline":"false",
                      "activationState":"notActivated",
                      "nickName":"xxx",  #设备别名
                      "tags":[  #设备包含的标签
                          {
                              "key":"type",   #设备标签的key
                              "value":"light" #设备标签的value
                          },
                          {
                              "key":"owner",
                              "value":"yinlong"
                          },
                          {
                              "key":"location",
                              "value":"master bedroom"
                          },
                          {
                              "key":"color",
                              "value":"red"
                          }
                      ]
                  }
              ]
          }
      ],
      "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
      "version":"1.0",
      "timestamp":157225013****,
      "code":0,
      "message":"success"
    }
  • 获取网关设备列表应答Topic:linkedge/response/``{srcApp}``/{pk}/{dn}/getDeviceList

  • 应答Payload:

    {
      "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
      "timestamp": 157121985****,
      "version":"1.0",
      "code":0,
      "message":"success",
      "params":[      #设备列表
          {
              "productKey":"a1Mtx4p2fHG",  #设备的productkey
              "deviceName":"device1",      #设备的devicename
              "localOnline":"true",        #设备和网关的连接状态
              "cloudOnline":"true",        #设备和云端的连接状态
              "activationState": "activated/notActivated/activationFailed", #设备在云端的激活状态
              "tag":[
                  {
                      "key":"coordinate",
                      "value":"0:0"
                  }
              ]
          }
      ]
    }

4.2.2 获取设备TSL配置信息

  • 获取设备TSL请求Topic:{srcApp}/request/thing/{pk}/{dn}/getTsl

    • 如果topic中的pk、dn为网关的,参数中指定设备pk,需要遍历所有网关,查询返回可能会有多个网关下pk的tsl,可能存在不一致的情况,如何选择是个问题。

    • 如果Topic中仅指定设备pk可能有多个网关回复, Topic中pk、dn为设备的,这样可以保证仅有一个网关回复,而且就是你想操作的设备的tsl,更加合理。

  • 请求Payload:

{
  "requestId": "0bc458b5-47f6-472f-bd88-3624696e9778",
  "version": "1.0",
  "timeout":3 # 最少1s,最多120s
}
  • 获取设备TSL应答Topic:thing/response/{srcApp}/{pk}/{dn}/getTsl

  • 应答Payload:

{
    "params":{
        "productKey":"a1KRepmC2XJ",
        "deviceName":"modbus_tcp_dev_1",
        "code":0,
        "message":"success",
        "tsl":"{"events":[{"desc":"属性上报","identifier":"post","method":"thing.event.property.post","name":"post","outputData":[{"dataType":{"specs":{"max":"2147483647","min":"-2147483648","unit":"Mpa"},"type":"double"},"identifier":"pressure1","name":"pressure1"}],"required":true,"type":"info"}],"profile":{"productKey":"a1KRepmC2XJ"},"properties":[{"accessMode":"rw","dataType":{"specs":{"max":"2147483647","min":"-2147483648","unit":"Mpa"},"type":"double"},"identifier":"pressure1","name":"pressure1","required":true}],"schema":"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json","services":[{"callType":"async","desc":"属性设置","identifier":"set","inputData":[{"dataType":{"specs":{"max":"2147483647","min":"-2147483648","unit":"Mpa"},"type":"double"},"identifier":"pressure1","name":"pressure1"}],"method":"thing.service.property.set","name":"set","outputData":[],"required":true},{"callType":"async","desc":"属性获取","identifier":"get","inputData":["pressure1"],"method":"thing.service.property.get","name":"get","outputData":[{"dataType":{"specs":{"max":"2147483647","min":"-2147483648","unit":"Mpa"},"type":"double"},"identifier":"pressure1","name":"pressure1"}],"required":true}]}",  #物模型
        "tslConfig":"{"profile":{"productKey":"a1KRepmC2XJ"},"properties":[{"identifier":"pressure1","operateType":"holdingRegister","originalDataType":{"specs":{"registerCount":1,"reverseRegister":0,"swap16":0},"type":"int16"},"pollingTime":1000,"registerAddress":"0x01","scaling":1,"trigger":1,"writeFunctionCode":16}]}"  #扩展物模型
    },
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
    "version":"1.0",
    "timestamp":157224857****,
    "code":0,
    "message":"success"
}

4.3 IFTTT规则配置

4.3.1 获取IFTTT规则列表

  • 获取分组IFTTT规则列表Topic:{srcApp}/request/linkedge/getSceneList

  • 获取网关IFTTT规则列表Topic:{srcApp}/request/linkedge/{pk}/{dn}/getSceneList

  • 请求Payload:

{
  "requestId": "0bc458b5-47f6-472f-bd88-3624696e9778",
  "timestamp": 157121985****, #ms [Optional]
  "timeout":3, # 最少1s,最多120s [Optional: default 4s]
  "version": "1.0" # [Optional]
}
  • 获取分组IFTTT规则应答Topic:linkedge/response/{srcApp}/getSceneList

  • 应答Payload:

{
    "params":[      #规则列表
        {
            "gwProductKey":"a1PQ9828qvr", #网关productkey
            "gwDeviceName":"alpine_test_gateway",#网关的devicenmae
            "code":0,
            "message":"success",
            "data":[    #包含网关中所有规则的描述

            ]
        },
        {
            "gwProductKey":"a1PQ9828qvr",
            "gwDeviceName":"yinlong_gw_dev1",
            "code":0,
            "message":"success",
            "data":[
                {
                    "times":5,
                    "failureTimes":5,
                    "lastState":{
                        "state":"failure",
                        "cause":"walk action set: The name iot.device.ida1ZJTVsqj2y_alpine_light_dev1 was not provided by any .service files",
                        "time":"2019-10-28T19:35:00+08:00",
                        "duration":1
                    },
                    "id":"a08d6c08bc1a440693ba9c9c8166a968",
                    "name":"ifttt",
                    "running":true,
                    "time":"2019-10-28T19:30:47+08:00",
                    "uptime":259072,
                    "actions":{
                        "times":5,
                        "failureTimes":5,
                        "lastState":{
                            "state":"failure",
                            "cause":"The name iot.device.ida1ZJTVsqj2y_alpine_light_dev1 was not provided by any .service files",
                            "time":"2019-10-28T19:35:00+08:00",
                            "duration":1
                        }
                    },
                    "conditions":{
                        "times":5,
                        "failureTimes":0,
                        "lastState":{
                            "state":"success",
                            "cause":"",
                            "time":"2019-10-28T19:35:00+08:00",
                            "duration":0
                        }
                    }
                }
            ]
        }
    ],
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
    "version":"1.0",
    "timestamp":157226250****,
    "code":0,
    "message":"success"
}
  • 获取网关IFTTT规则应答Topic:linkedge/response/{srcApp}/{pk}/{dn}/getSceneList

  • 应答Payload:

{
    "params":[                                                #网关下的规则列表
        {
            "times":0,
            "failureTimes":0,
            "lastState":null,
            "id":"a08d6c08bc1a440693ba9c9c8166a968",
            "name":"ifttt",
            "running":true,
            "time":"2019-10-28T17:35:35+08:00",
            "uptime":5967,
            "actions":{
                "times":0,
                "failureTimes":0,
                "lastState":null
            },
            "conditions":{
                "times":0,
                "failureTimes":0,
                "lastState":null
            }
        }
    ],
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
    "version":"1.0",
    "timestamp":157225534****,
    "code":0,
    "message":"success"
}

4.3.2 控制IFTTT规则启停

同一个IFTTT规则,部署到不同的网关,ID是相同的。因此IFTTT规则启停,仅支持面向网关的定向操作,不支持分组维度。

  • 使能网关IFTTT规则Topic:{srcApp}/request/linkedge/{pk}/{dn}/enableScene

  • 关闭网关IFTTT规则Topic:{srcApp}/request/linkedge/{pk}/{dn}/disableScene

  • 请求Payload:其中params数组中至少包含一个,至多包含32个对象。

{
  "requestId": "0bc458b5-47f6-472f-bd88-3624696e9778",
  "version": "1.0",
  "params": [ #场景规则id数组[Required]
    {
      "id": "id1"
    }
  ]
}
  • 使能网关IFTTT规则配置应答Topic:linkedge/response/{srcApp}/{pk}/{dn}/enableScene

  • 关闭网关IFTTT规则配置应答Topic:linkedge/response/{srcApp}/{pk}/{dn}/disableScene

  • 应答Payload:

{
    "params":[
        {
            "id":"123000000",
            "code":1,
            "message":"no such scene"
        },
        {
            "id":"a08d6c08bc1a440693ba9c9c8166a968",
            "code":0,
            "message":"success"
        }
    ],
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
    "version":"1.0",
    "timestamp":157227690****,
    "code":0,
    "message":"success"
}

4.4 设备列表和状态变更

4.4.1 设备列表变更

当网关互联中某一网关所拥有的设备列表出现变化时,互联网络将广播一条消息通知给订阅者。

  • 变更Topic: linkedge/notify/deviceListChanged

  • 内容

{
    "timestamp":157225090****,
    "version":"1.0",
    "params":[
        {
            "gwProductKey":"a1XqBnyTZLD",
            "gwDeviceName":"ModbusTestGW"
        }
    ]
}

4.4.2 设备在线状态变更

当网关互联中某子设备的在线状态出现变化时(包括连接到本地和连接到云端),网关互联网络将广播一条消息给订阅者。

  • 通知Topic: linkedge/notify/deviceStateChanged

  • 内容

内容格式大体与4.2.1获取设备列表相同。

{
    "timestamp": 1572250903307,
    "version": "1.0",
    "params": [{
        "gwProductKey": "a1XqBnyTZLD",  #网关的productkey        
        "gwDeviceName": "ModbusTestGW", #网关的devicename
        "deviceList": [{                #网关下的设备列表
            "productKey": "a1OSqKKiZLL",  #设备的productkey
            "deviceName": "DN035",        #设备的devicename
            "localOnline": "true/false",  #设备的本地在线状态
            "cloudOnline": "true/false",  #设备的云端在线状态
            "activationState": "activated/notActivated/activationFailed",#设备在云端的激活状态
        }]
    }]
}

4.5 网关信息查询

4.5.1 获取网关列表

  • 获取分组网关列表Topic:{srcApp}/request/linkedge/getGatewayList

  • 请求Payload

{
  "requestId": "0bc458b5-47f6-472f-bd88-3624696e9777", # [Required]
  "timestamp": 157121985****, #ms [Optional]
  "timeout":3, # 最少1s,最多120s [Optional: default 4s]
  "version": "1.0" # [Optional]
}
  • 获取分组网关列表应答Topic:linkedge/response/{srcApp}/getGatewayList

  • 响应Payload

{
    "params":[
        {
            "gwProductKey":"a1phR16zqNZ",
            "gwDeviceName":"gateway_01",
            "code":0,     #此网关接口的服务调用的返回码
            "message":"success",
            "gatewayInfo":{   #网关信息
                "productKey":"a1phR16zqNZ", #网关的productkey
                "deviceName":"gateway_01",  #网关的devicename
                "nickName":"",              #网关的别名
                "tags":[                    #网关的标签

                ]
            }
        },
        {
            "gwProductKey":"a1phR16zqNZ",
            "gwDeviceName":"gateway_02",
            "code":101572,
            "message":"getGateway timeout"
        },
        {
            "gwProductKey":"a1phR16zqNZ",
            "gwDeviceName":"gateway_03",
            "code":101572,
            "message":"ERROR_GWC_REQUEST_TIMEOUT"
        }
    ],
    "requestId":"0bc458b5-47f6-472f-bd88-3624696e9777",
    "version":"1.0",
    "timestamp":158202075****,
    "code":10****,           #分组接口的调用返回码
    "message":"ERROR_GWC_REQUEST_TIMEOUT"
}

5.错误码

应答Payload中的”code”字段代表错误码,成功时返回0,异常时返回下述错误码,错误信息保存到”message”字段:

     0: 成功
101571: 参数校验不合法
101572: 请求处理超时
101573: LinkIoTEdge处理失败
101574:设备驱动处理失败
101575: MQTT消息代理处理失败
101576: 设备不存在
101578: 请求的参数个数超出上限
101579: 访问资源不存在
101580: 请求的参数为空

6.自测用例

该部分测试用例中的测试数据,对于MQTT客户端开发具有很好的借鉴价值,结合具体例子的请求和应答便于开发者加深对协议规范的理解。

6.1 部署配置样例

  • 本地部署方法:./casctl deploy gwc_deploy.conf

  • gwc_deploy.conf配置文件样例:

{
    "version":"1.0",
    "instanceId":"iid222",
    "instanceGroupId":"linkedge",
    "instanceGroupPsk":"123456abcdef12345678123456ABCDEF",
    "userTlsConfig":[
        {
            "userId":"customer1",
            "psk":"123456"
        },
        {
            "userId":"customer2",
            "psk":"12345678"
        }
    ],
    "nodesConfig":[
        {
            "ipAddress":"172.17.0.2",
            "productKey":"a1PQ9828qvr",
            "deviceName":"yinlong_gw_dev1",
            "isGroupAgent":"1" #Mark this gw as groupAgent

        },
        {
            "ipAddress":"172.17.0.3",
            "productKey":"a1PQ9828qvr",
            "deviceName":"alpine_test_gateway"
        }
    ]
}

6.2 自测用例

  1. 订阅所有设备属性、事件上报

/* 订阅设备属性上报Topic,接收设备属性上报数据 */
#./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t thing/notify/+/+/property -v &
thing/notify/a1Mtx4p2fHG/LightSensor/property {"MeasuredIlluminance":{"value":550,"time":156662262****}}
thing/notify/a1Mtx4p2fHG/LightSensor/property {"MeasuredIlluminance":{"value":600,"time":156662265****}}
thing/notify/a1Mtx4p2fHG/LightSensor/property {"MeasuredIlluminance":{"value":650,"time":156662268****}}
  1. 访问外部/本地网关设备方法

/* 1.先订阅应答Topic,用户接收设备应答数据 */
#./mosquitto_sub --psk-identity linkedge --psk 12345678 -p 8883 -t thing/response/testApp/+/+/+ -v &
/* 2.发送设备方法调用get请求 */
#./mosquitto_pub --psk-identity linkedge --psk 12345678 -p 8883 -t testApp/request/thing/a1Mtx4p2fHG/LightSensor/get -m "{\"params\":[\"MeasuredIlluminance\"],\"requestId\":\"ff8db62b-4d75-46c8-bf6a-1600d326a88b\"}"
/* 3.mosquitto_sub输出设备应答信息 */
thing/response/testApp/a1Mtx4p2fHG/LightSensor/get {"code":0,"message":"success","params":{"MeasuredIlluminance":1000},"requestId":"ff8db62b-4d75-46c8-bf6a-1600d326a88b"}
  1. 消息路由

配置全部设备数据到FC,配置某个ProductKey下所有设备数据到FC。

  1. 获取网关设备列表

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/getDeviceList -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/a1PQ9828qvr/yinlong_gw_dev1/getDeviceList -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\", \"version\":\"1.0\"}"
linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/getDeviceList {"data":[{"productKey":"a1ZJTVsqj2y","deviceName":"LightDev","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[{"key":"type","value":"light"},{"key":"owner","value":"yinlong"},{"key":"location","value":"livingroom"},{"key":"color","value":"white"}]},{"productKey":"a1arJcX0Koy","deviceName":"Sensor_device1","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[{"key":"location","value":"master bedroom"}]},{"productKey":"a1KRepmC2XJ","deviceName":"modbus_tcp_dev_1","localOnline":"false","cloudOnline":"false","activationState":"notActivated","tags":[]},{"productKey":"a1Mtx4p2fHG","deviceName":"LightSensor","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]},{"productKey":"a1ZJTVsqj2y","deviceName":"LightDev2","localOnline":"false","cloudOnline":"false","activationState":"notActivated","tags":[{"key":"type","value":"light"},{"key":"owner","value":"yinlong"},{"key":"location","value":"master bedroom"},{"key":"color","value":"red"}]},{"productKey":"a1PQ9828qvr","deviceName":"yinlong_gw_dev1","localOnline":"false","cloudOnline":"false","activationState":"notActivated","tags":[]},{"productKey":"a1ZJTVsqj2y","deviceName":"lightDevNoSpecial","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777"}
  1. getTsl 测试用例

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t thing/response/testApp/+/+/getTsl -v & 
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/thing/a1arJcX0Koy/alpine_light_sensor/getTsl -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\",\"timeout\":5}"
thing/response/testApp/a1arJcX0Koy/alpine_light_sensor/getTsl {"params":{"productKey":"a1arJcX0Koy","deviceName":"alpine_light_sensor","code":0,"message":"success","tsl":"{\"events\":[{\"desc\":\"属性上报\",\"identifier\":\"post\",\"method\":\"thing.event.property.post\",\"name\":\"post\",\"outputData\":[{\"dataType\":{\"specs\":{\"max\":\"65535\",\"min\":\"0\",\"step\":\"0.01\",\"unit\":\"Lux\",\"unitName\":\"照度\"},\"type\":\"double\"},\"identifier\":\"MeasuredIlluminance\",\"name\":\"光照度检测值\"}],\"required\":true,\"type\":\"info\"}],\"profile\":{\"productKey\":\"a1arJcX0Koy\"},\"properties\":[{\"accessMode\":\"r\",\"dataType\":{\"specs\":{\"max\":\"65535\",\"min\":\"0\",\"step\":\"0.01\",\"unit\":\"Lux\",\"unitName\":\"照度\"},\"type\":\"double\"},\"identifier\":\"MeasuredIlluminance\",\"name\":\"光照度检测值\",\"required\":true}],\"schema\":\"https://iotx-tsl.oss-ap-southeast-1.aliyuncs.com/schema.json\",\"services\":[{\"callType\":\"async\",\"desc\":\"属性设置\",\"identifier\":\"set\",\"inputData\":[],\"method\":\"thing.service.property.set\",\"name\":\"set\",\"outputData\":[],\"required\":true},{\"callType\":\"async\",\"desc\":\"属性获取\",\"identifier\":\"get\",\"inputData\":[\"MeasuredIlluminance\"],\"method\":\"thing.service.property.get\",\"name\":\"get\",\"outputData\":[{\"dataType\":{\"specs\":{\"max\":\"65535\",\"min\":\"0\",\"step\":\"0.01\",\"unit\":\"Lux\",\"unitName\":\"照度\"},\"type\":\"double\"},\"identifier\":\"MeasuredIlluminance\",\"name\":\"光照度检测值\"}],\"required\":true}]}","productKey":"a1arJcX0Koy","deviceName":"alpine_light_sensor","code":0,"message":"success","tslConfig":"{\"profile\":{\"productKey\":\"a1arJcX0Koy\"}}"},"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":1572249171823,"code":0,"message":"success"}
  1. 获取分组设备列表

  • 前置条件:修改gwc_deploy.conf,选择一台网关为groupAgent:设置代理网关标志 “isGroupAgent”:”1”

./casctl dep gwc_deploy.conf
  • 测试命令

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/getDeviceList -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/getDeviceList -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\"}"
linkedge/response/testApp/getDeviceList {"params":[{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"yinlong_gw_dev1","code":0,"message":"success","deviceList":[{"productKey":"a1ZJTVsqj2y","deviceName":"LightDev","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[{"key":"type","value":"light"},{"key":"owner","value":"yinlong"},{"key":"location","value":"livingroom"},{"key":"color","value":"white"}]},{"productKey":"a1arJcX0Koy","deviceName":"Sensor_device1","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[{"key":"location","value":"master bedroom"}]},{"productKey":"a1ZJTVsqj2y","deviceName":"LightDev2","localOnline":"false","cloudOnline":"false","activationState":"notActivated","tags":[{"key":"type","value":"light"},{"key":"owner","value":"yinlong"},{"key":"location","value":"master bedroom"},{"key":"color","value":"red"}]},{"productKey":"a1Mtx4p2fHG","deviceName":"LightSensor","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]},{"productKey":"a1KRepmC2XJ","deviceName":"modbus_tcp_dev_1","localOnline":"false","cloudOnline":"false","activationState":"notActivated","tags":[]},{"productKey":"a1ZJTVsqj2y","deviceName":"lightDevNoSpecial","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]}]},{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"alpine_test_gateway","code":0,"message":"success","deviceList":[{"productKey":"a1fsUodstaA","deviceName":"oil_temperature_dev1","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]},{"productKey":"a1arJcX0Koy","deviceName":"alpine_light_sensor","localOnline":"true","cloudOnline":"true","activationState":"activated","tags":[]}]}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157218682****,"code":0,"message":"success"}
超时情况:linkedge/response/testApp/getDeviceList {"params":[{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"yinlong_gw_dev1","code":101572,"message":"ERROR_GWC_REQUEST_TIMEOUT"},{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"alpine_test_gateway","code":101572,"message":"ERROR_GWC_REQUEST_TIMEOUT"}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157218540****,"code":101572,"message":"ERROR_GWC_REQUEST_TIMEOUT"}
  1. getSceneList

  • 获取单个网关的规则列表

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/getSceneList -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/a1PQ9828qvr/yinlong_gw_dev1/getSceneList -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\"}"
linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/getSceneList {"params":{"code":0,"message":"success","data":[{"times":0,"failureTimes":0,"lastState":null,"id":"a08d6c08bc1a440693ba9c9c8166a968","name":"ifttt","running":false,"time":"","uptime":0,"actions":{"times":0,"failureTimes":0,"lastState":null},"conditions":{"times":0,"failureTimes":0,"lastState":null}}]},"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157222996****,"code":0,"message":"success"}
dbus-send --bus=unix:path=/tmp/var/run/mbusd/mbusd_socket --dest=iot.gateway.scene --print-reply /iot/gateway/scene iot.gateway.scene.listSceneStats
  • 获取分组的规则列表

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/getSceneList -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/getSceneList -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\"}"
linkedge/response/testApp/getSceneList {"params":[{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"alpine_test_gateway","code":0,"message":"success","data":[]},{"gwProductKey":"a1PQ9828qvr","gwDeviceName":"yinlong_gw_dev1","code":0,"message":"success","data":[{"times":5,"failureTimes":5,"lastState":{"state":"failure","cause":"walk action set: The name iot.device.ida1ZJTVsqj2y_alpine_light_dev1 was not provided by any .service files","time":"2019-10-28T19:35:00+08:00","duration":1},"id":"a08d6c08bc1a440693ba9c9c8166a968","name":"ifttt","running":true,"time":"2019-10-28T19:30:47+08:00","uptime":273231,"actions":{"times":5,"failureTimes":5,"lastState":{"state":"failure","cause":"The name iot.device.ida1ZJTVsqj2y_alpine_light_dev1 was not provided by any .service files","time":"2019-10-28T19:35:00+08:00","duration":1}},"conditions":{"times":5,"failureTimes":0,"lastState":{"state":"success","cause":"","time":"2019-10-28T19:35:00+08:00","duration":0}}}]}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157226252****,"code":0,"message":"success"}
  1. enableScene

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/+/+/enableScene -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/a1PQ9828qvr/yinlong_gw_dev1/enableScene -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\",\"params\":[{\"id\":\"a08d6c08bc1a440693ba9c9c8166a968\"},{\"id\":\"123000000\"}]}"
linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/enableScene {"params":[{"id":"123000000","code":1,"message":"no such scene"},{"id":"a08d6c08bc1a440693ba9c9c8166a968","code":0,"message":"success"}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157227690****,"code":0,"message":"success"}
  1. disableScene

./mosquitto_sub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t linkedge/response/testApp/+/+/disableScene -v &
./mosquitto_pub --psk-identity linkedge --psk 123456aBcdef12345678123456ABCDEf -p 8883 -t testApp/request/linkedge/a1PQ9828qvr/yinlong_gw_dev1/disableScene -m "{\"requestId\": \"0bc458b5-47f6-472f-bd88-3624696e9777\",\"params\":[{\"id\":\"a08d6c08bc1a440693ba9c9c8166a968\"}]}"
linkedge/response/testApp/a1PQ9828qvr/yinlong_gw_dev1/disableScene {"params":[{"id":"a08d6c08bc1a440693ba9c9c8166a968","code":0,"message":"success"}],"requestId":"0bc458b5-47f6-472f-bd88-3624696e9777","version":"1.0","timestamp":157227715****,"code":0,"message":"success"}

7. 设备端开发

7.1 C版本SDK

本章为您介绍C版本的SDK使用方法及相关API。Link IoT Edge提供C版本的SDK,名称为linkedge-thing-access-sdk-c。C版本开源的SDK源码请参见开源C库

get_properties_callback

/*
     * 获取属性(对应设备产品物模型属性定义)的回调函数,需驱动开发者实现获取属性业务逻辑。
     * 
     * Link IoT Edge需要获取某个设备的属性时,SDK会调用该接口间接获取到数据并封装成固定格式后回传给Link IoT Edge。
     * 开发者需要根据设备id和属性名找到设备,将获取到的属性值按照@device_data_t格式填充。
     *
     * @dev_handle:         Link IoT Edge需要获取属性的具体某个设备。
     * @properties:         属性值键值结构,驱动开发者需要将根据属性名称获取到的属性值更新到properties中。
     * @properties_count:   属性个数。
     * @usr_data:           注册设备时,用户传递的私有数据。
     * 所有属性均获取成功则返回LE_SUCCESS,其他则返回错误码(参考le_error.h错误码宏定义)。
     * */
typedef int (*get_properties_callback)(device_handle_t dev_handle, 
                                       leda_device_data_t properties[], 
                                       int properties_count, 
                                       void *usr_data);

set_properties_callback

/*
     * 设置属性(对应设备产品物模型属性定义)的回调函数,需驱动开发者实现设置属性业务逻辑。
     * 
     * Link IoT Edge需要设置某个设备的属性时,SDK会调用该接口将具体的属性值传递给应用程序,开发者需要在本回调
     * 函数里将属性设置到设备。
     *
     * @dev_handle:         Link IoT Edge需要设置属性的具体某个设备。
     * @properties:         Link IoT Edge需要设置的设备的属性名称和值。
     * @properties_count:   属性个数。
     * @usr_data:           注册设备时,用户传递的私有数据。
     * 
     * 若获取成功则返回LE_SUCCESS,失败则返回错误码(参考le_error.h错误码宏定义)。
     * */
typedef int (*set_properties_callback)(device_handle_t dev_handle, 
                                       const leda_device_data_t properties[], 
                                       int properties_count, 
                                       void *usr_data);

call_service_callback

/*
     * 服务(对应设备产品物模型服务定义)调用的回调函数,需要驱动开发者实现服务对应业务逻辑。
     * 
     * Link IoT Edge需要调用某个设备的服务时,SDK会调用该接口将具体的服务参数传递给应用程序,开发者需要在本回调
     * 函数里调用具体的服务,并将服务返回值按照@device_data_t格式填充到output_data。 
     *
     * @dev_handle:   Link IoT Edge需要调用服务的具体某个设备。
     * @service_name: Link IoT Edge需要调用的设备的具体某个服务名,名称与设备产品物模型一致。
     * @data:         Link IoT Edge需要调用的设备的具体某个服务参数,参数与设备产品物模型保持一致。
     * @data_count:   Link IoT Edge需要调用的设备的具体某个服务参数个数。
     * @output_data:  开发者需要将服务调用的返回值,按照设备产品物模型规定的服务格式返回到output中。
     * @usr_data:     注册设备时,用户传递的私有数据。
     * 
     * 若获取成功则返回LE_SUCCESS,失败则返回错误码(参考le_error.h错误码宏定义)。
     * */
typedef int (*call_service_callback)(device_handle_t dev_handle, 
                                     const char *service_name, 
                                     const leda_device_data_t data[], 
                                     int data_count, 
                                     leda_device_data_t output_data[], 
                                     void *usr_data);

leda_report_properties

/*
 * 上报属性,在设备所属产品物模型中规定了设备的属性上报能力。
 *
 * 上报属性,可以上报一个,也可以多个一起上报。
 *
 * dev_handle:          设备在Link IoT Edge本地唯一标识。
 * properties:          @leda_device_data_t,属性数组。
 * properties_count:    本次上报属性个数。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 *
 */
int leda_report_properties(device_handle_t dev_handle, const leda_device_data_t properties[], int properties_count);

leda_report_event

/*
 * 上报事件,设备具有的事件上报能力在设备产品物模型有规定。
 *
 * 
 * dev_handle:  设备在Link IoT Edge本地唯一标识。
 * event_name:  事件名称。
 * data:        @leda_device_data_t,事件参数数组。
 * data_count:  事件参数数组长度。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 *
 */
int leda_report_event(device_handle_t dev_handle, const char *event_name, const leda_device_data_t data[], int data_count);

leda_offline

/*
 * 下线设备,假如设备工作在不正常的状态或设备退出前,可以先下线设备,这样Link IoT Edge就不会继续下发消息到设备侧。
 *
 * dev_handle:  设备在Link IoT Edge本地唯一标识。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 *
 */
int leda_offline(device_handle_t dev_handle);

leda_online

/*
 * 上线设备,设备只有上线后,才能被Link IoT Edge识别。
 *
 * dev_handle:  设备在Link IoT Edge本地唯一标识。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
int leda_online(device_handle_t dev_handle);

leda_register_and_online_by_device_name

/*
 * 通过已在阿里云物联网平台创建的设备device_name,注册并上线设备,申请设备唯一标识符。
 *
 * 若需要注册多个设备,则多次调用该接口即可。
 *
 * product_key: 在阿里云物联网平台创建的产品ProductKey。
 * device_name: 在阿里云物联网平台创建的设备名称DeviceName。
 * device_cb:   请求调用设备回调函数结构体,详细描述见@leda_device_callback。
 * usr_data:    设备注册时传入私有数据,在回调中会传给设备。
 *
 * 阻塞接口,返回值设备在Link IoT Edge本地唯一标识,>= 0表示有效,< 0 表示无效。
 *
 */
device_handle_t leda_register_and_online_by_device_name(const char *product_key, const char *device_name, leda_device_callback_t *device_cb, void *usr_data);

leda_register_and_online_by_local_name

/*
 * 通过本地自定义设备名称,注册并上线设备,申请设备唯一标识符。
 *
 * 若需要注册多个设备,则多次调用该接口即可。
 *
 * product_key: 在阿里云物联网平台创建的产品ProductKey。
 * local_name:  由设备特征值组成的唯一描述信息,必须保证同一个product_key时,每个设备名称不同。
 * device_cb:   请求调用设备回调函数结构体,详细描述见@leda_device_callback。
 * usr_data:    设备注册时传入私有数据,在回调中会传给设备。
 *
 * 阻塞接口,返回值设备在Link IoT Edge本地唯一标识,>= 0表示有效,< 0 表示无效。
 *
 * 注:在同一产品ProductKey条件设备注册,不允许本接口和leda_register_and_online_by_device_name接口同时使用。 
 * 即每一个产品ProductKey设备注册必须使用同一接口,否则设备注册会发生不可控行为。
 */
device_handle_t leda_register_and_online_by_local_name(const char *product_key, const char *local_name, leda_device_callback_t *device_cb, void *usr_data);

leda_init

/*
 * 驱动模块初始化,模块内部会创建工作线程池,异步执行阿里云物联网平台下发的设备操作请求,工作线程数目通过worker_thread_nums配置。
 *
 * worker_thread_nums: 线程池工作线程数,该数值根据注册设备数量进行设置。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
int leda_init(int worker_thread_nums);

leda_exit

/*
 * 驱动模块退出。
 *
 * 模块退出前,释放资源。
 *
 * 阻塞接口。
 */
void leda_exit(void);

leda_get_driver_info_size

/*
 * 获取驱动信息长度。
 *
 * 阻塞接口,成功返回驱动信息长度,失败返回0。
 */
int leda_get_driver_info_size(void);

leda_get_driver_info

/*
 * 获取驱动信息(在物联网平台配置的驱动配置)。
 *
 * driver_info: 驱动信息,需要提前申请好内存传入。
 * size:        驱动信息长度,leda_get_driver_info_size,如果传入driver_info比实际配置内容长度短,会返回LE_ERROR_INVAILD_PARAM。
 *  
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 * 
 * 配置格式:
    {
        "json":{
            "ip":"127.0.0.1",
            "port":54321
        },
        "kv":[
            {
                "key":"ip",
                "value":"127.0.0.1",
                "note":"ip地址"
            },
            {
                "key":"port",
                "value":"54321",
                "note":"port端口"
            }
        ],
        "fileList":[
            {
                "path":"device_config.json"
            }
        ]
    }
 */
int leda_get_driver_info(char *driver_info, int size);

leda_get_device_info_size

/*
 * 获取设备信息长度。
 *
 * 阻塞接口,成功返回设备信息长度,失败返回0。
 */
int leda_get_device_info_size(void);

leda_get_device_info

/*
 * 获取设备信息(在物联网平台配置的设备配置)。
 *
 * device_info:  设备信息,需要提前申请好内存传入。
 * size:         设备信息长度,该长度通过leda_get_device_info_size接口获取,如果传入device_info比实际配置内容长度短,会返回LE_ERROR_INVAILD_PARAM。
 *  
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 * 
 * 配置格式:
    [
        {
            "custom":{
                "port":12345,
                "ip":"127.0.0.1"
            },
            "deviceName":"device1",
            "productKey":"a1ccxxeypky"
        }
    ]
 */
int leda_get_device_info(char *device_info, int size);

leda_get_config_size

/*
 * 获取驱动配置长度。
 *
 * 阻塞接口,成功返回驱动配置长度,失败返回0。
 */
int leda_get_config_size(void);

leda_get_config

/*
 * 获取驱动所有配置。
 *
 * config:       驱动配置,需要提前申请好内存传入。
 * size:         驱动配置长度,该长度通过leda_get_config_size接口获取,如果传入config比实际配置内容长度短,会返回LE_ERROR_INVAILD_PARAM。
 *  
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 * 
 * 配置格式:
    {
        "config":{
            "json":{
                "ip":"127.0.0.1",
                "port":54321
            },
            "kv":[
                {
                    "key":"ip",
                    "value":"127.0.0.1",
                    "note":"ip地址"
                },
                {
                    "key":"port",
                    "value":"54321",
                    "note":"port端口"
                }
            ],
            "fileList":[
                {
                    "path":"device_config.json"
                }
            ]
        },
        "deviceList":[
            {
                "custom":"{"port":12345,"ip":"127.0.0.1"}",
                "deviceName":"device1",
                "productKey":"a1ccxxeypky"
            }
        ]
    }
 */
int leda_get_config(char *config, int size);

config_changed_callback

/*
 * 驱动配置变更回调接口。
 *
 * config:       配置信息。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
typedef int (*config_changed_callback)(const char *config);

leda_register_config_changed_callback

/*
 * 订阅驱动配置变更监听回调。
 *
 * config_cb:      配置变更通知回调接口。
 *
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
int leda_register_config_changed_callback(config_changed_callback config_cb);

leda_get_tsl_size

/*
 * 获取指定产品ProductKey对应物模型内容长度。
 *
 * product_key:   产品ProductKey。
 *
 * 阻塞接口,成功返回product_key对应物模型内容长度,失败返回0。
 */
int leda_get_tsl_size(const char *product_key);

leda_get_tsl

/*
 * 获取指定产品ProductKey对应物模型内容。
 *
 * product_key:  产品ProductKey。
 * tsl:          物模型内容,需要提前申请好内存传入。
 * size:         物模型内容长度,该长度通过leda_get_tsl_size接口获取,如果传入tsl比实际物模型内容长度短,会返回LE_ERROR_INVAILD_PARAM。
 *  
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
int leda_get_tsl(const char *product_key, char *tsl, int size);

leda_get_tsl_ext_info_size

/*
 * 获取指定产品ProductKey对应物模型扩展信息内容长度。
 *
 * product_key:   产品ProductKey。
 *
 * 阻塞接口,成功返回product_key对应物模型扩展信息内容长度,失败返回0。
 */
int leda_get_tsl_ext_info_size(const char *product_key);

leda_get_tsl_ext_info

/*
 * 获取指定产品ProductKey对应物模型扩展信息内容。
 *
 * product_key:  产品ProductKey。
 * tsl_ext_info: 物模型扩展信息,需要提前申请好内存传入。
 * size:         物模型扩展信息长度,该长度通过leda_get_tsl_ext_info_size接口获取,如果传入tsl_ext_info比实际物模型扩展信息内容长度短,会返回LE_ERROR_INVAILD_PARAM。
 *  
 * 阻塞接口,成功返回LE_SUCCESS,失败返回错误码。
 */
int leda_get_tsl_ext_info(const char *product_key, char *tsl_ext_info, int size);

leda_get_device_handle

/*
 * 获取设备句柄。
 *
 * product_key: 产品ProductKey。
 * device_name: 设备名称DeviceName。
 *
 * 阻塞接口,成功返回device_handle_t,失败返回小于0数值。
 */
device_handle_t leda_get_device_handle(const char *product_key, const char *device_name);

7.2 Java版本SDK

设备接入SDK(Java版本)支持开发者使用Java语言开发设备接入驱动(以下简称驱动)。客户网关环境在安装有Link IoT Edge软件的条件下只要满足Java运行环境即可运行Java驱动。

Java版本开源的SDK源码请参见开源Java库

LedaConfig

  • 类名全称:com.aliyun.linkedge.sdk.LedaConfig

  • 类声明:

    public class LedaConfig
  • Java方法说明:| 限定符和类型 | 方法和说明 || :—- | :—- || static String | getDriverConfig()获取驱动配置。 || static String | getDeviceConfig()获取设备配置。 || static String | getTsl(String productKey)获取productKey(产品唯一标识符)对应的物模型(TSL)。 || static String | getTslConfig(String productKey)获取productKey对应的物模型扩展配置。 |

LedaDevice

  • 类名全称:com.aliyun.linkedge.sdk.LedaDevice

  • 类声明:

    public class LedaDevice
  • 构造函数:

    LedaDevice(String productKey, String deviceName)
  • Java方法说明:| 限定符和类型 | 方法和说明 || :—- | :—- || LedaData | getProperties(List propertyNameList)根据指定的属性名称,获取属性值。使用该方法时,需要实现重载(Overload)。 || int | setProperties(HashMap properties)设置属性名称和属性值。使用该方法时,需要实现重载。 || LedaData | callService(String methodName, HashMap params)执行自定义方法。使用该方法时,需要实现重载。 || int | online()上线设备。 || int | offline()下线设备。 || int | reportProperties(HashMap properties)上报设备属性。 || int | reportEvents(String eventName, HashMap outputData)上报设备事件。 |

数据类

  • 类名全称:com.aliyun.linkedge.sdk.LedaDevice

  • 类声明:

    public class LedaData
  • 构造函数:

    LedaData(int code, HashMap<String, Object> data)
  • Java方法说明:| 限定符和类型 | 方法和说明 || :—- | :—- || void | setCode(int code)设置状态码。 || int | getCode()获取状态码。 || void | setData(HashMap data)设置数据内容。 || HashMap | getData()获取数据内容。 |

错误码

  • 类名全称:com.aliyun.linkedge.sdk.exception.LedaErrorCode

  • 类声明:

    public class LedaErrorCode {
      public static final int LE_SUCCESS                              = 0;
      public static final int LE_ERROR_UNKNOWN                        = 100000;
      public static final int LE_ERROR_INVALID_PARAM                  = 100001;
      public static final int LE_ERROR_TIMEOUT                        = 100006;
      public static final int LE_ERROR_PARAM_RANGE_OVERFLOW           = 100007;
      public static final int LE_ERROR_SERVICE_UNREACHABLE            = 100008;
      public static final int LEDA_ERROR_DEVICE_UNREGISTER            = 109000;
      public static final int LEDA_ERROR_DEVICE_OFFLINE               = 109001;
      public static final int LEDA_ERROR_PROPERTY_NOT_EXIST           = 109002;
      public static final int LEDA_ERROR_PROPERTY_READ_ONLY           = 109003;
      public static final int LEDA_ERROR_PROPERTY_WRITE_ONLY          = 109004;
      public static final int LEDA_ERROR_SERVICE_NOT_EXIST            = 109005;
      public static final int LEDA_ERROR_SERVICE_INPUT_PARAM          = 109006;
      public static final int LEDA_ERROR_INVALID_JSON                 = 109007;
      public static final int LEDA_ERROR_INVALID_TYPE                 = 109008;
      private static final String LE_SUCCESS_MSG                      = "Success";                          /* 请求成功*/
      private static final String LE_ERROR_INVALID_PARAM_MSG          = "Invalid params";                   /* 传入参数为NULL或无效*/
      private static final String LE_ERROR_TIMEOUT_MSG                = "Tiemout";                          /* 超时*/
      private static final String LE_ERROR_PARAM_RANGE_OVERFLOW_MSG   = "Param range overflow";             /* 参数范围越界*/
      private static final String LE_ERROR_SERVICE_UNREACHABLE_MSG    = "Service unreachable";              /* 服务不可达*/
      private static final String LEDA_ERROR_DEVICE_UNREGISTER_MSG    = "Device has't register";            /* 设备未注册*/ 
      private static final String LEDA_ERROR_DEVICE_OFFLINE_MSG       = "Device has offline";               /* 设备已下线*/
      private static final String LEDA_ERROR_PROPERTY_NOT_EXIST_MSG   = "Property no exist";                /* 属性不存在*/
      private static final String LEDA_ERROR_PROPERTY_READ_ONLY_MSG   = "Property only support read";       /* 属性只读*/
      private static final String LEDA_ERROR_PROPERTY_WRITE_ONLY_MSG  = "Property only support write";      /* 属性只写*/
      private static final String LEDA_ERROR_SERVICE_NOT_EXIST_MSG    = "Service no exist";                 /* 服务不存在*/
      private static final String LEDA_ERROR_SERVICE_INPUT_PARAM_MSG  = "Service param invalid";            /* 服务的输入参数不正确错误码*/
      private static final String LEDA_ERROR_INVALID_JSON_MSG         = "Json format invalid";              /* JSON格式错误*/
      private static final String LEDA_ERROR_INVALID_TYPE_MSG         = "Param type invalid";               /* 参数类型错误*/
    }
  • Java方法说明:| 限定符和类型 | 方法和说明 || :—- | :—- || String | getMessage(int code)获取错误码对应的消息。 |