当前位置: 首页 >应用方案 >技术应用 >

利用云平台脚本解析连接物模型(二)

之前的亿佰特技术文章中我们简单介绍了利用JavaScriptECMAScript 5脚本解析Alink JSON实现Modbus协议采集RTU设备,本文将利用“功能定义”通过“READ_R”的不同“枚举值”实现多台Modbus从机设备的寄存器采集。

这次我们使用真实的RTU进行开发,一台MA01-AXCX4040用于采集DI上传,一台GPS设备上传NMEA0183协议的RMC定位字符串数据。

手动发送数据过于麻烦,若采用云平台脚本自动发送对于PLC工程师比较陌生,这里小编将结合MQTT模式”与串口服务器的“主动上报网关”实现物模型的数据自动更新。

一.硬件准备

一台串口服务器,用于连接MQTT服务器和主动轮询RTU设备并上报服务器;

一台MA01-AXCX4040远程IO联网模块(标准Modbus RTU设备),响应主机请求(上报DI状态);

1 MA01-AXCX4040部分寄存器描述


功能描述

寄存器类型

寄存器

数量

支持功能码

干接点采集

离散量输入

0x0000

4

0x02

开关量输出

线圈

0x0000

4

0x010x050x0F

Modbus地址

保持寄存器

0x07e8

1

0x030x060x10

一台支持Modbus RTU协议GPS采集模块,通过读取保持寄存器值显示当前定位信息(字节序:大端,字序:大端)共计70字节字符串;

2 GPS定位模块部分寄存器描述

功能描述

寄存器类型

寄存器

数量

支持功能码

RMC数据

保持寄存器

0x0005

35

70字节大端字符)

0x02

Modbus地址

保持寄存器

0x0002

1

0x030x060x10

保证设备供电与正确接入互联网,将采用阿里云MQTT服务器实现远程采集控制,因此无法在局域网中实现该功能。

二.云平台

1.产品与设备创建

参考之前的文章《利用云平台脚本解析连接物模型(》,这里我就不再说明如何配置。

这里我就利用上次创建的设备修改JavaScript脚本”和“功能定义”实现本文功能,不在额外的创建新设备。

2.修改“功能定义”

修改原有的“读取寄存器”配置,增加枚举描述和枚举值,这个值会在脚本中使用并且会作为指令的地址位使用,不可随意定义。

1读取寄存器配置

添加ME31-AXCX4040相关功能定义“开关量采集第一路”,以类似方法可以定义其余三路开关量采集与开关量输出反馈;

添加GPS相关功能定义GPS定位数据”,使用字符串,长度限制70字节(可以不限制);

2开关量采集

修改JavaScript脚本(ECMAScript 5)

笔者仅学习过C语言,对于脚本语言并不了解,所有使用脚本函数均是修改阿里云教程和在W3SCHOOL中查询得到,若有更简单的字符串解析函数,以你为准。我这只是提供一种方法,不一定为最优解。

/*此函数将设备上报数据转换为Alink JSON物模型数据。*/

function rawDataToProtocol(bytes) {

   /*将设备上报的原始数据转换为数组。其中bytes对象中存储着设备上报原始数据。*/

   var uint8Array = new Uint8Array(bytes.length);

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

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

   }

   var params = {};                            // 定义属性存放对象。

   var jsonMap = { };                           // 定义模拟Alink数据报对象。

   /*填写Alink数据报协议头部分。*/

   jsonMap['version'] = ALINK_VERSION;         // Alink 协议版本号。

   jsonMap['id'] = ALINK_ID;                   // 消息ID

   jsonMap['method'] = ALINK_PROP_POST_METHOD; // 设备上行数据方法:设备属性上报。

   /*填写Alink数据报属性部分。*/

   //ME31-AXCX4040:01020100

   //GPS:020346(70字节数据:$GNRMC,072905.00,A,3640.46260,N,11707.54950,E,000.0,000.0,050119,OK*20)2字节CRC

   if(uint8Array[0]==0x01){

       switch(uint8Array[3]){

           case 0x00: params['DI1']=0;break;

           case 0x01: params['DI1']=1;break;

       }

   }else if(uint8Array[0]==0x02){

       var rmc_str="";

       var count;

       for(count=3;count<bytes.length-2;count++){

//从最后插入数字转字符,累计处理70次,得到GPS-RMC字符串

           rmc_str=rmc_str.concat(String.fromCharCode(uint8Array[count]));

       }

       params['GPS_RMC']=rmc_str;

   }

   jsonMap['params'] = params;                 // 将参数打包到数据帧中。

   return jsonMap;                             // 返回结果会发送给物联网平台。

}

