利尔达科技集团股份有限公司
【技术分享】NB860+Lierda云平台=上电即上云——云管端协作让万物互联更简单(二)
来源:利尔达科技 作者:利尔达 日期:2022-10-28 浏览量:1202

  随着物联网行业的快速发展,越来越多的物联网云服务平台涌现。如何快速实现应用开发,如何管理,如何让设备快速上云,成为关注的焦点。


  第一期中我们介绍了基于MQTT协议快速接入利尔达物联网全连接云平台,本期我们将介绍如何使用NB860系列模组通过云云对接快速接入利尔达云平台,并介绍两者数据交互操作流程,帮助用户或开发人员尽快完成相关的应用开发。


  所需产品


  本次接入的利尔达物联网全连接云平台是我司自主研发的云平台,为设备提供安全可靠的连接管理能力,整合物联网产业链上下游,向下连接智能设备,向上承接物联网应用,形成端到云完整链路物联网解决方案,赋能企业各类IOT场景接入。


  另外用到的利尔达NB860/MB960/MB260系列模组是基于5G NB-IoT芯片自主开发的第三代NB-IoT模组。该款模组集高性价比、高安全性和低功耗等优点于一身,拥有蓝牙、OpenCPU等能力,为智能表计、智能烟感、智能停车、智慧路灯等百万级成熟NB-IoT应用提供了更优选择。


  利尔达NB860/MB960/MB260系列模组支持TCP/UDP、MQTT、LwM2M等多种协议接入云平台,为行业应用开发提供了更多的可能性。本文我们将为大家介绍利尔达NB860模组基于Lwm2m协议依托AEP平台实现云云对接功能快速接入利尔达物联网全连接云平台,实现数据交互。


  设备端流程:上电即上云


  利尔达NB860/MB960/MB260系列模组支持上电即上云。设备上电后,模组会自动向云平台发起流程操作,完成一系列驻网注册登录平台流程,用户在此期间无需任何指令配置即可完成云平台对接。


  云平台端流程:保姆级配置教程


  利尔达物联网全连接云平台提供了完善的云上配置流程及操作步骤。用户可通过文档中心查阅相关文档进行快速配置。点击进入详细教程链接


  一、在电信平台添加应用和产品


  在进行物联网平台云网关配置前,需在中国电信AEP平台完成产品创建,并添加应用。


  前提条件
  已完成中国电信AEP平台账号注册和认证。

  操作步骤
  1、登录中国电信AEP平台。
  2、在产品中心页面,单击右上角的创建产品。
  3、在弹出的对话框中,完成参数配置后,单击确定。
  本示例配置参数如下表所示。

  4、单击左侧导航栏的应用管理,单击页面右上角的新增应用,完成参数配置后,单击创建。可根据页面提示,自定义配置参数。应用创建完成后,在应用列表,单击该应用的查看详情按钮,查看并保存App Key和App Secret的值。
  5、在产品中心找到相应的产品定义电信物模型,电信非透传产品才能在电信平台定义物模型数据。


  二、在物联网平台创建产品


  您需要在物联网平台创建产品,产品名称最好与中国电信AEP平台产品名称一致,方便对应相应产品。


  前提条件

  已在中国电信AEP平台完成应用和产品添加。


  操作步骤

  1、登录物联网平台控制台。

  2、在右侧导航栏,单击创建产品,完成参数配置,单击确认,创建产品完成后系统将会自动订阅(包括设备上下线通知,设备数据变化通知,设备事件上报通知,设备指令响应通知),删除产品将会删除所有订阅。

  此处参数配置如下。

  3、在物联网云平台侧边栏点击产品管理,点击创建好的产品名称查看产品详情,点击物模型定义,点击编辑物模型进行新增物模型数据如下:

  属性:

  4、单击左侧导航栏的应用管理,单击页面右上角的新增应用,完成参数配置后,单击创建。


  *提示:在物联网云平台添加的物模型和电信平台添加的物模型可以不一致,中间通过物联网平台的数据脚本解析将两种物模型数据进行解析对应,但还是建议两个平台物模型保持一致,方便使用和创建数据解析脚本。


  三、使用云网关创建设备


  您只需要在物联网平台某一产品下创建设备,平台将会同步在电信平台相应的产品下创建设备,设备名称与中国电信AEP平台设备名称建议一致,以便对应查找。


  前提条件

  已在中国电信AEP平台完成应用和产品添加,已在物联网平台完成电信关联产品添加。


  操作步骤

  1、登录物联网平台控制台。

  2、点击上面导航栏中云平台,单击侧边栏设备管理,点击添加设备完成参数配置,单击确认。

  3、按照页面提示填写信息,然后单击确认。

  也可以使用批量导入导入电信设备,请下载模板使用模板导入。


  *提示:电信设备的设备ID需要去电信AEP平台查找,本平台不可见。


  四、创建云云对接数据解析脚本


  完成设备和产品物模型的创建,为了和电信AEP平台进行通信,物联网平台的物模型和中国电信平台物模型的数据格式不同,需要在产品管理相应产品下创建数据解析脚本进行格式转换。


  示例编写了电信非透传设备的JS脚本,如下:

  1   //上行:属性上报,事件上报

  2   var PROPERTY_REPORT_NAME = "property_report"; //属性上报。

  3   var EVENT_REPORT_NAME = "event_report"; //事件上报。

  4   var EVENT_HUMI_WARNING_PROPERTY = "TEST_EVENT";  // 测试事件,和后台物模型定义事件标识保持一致

  5

  6   // 下行:服务调用

  7   var EXAMPLE_SERVCE_IDENTIFY = "ontemp";

  8

  9

  10   /**

  11   * 上行平台间物模型数据格式转换

  12   *

  13   */

  14   function rawDataToProtocol(strString) {

  15      var jsonMap = {}

  16      var report = JSON.parse(strString);

  17

  18      if (report.reportType == 1) {

  19          jsonMap['report_type'] = PROPERTY_REPORT_NAME; //必要字段,JSON格式,属性上报

  20      var params = {};

  21      params['temp'] = report.temp; //对应产品属性中temp。

  22      jsonMap['params'] = params; //必要字段,JSON格式,属性上报参数。

  23   } else if(report.reportType == 2) {

  24       jsonMap['report_type'] = EVENT_REPORT_NAME; //必要字段,JSON格式,事件标识。

  25      // 判断事件标识

  26       jsonMap['event'] = EVENT_HUMI_WARNING_PROPERTY;

  27       var params = {};

  28       params['temp'] = report.temp; //对应产品属性中prop_int16。

  29      jsonMap['params'] = params; //必要字段,JSON格式,事件上报参数。

  30   }

  31    // 必须stringify 格式化

  32   return JSON.stringify(jsonMap);

  33   }

  34

  35   /**

  36   * 下行平台间物模型数据格式转换

  37   *

  38   */

  39   function protocolToRawData(json) {

  40      var result ={};

  41      var obj= JSON.parse(json);

  42      var params=obj.params;

  43 result.serviceIdentify=EXAMPLE_SERVICE_IDENTIFY; //必要字段,JSON格式,服务标识。

  44      result.params=params; //必要字段,JSON格式,服务调用参数。

  45      return JSON.stringify(result);

  46   }


  脚本写完后可以在旁边的模拟数据中先进行测试,如果所有的模拟数据对应的模拟运行结果如预期一样则说明脚本编写完成,如下:

  电信透传设备JS脚本编写可参考如下:

  1   var PROPERTY_REPORT_VALUE = 0x00; //属性上报。

  2   var PROPERTY_REPORT_NAME = "property_report"; //属性上报。

  3   var EVENT_REPORT_VALUE = 0x01; //事件上报。

  4   var EVENT_REPORT_NAME = "event_report"; //事件上报。

  5

  6

  7   var EVENT_HUMI_WARNING_VALUE =1;  // 湿度告警标识

  8   var EVENT_HUMI_WARNING_PROPERTY = "TEST_EVENT";  // 湿度告警标识,和后台物模型定义事件标识保持一致

  9

  10   var COMMAND_TYPE_FLAG = "command_type";  //下行指令类型标识符号

  11

  12

  13   // service 示例

  14   var EXAMPLE_SERVICE_IDENTIFY = "service1";

  15   var EXAMPLE_SERVICE_IDENTIFY_VALUE = 1;

  16

  17

  18   // 属性上报  head+参数1+参数2+......

  19   var property_report = "00f0ff013FA00000";

  20   // 事件上报 head+ 事件标识 + 参数1+参数2+......

  21   var event_report = "0101f0ff013FA00000";

  22

  23   /**

  24   * 上行16进制字符串转物模型JSON入口

  25   *

  26   */

  27   function rawDataToProtocol(strString) {

  28      var bytes = str2Bytes(strString);

  29      var uint8Array = new Uint8Array(bytes.length);

  30      for (var i = 0; i < bytes.length; i++) {

  31          uint8Array[i] = bytes[i] & 0xff;

  32      }

  33      var dataView = new DataView(uint8Array.buffer, 0);

  34      var jsonMap = new Object();

  35      var fHead = uint8Array[0]; // command

  36

37      if (fHead == PROPERTY_REPORT_VALUE) {

  38         jsonMap['report_type'] = PROPERTY_REPORT_NAME; //必要字段,JSON格式,属性上报topic。

  39          var params = {};

  40          params['prop_int'] = dataView.getInt8(1); //对应产品属性中prop_int16。

  41       params['uint8_prop'] = dataView.getUint8(2); //对应产品属性中prop_bool。

  42          params['bool_prop'] =  uint8Array[3];

  43          params['prop_float'] = dataView.getFloat32(4); //对应产品属性中prop_float。

  44          jsonMap['params'] = params; //必要字段,JSON格式,属性上报参数。

  45      } else if(fHead == EVENT_REPORT_VALUE) {

  46         jsonMap['report_type'] = EVENT_REPORT_NAME; //必要字段,JSON格式,属性上报。

  47

  48         var event_flag_value = uint8Array[1];

  49         // 判断事件标识

  50         if(event_flag_value == EVENT_HUMI_WARNING_VALUE){

  51             jsonMap['event'] = EVENT_HUMI_WARNING_PROPERTY;

  52         }

  53         var params = {};

  54         params['prop_int'] = dataView.getInt8(2); //对应产品属性中prop_int16。

  55      jsonMap['params'] = params; //必要字段,JSON格式,事件上报参数。

  56      }

  57       // 必须stringify 格式化

  58      return JSON.stringify(jsonMap);

  59      }

  60

  61

  62      /**

  63      * 下行json格式数据转十六进制字符串入口

  64      *

  65      */

  66      function protocolToRawData(json) {

  67      var command_type = json['command_type'];

  68      var payloadArray = [];

  69

  70      // 参数

  71      var params = json['params'];

  72      var prop_float = params['prop_float'];

  73      var prop_int16 = params['prop_int'];

  74      var prop_bool = params['prop_bool'];

  75      var prop_int = params['on'];

  76

  77      payloadArray = payloadArray.concat(buffer_uint8(COMMAND_SERVICE_CALL_VALUE));  //command字段。

  78

  79      //判断服务标识,自定义服务标识对应的标识值

  80   if(json['service_identify']==EXAMPLE_SERVICE_IDENTIFY){

  81          payloadArray = payloadArray.concat(buffer_uint8(EXAMPLE_SERVICE_IDENTIFY_VALUE));

  82      }

  83      payloadArray = payloadArray.concat(buffer_int16(prop_int16)); //属性'prop_int16'的值。

  84

  85      return bytes2Str(payloadArray);

  86   }

  87

  88

  89   //以下是部分辅助函数。

  90   function buffer_uint8(value) {

  91      var uint8Array = new Uint8Array(1);

  92      var dv = new DataView(uint8Array.buffer, 0);

  93      dv.setUint8(0, value);

  94      return [].slice.call(uint8Array);

  95   }

  96   function buffer_int16(value) {

  97      var uint8Array = new Uint8Array(2);

  98      var dv = new DataView(uint8Array.buffer, 0);

  99       dv.setInt16(0, value);

  100      return [].slice.call(uint8Array);

  101   }

  102   function buffer_int32(value) {

  103     var uint8Array = new Uint8Array(4);

  104     var dv = new DataView(uint8Array.buffer, 0);

  105     dv.setInt32(0, value);

  106     return [].slice.call(uint8Array);

  107   }

  108

  109

  110   /*

  111   字符串转字节数组

  112   */

  113   function str2Bytes(str)

  114   {

  115      var pos = 0;

  116      var len = str.length;

  117      if(len %2 != 0)

  118      {

  119      return null;

  120      }

  121

  122   len /= 2;

  123      var hexA = new Array();

  124      for(var i=0; i<len; i++)<="" span="">

  125      {

  126         var s = str.substr(pos, 2);

  127         var v = parseInt(s, 16);

  128         hexA.push(v);

  129         pos += 2;

  130      }

  131      return hexA;

  132   }

  133

  134   /* 字节数组转字符串 */

  135   function bytes2Str(arr)

  136   {

  137   var str = "";

  138      for(var i=0; i<arr.length; i++)<="" span="">

  139      {

  140      var tmp = arr[i].toString(16);

  141      if(tmp.length == 1)

  142         {

  143             tmp = "0" + tmp;

  144      }

  145         str += tmp;

  146   }

  147      return str;

  148   }


五、效果展示


  至此,我们已完成电信平台应用,产品,产品物模型创建,物联网平台电信关联产品,设备,产品物模型创建,数据解析脚本编写。


  数据上行

  设备上电入网后自动注册到平台,可在设备列表中看到设备连接状态为在线。

  通过AT指令AT+NMGS向平台发送数据(如不符合定义的物模型数据,将会解析错误),即可在物联网平台的设备物模型设备数据中的属性上报看到结果。

  数据下行

  在线调试,选择透传调试,输入有效的数据点击发送。

  设备收到消息为:

  至此,我们已完成依托AEP平台与利尔达物联网全连接云平台进行云云对接的端(Lierda NB860模组)到云(物联网全连接云平台)对接实现数据交互功能。第三期我们将介绍NB860模组配合利尔达物联网全连接云平台基于TCP协议进行直连对接快速上云,敬请期待。