ModBus JS 通讯协议解码器

介绍

Fox-Edge的ModBus的通用解码器,它只需要配置配置ModBus的模板文件,就可以进行ModBus报文协议的数据解析。

如果你的ModBus设备的命令比较简单,那么可以不使用模板,而是直接配置操作参数的方式,进行设备操作。

资料

ModBus协议中文版

工具

考虑到很多开发者手头上并没有MODBUS物理设备,可以先使用MODBUS设备模拟器进行新手上路。

等你能够对MODBUS设备模拟器进行操作之后,你可以将MODBUS模拟器替换为你手头上的MODBUS物理设备,就可以直接通信了。

推荐工具:
ModBus设备模拟器:ModbusSlave
ModBus客户端工具:ModbusPoll

你可以在下载和安装这两个工具之后,使用ModbusSlave模拟一个TCP的MODBUS设备,然后使用ModbusPoll工具使用TCP方式去连接这ModbusSlave。

这时候,你会看到ModbusPoll会循环读取ModbusSlave的表格数据,你在ModbusPoll上修改表格数据,它也会被配置到ModbusSlave中去。

概念

关于MODBUS

很多开发者一开始没有接触过MODBUS,对MODBUS缺失概念,然后会摸不着头脑。

在MODBUS中,是一种类似内存地址的通信协议,它的数据放在连续的内存地址当中,只不过它的内存地址,在MODBUS中叫做寄存器。

我们的计算机每一个内存地址存放的是8位的数据,而MODBUS寄存器存放的是一个16位的数据。

设备厂商,通常会把MODBUS设备的数据放到一个个的寄存器中,你想对MODBUS设备进行操作的时候,就是读取寄存器数据和写入寄存器数据。

你对MODBUS设备的操作,就是读取和写入寄存器。

那么跟着对应的就是,每一个MODBUS设备的生产厂商,他们都会提供一个地址表,告诉你它在哪个寄存器上是如何存储内存数据的。

你对MODBUS设备的操作,就是根据设备厂商提供给你的那一份表,按整数、浮点数、定点数、布尔值,读取和写入数据到寄存器。

技术方案

Fox-Edge提供了一个通过模板进行配置,就能快速操作MODBUS设备的办法。

组件

假设,你的MODBUS设备是TCP连接,那么先从 组件仓库>服务模块 页面中安装 tcp-client 通道服务,用于跟MODBUS设备建立通信连接。

然后,你从 组件仓库>动态解码 安装 MODBUS 解码器,用于跟MODBUS设备通信需要的编码和解码

模板

模板文件

可以参考下列文件的格式,自己配置配置一个模板文件,那么可以让解码器装载这些模板文件,就可以自动解析数据

文件

fox-edge
├─template
│  ├─modbus
│  │  └─1.0.0
│  │    └─101.CETUPS_Read System Measures Table.csv
│  │    └─100.CETUPS_Read Alarms And Events Table.csv
│  │    └─103.CETUPS_Input Status Table.csv
│  │    └─102.CETUPS_Coil Status Table.csv

格式说明

value_name value_index bit_index bit_length value_type magnification determine remark
对象名称 modbus地址 该地址bit位 占用多少个bit 数据类型 放大倍数 判定方式 备注
说明:ModBus解码器会根据这张表,对设备进行读取数据后,进行解析成方便用户理解的数据对象

1、value_index
也就是modbus中的地址偏移量。对于一个modbus偏移量来说,它的大小为16位的空间

2、bit_index和bit_length
有些设备厂家为了节省空间,会将一批告警状态数据保存在设备的某个ModBus地址偏移量当中。对于这种用一个16位地址
保存一批状态数据的设备,可以采用bit_index和bit_length自动分拆成一批对象

3、value_type
modbus设备的16位数据,可以被设备厂家们用来保存bool、int、float等数据格式,解码器会对这16位数据进行相应的解析

4、magnification
有些设备厂家,为了保存非常大数值的数据,会采用定点数的方式,在16位mosbus地址空间上,约定放大了一定的倍数保存。

5、determine
对于bool类型的数值,什么时候是true,什么时候是false,厂商们通常会有特定的数值约定,可以通过判定方式判定具体的bool数值


说明:
具体内容,可以参考101.CETUPS_Read System Measures Table.csv文件内容

步骤

1. 模拟器准备

在本地计算机上,安装好下面两个MODBUS工具,用于模拟MODBUS设备的客户端

ModBus设备模拟器:ModbusSlave

ModBus客户端工具:ModbusPoll

根据默认配置,你可以在ModbusPoll上,连接到ModbusSlave,并读取到ModbusSlave上的表格数据。