根据Modbus地址编码平台下发指令,如下所示:

/*此函数实现由物联网平台下发数据转换为设备能识别的16进制数。*/

function protocolToRawData(json)

{

   var method = json['method'];

   var id = json['id'];

   var version = json['version'];

   var payloadArray = [];

   if (method == ALINK_PROP_SET_METHOD)    // 接收来自物联网平台的“设置设备属性”的命令。

   {

       var send_params = json['params'];

       var prop_cur = send_params['READ_R'];   // 将设置的具体值抽取出来。

       //按照自定义协议格式拼接rawdata

       payloadArray = payloadArray.concat(buffer_uint8(prop_cur));

       if(prop_cur == 1){

           //添加查询ME31-AXCX4040第一路指令

           payloadArray = payloadArray.concat(buffer_uint8(0x02));

           payloadArray = payloadArray.concat(buffer_uint8(0x00));

           payloadArray = payloadArray.concat(buffer_uint8(0x00));

           payloadArray = payloadArray.concat(buffer_uint8(0x00));

           payloadArray = payloadArray.concat(buffer_uint8(0x01));

           payloadArray = payloadArray.concat(buffer_uint8(0xB9));

           payloadArray = payloadArray.concat(buffer_uint8(0xCA));

       }else if(prop_cur == 2){

           //添加查询GPS-RMC字符串

           payloadArray = payloadArray.concat(buffer_uint8(0x03));

           payloadArray = payloadArray.concat(buffer_uint8(0x00));

           payloadArray = payloadArray.concat(buffer_uint8(0x05));

           payloadArray = payloadArray.concat(buffer_uint8(0x00));

           payloadArray = payloadArray.concat(buffer_uint8(0x23));

           payloadArray = payloadArray.concat(buffer_uint8(0x14));

           payloadArray = payloadArray.concat(buffer_uint8(0x21));

       }


   }

   return payloadArray;    // 返回时,将数据发送至设备端。

}

ME31-AXAX4040上报数据解析;

3上报数据解析

GPS上报数据解析,以123456为例(实际数据为70字节);

4GPS数据上报

物模型下发读取ME31-AXAX4040第一路DI状态指令;

5ME31联网模块

物模型下发读取GPS数据指令;

6GPS数据指令

三.MQTT X仿真测试

在调试使用工具先测试功能是否正常,若不经过此步骤直接连接设备,若通讯失败难以分析问题导致无法实现功能。

配置连接参数,参考《利用云平台脚本解析连接物模型(一)》;

1.测试平台请求

7阿里云测试平台

2.测试设备响应

8测试设备

四.配置RTU设备

在脚本中我们指定了不同Modbus地址连接不同的设备,比如指定

MA01-AXCX4040使用地址1,指定GPS定位模块使用地址2,在脚本解析中利用地址不同执行不同的解析函数,从而将数据保存到正确变量下。

Modbus协议的响应帧只有地址码和功能码并不返回请求的寄存器地址导致设备无法调用正确的解析函数,如果要实现同一设备地址的不同寄存器地址采集则需要在请求时记录发送的寄存器地址,因此实现同一设备不同寄存器请求时需要采用与Modbus机制相同的采集机制(主从模式,主机请求从机应答,一请一答),这个问题留到下篇文章中处理,现在只考虑每个地址读取一个连续寄存器的情况。

1.配置MA01-AXCX4040

软件地址配置(出厂默认为1):

9软件地址配置

硬件地址(全部拨向背离数字一侧,出厂默认为31,需要修改为1):

10联网模块设置

2.配置GPS模块

查询Modbus寄存器表可以知道保持地址的寄存器位(0x0002),通过Modbus指令配置Modbus地址为2,如下图所示;

11GPS模块

五.实机演示

1.普通模式

可通过串口服务器MQTT模式连接阿里云物模型,并通过平台手动请求RTU设备返回数据,串口服务器配置如下:

11串口服务器模型

云平台通过“在线调试”手动发送查询DI指令;

12物联网云平台调试

云平台通过“在线调试”手动发送查询GPS指令;


13查询GPS指令

2.自动上报模式

可以利用串口服务器的Modbus网关”主动上报功能实现,周期更新数据,Modbus RTU轮询间隔免费用户不建议小于1000ms,轮询间隔指的是每条指令的间隔,例如这里配置的间隔为10s,平台将以20s的周期刷新平台数据;

14串口服务器自动上报模式

15串口服务器自动上报模式


https://www.wjx.cn/jq/84863372.aspx