而且,你在ModbusPoll上的表格修改数据,也会被发送到ModbusSlave上修改。

你测试这对MODBUS模拟器工具通过后,就可以在Fox-Edge跟它ModbusSlave进行连接了

2. 组件安装

在Fox-Edge上的 组件仓库>服务模块 选择安装TCP或者Serial通道服务。

在Fox-Edge上的 组件仓库>动态界面 选择安装MODBUS解码器

3. 通道配置

在Fox-Edge上的 通道管理>通道列表 添加一个TCP或者Serial的通道

如果是TCP参数,它的格式范例如下:

{
     "host": "192.168.1.8",
     "port": 502
}

其中,host/port是你的MODBUS设备的服务地址,目前是ModbusSlave这个设备模拟器的服务地址,由于ModbusSlave安装在你的计算机上,那么它就是你笔记本的IP。

如果是Serial参数,它的格式范例如下:

{
     "baudRate": 9600,
     "databits": 8,
     "parity": "N",
     "serialName": "ttyUSB2",
     "stopbits": 1
}

如果你安装了 本地组件/设备模板 ,那么你可以直接生成默认的通道配置参数

4. 设备配置

在Fox-Edge上的 通道管理>设备列表 添加一个MODBUS设备,指明该设备使用的是前面创建的通道

并在参数配置中,填写MODBUS的地址和协议模式

如果是TCP参数,它的格式范例如下:

{
     "devAddr": 1,
     "modbusMode": "TCP"
}

同样,如果你是串口,那么你的工作模式应该填为RTU

{
     "devAddr": 1,
     "modbusMode": "RTU"
}

如果你安装了 本地组件/设备模板 ,那么你可以直接生成默认的设备配置参数

5. 连接测试

在Fox-Edge上的 任务管理>通道操作任务 添加一个连通性测试任务,用于测试跟MODBUS设备是否连接上了。

你可以在ModbusSlave或者ModbusPoll的通信日志页面,取一条有效的通信报文,作为验证报文。

例如你是TCP通信,你在ModbusSlave的通信日志页面,复制一条通信数据内容如下:

"1B 51 00 00 00 06 01 03 00 00 00 0A"

这时候,你可以把该内容填写到模板参数中

这时候,你选择该任务后,点击页面中的发送按钮,你可以看到ModbusSlave给你返回了一段报文:

{
     "type": "tcp-client",
     "uuid": "25364b96-06a5-49d0-bbe2-534e0abc6dd4",
     "name": "测试通道-MODBUS",
     "mode": "exchange",
     "send": "1B 51 00 00 00 06 01 03 00 00 00 0A",
     "recv": "1b5100000017010314006f029a00000000000000000000000000000000",
     "timeout": 2000,
     "msg": "",
     "code": 200
}

recv有数据,这时候说明你的通道连接,跟ModbusSlave是正常的,它能够应答你的Fox-Edge上的HEX报文请求。

6. 设备操作

在Fox-Edge上的 任务管理>设备操作任务 MODBUS设备操作任务,比如 Read Holding Register 的操作任务。

参数说明:

{
     "devAddr": 1,---------------------------设备地址
     "modbusMode": "TCP",--------------------MODBUS的工作模式:TCP/RTU
     "modelList": [--------------------------告知MODBUS解码器,数据如何编码/解码
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",
               "remark": "0号寄存器",
               "value_index": "0",
               "value_name": "温度",
               "value_type": "int"
          },
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",--------放大/缩小倍数:默认1,也就是x1
               "remark": "1号寄存器",
               "value_index": "1",----------寄存器的地址,是1
               "value_name": "湿度",--------这个数据对象的名称:湿度
               "value_type": "int"----------寄存器数据的格式是int
          }
     ],
     "regAddr": 0,--------------------------告知解码器,从0号寄存器开始,连续读取2个寄存器
     "regCnt": 2
}

范例:

{
     "devAddr": 1,
     "modbusMode": "TCP",
     "modelList": [
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",
               "remark": "0号寄存器",
               "value_index": "0",
               "value_name": "温度",
               "value_type": "int"
          },
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",
               "remark": "1号寄存器",
               "value_index": "1",
               "value_name": "湿度",
               "value_type": "int"
          }
     ],
     "regAddr": 0,
     "regCnt": 2
}

这时候,你选择该任务后,点击页面中的发送按钮,你可以看到ModbusSlave给你返回了一段报文:

[
     {
          "uuid": "8b843b8a-d6e9-4444-8a7f-a938ae9d251b",
          "operateMode": "exchange",
          "operateName": "Read Holding Register",
          "manufacturer": "广州灵狐技术有限公司",
          "deviceType": "MODBUS",
          "deviceName": "测试设备:MODBUS",
          "param": {
               "devAddr": 1,
               "modbusMode": "TCP",
               "modelList": [
                    {
                         "bit_index": "0",
                         "bit_length": "16",
                         "determine": "",
                         "magnification": "1",
                         "remark": "0号寄存器",
                         "value_index": "0",
                         "value_name": "温度",
                         "value_type": "int"
                    },
                    {
                         "bit_index": "0",
                         "bit_length": "16",
                         "determine": "",
                         "magnification": "1",
                         "remark": "1号寄存器",
                         "value_index": "1",
                         "value_name": "湿度",
                         "value_type": "int"
                    }
               ],
               "regAddr": 0,
               "regCnt": 2
          },
          "timeout": 2000,
          "record": true,
          "data": {
               "commStatus": {
                    "commFailedCount": 0,
                    "commFailedTime": 0,
                    "commSuccessTime": 1753800297247-------通信成功了,操作成功的时间
               },
               "value": {
                    "status": {
                         "温度": 111,---------------------可以看到数据被读取到,并解析为温度111读
                         "湿度": 42
                    }
               }
          },
          "msg": "",
          "code": 200---------------------------------------操作成功
     }
]

上面的返回,说明你对MODBUS设备已经正常访问了

7. 模板应用

通过上面的操作,你可以简单的访问MODBUS设备了,但是MODBUS的设备,它往往是比较多的寄存器的。

所以,Fox-Edge提供了设备模板的方案,在上面的基础上进行简化配置。

1.下载CSV模板

用户可以先下载CSV模板

2.下载CSV模板

将厂商提供的MODBUS数据定义表,按CSV文件的固定格式写入CSV文件中

3.转为为JSON格式

将CSV文件的内容,复制到线上网站 https://wejson.cn/csv2json/ 将CSV格式转换为JSON格式。

实际上,这个CSV模板转为JSON后,对应的就是前面的JSON格式的modelList的参数

     "modelList": [
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",
               "remark": "0号寄存器",
               "value_index": "0",
               "value_name": "温度",
               "value_type": "int"
          },
          {
               "bit_index": "0",
               "bit_length": "16",
               "determine": "",
               "magnification": "1",
               "remark": "1号寄存器",
               "value_index": "1",
               "value_name": "湿度",
               "value_type": "int"
          }
     ]

4.保存为动态模板

回到Fox-Edge的 本地组件/动态模板 中,创建一个动态模板,指明为MODBUS引擎,然后网站上转换的JSON格式模板内容,贴入配置参数中。

记住这个名称,例如你会在模板中看到:广州灵狐技术有限公司|测试MODBUS设备|保持寄存器地址表

那么,后面你就可以反复使用这个模板,应用到其他Fox-Edge项目中。

5.使用动态模板

在Fox-Edge上的 任务管理>设备操作任务 MODBUS设备操作任务,比如 Read Holding Register 的操作任务。

使用模板进行操作设备,将前面的modelList换成modelName

{
     "devAddr": 1,
     "modbusMode": "TCP",
     "modelName": "广州灵狐技术有限公司|测试MODBUS设备|保持寄存器地址表",
     "regAddr": 0,
     "regCnt": 2
}

通过动态模板modelName,你可以简化大量的配置,而通过动态模板modelList,你可以逐个验证每个寄存器的配置。

8. 自动采集

在Fox-Edge上的 任务管理>设备监控任务 添加一个设备监控任务,用于自动采集MODBUS设备的数据。

你将前面在 任务管理>设备操作任务 验证过的一个个手动操作任务,将内容复杂到 任务管理>设备监控任务 之中。

然后,设备监控任务会根据你的任务编排,周期性的采集数据。

最后,将采样到的数据,发送给持久化服务中,保存到redis和mysql数据库中,那么后面其他服务就可以消费这些数据了。

"1B 51 00 00 00 06 01 03 00 00 00 0A"

这时候,你可以把该内容填写到模板参数中

这时候,你选择该任务后,点击页面中的发送按钮,你可以看到ModbusSlave给你返回了一段报文:

{
     "type": "tcp-client",
     "uuid": "25364b96-06a5-49d0-bbe2-534e0abc6dd4",
     "name": "测试通道-MODBUS",
     "mode": "exchange",
     "send": "1B 51 00 00 00 06 01 03 00 00 00 0A",
     "recv": "1b5100000017010314006f029a00000000000000000000000000000000",
     "timeout": 2000,
     "msg": "",
     "code": 200
}

recv有数据,这时候说明你的通道连接,跟ModbusSlave是正常的,它能够应答你的Fox-Edge上的HEX报文请求。