工具包引入

<dependency>
  <groupId>cn.allbs</groupId>
  <artifactId>allbs-model</artifactId>
  <version>0.6.0</version>
</dependency>

源码下载

解析&生成过程中自定义参数说明

应用场景 参数值 参数说明
指令生成 GeneratorEnum.ADDRESS.name 从站地址
指令生成 GeneratorEnum.FUNCTION.name 功能码
指令生成 GeneratorEnum.START_ADDRESS.name 起始寄存器地址
指令生成 GeneratorEnum.READ_ADDRESS.name 读寄存器地址
协议解析 data 数据信息
协议解析 circuit 回路
协议解析 point 点数
协议解析 gas_type 点位属性
协议解析 pre_gas_type 点位属性原始值
协议解析 gas_unit 气体单位
协议解析 pre_gas_unit 气体单位原始值
协议解析 gas_num 气体监测值
协议解析 detector_status 探测器状态
协议解析 pre_detector_status 探测器状态原始值
协议解析 detector_num 探测器浓度值
协议解析 extra_power 外控电源状态
协议解析 pre_extra_power 外控电源状态原始值
协议解析 address 地址
协议解析 function 功能
协议解析 controller_status 控制器状态
协议解析 pre_controller_status 控制器状态原始值

生成示例

代码

Map<String, Object> map = new HashMap<>(4);
// 地址
map.put(ADDRESS.getName(), 1);
// 功能码
map.put(FUNCTION.getName(), 3);
// 起始寄存器地址
map.put(START_ADDRESS.getName(), 0);
// 读寄存器数量
map.put(READ_ADDRESS.getName(), 2);
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
byte[] bytes = sfjk200Mapper.writeDataAsByteArray(map);

结果

image-20230310143214803

解析示例

读取 SFJK-200 控制器配置点数( 未配置点数时,返回回路 x 的值为 0x00 )所有请求数据 及响应数据均以 16 进制数据进行交换

image-20230309162532082

byte[] bytes = new byte[9];
bytes[0] = 0x01;
bytes[1] = 0x03;
bytes[2] = 0x04;
bytes[3] = 0x3F;
bytes[4] = 0x00;
bytes[5] = 0x00;
bytes[6] = 0x00;
bytes[7] = (byte) 0xf6;
bytes[8] = 0x27;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
System.out.println(sfjk200Mapper.readValue(bytes, 0x0000, Map.class));

image-20230309162610293

读取探测器属性及单位 ( 读取 1 回路 1 号点探测的浓度及属性,根据寄存器地址映射表查 到,1 号探测器对应寄存器地址为 0002H )数据高字节代表单位,低字节代表属性。

image-20230309162641484

byte[] bytes = new byte[9];
bytes[0] = 0x01;
bytes[1] = 0x03;
bytes[2] = 0x02;
bytes[3] = 0x01;
bytes[4] = 0x0A;
bytes[5] = (byte) 0x39;
bytes[6] = (byte) 0xD3;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
System.out.println(sfjk200Mapper.readValue(bytes, 0x0002, Map.class));

image-20230309164119135

连续读取 1 回路 3、4、5、6 号探测器属性及单位。(根据寄存器地址映射表查到 3 号探测 器从 0004H 地址开始 )

image-20230310094326283

byte[] bytes = new byte[13];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x08;
bytes[3] = (byte) 0x01;
bytes[4] = (byte) 0x0A;
bytes[5] = (byte) 0x01;
bytes[6] = (byte) 0x0D;
bytes[7] = (byte) 0x00;
bytes[8] = (byte) 0x81;

bytes[9] = (byte) 0x02;
bytes[10] = (byte) 0x82;
bytes[11] = (byte) 0x03;
bytes[12] = (byte) 0x22;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x0004, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

image-20230310100156371

读取 1 回路 1 号探测器的低限报警值( 假设 1 号探测器属性为甲烷,单位为%LEL.根据寄存 器地址映射表查到,1 号探测器对应寄存器地址为 03E2H)

image-20230310100226131

byte[] bytes = new byte[7];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;

bytes[2] = (byte) 0x02;
bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0xFA;
bytes[5] = (byte) 0x38;
bytes[6] = (byte) 0x07;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x03E2, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

** 注意:当前数据为全部除以10后的数据,因为解析和指令是分开的,所以需要根据指定中指定气体单位判断返回结果需不需要乘以10 **

image-20230310100553993

读取 1 回路 3、4、5、6 号探测器的低限报警值(3 号点属性为天然气,单位为%LEL .4 号 点为甲烷,单位为%LEL .5 号点属性为一氧化碳,单位为 μmol/mol,6 号点为氧气,单位为%V/V) 根据寄存器地址映射表查到,3 号探测器对应寄存器地址为 03E4H

image-20230310100818315

byte[] bytes = new byte[13];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x08;

bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0x64;
bytes[5] = (byte) 0x00;
bytes[6] = (byte) 0x96;
bytes[7] = (byte) 0x00;
bytes[8] = (byte) 0x78;

bytes[9] = (byte) 0x00;
bytes[10] = (byte) 0xBD;
bytes[11] = (byte) 0xB8;
bytes[12] = (byte) 0x64;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x03E4, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

** 注意:当前数据为全部除以10后的数据,因为解析和指令是分开的,所以需要根据指定中指定气体单位判断返回结果需不需要乘以10 **

image-20230310102142906

读取单个探测器状态(状态参考探测器状态定义)根据寄存器地址映射表查到,1 号探测器 对应寄存器地址为 07C2H

示例

image-20230310102213104

代码

byte[] bytes = new byte[7];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x02;

bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0x01;
bytes[5] = (byte) 0x79;
bytes[6] = (byte) 0x8E;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x07C2, Map.class);
map.forEach((k, v) -> {
if (k.equals("data")) {
    List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

输出

image-20230310103101955

** 示例CRC存在问题 **

读取 1 回路 3、4、5、6 号探测器的状态(根据寄存器地址映射表查到,3 号探测器对应寄 存器地址为 07C4H)

示例

image-20230310103158191

代码

byte[] bytes = new byte[13];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x08;

bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0x01;
bytes[5] = (byte) 0x00;
bytes[6] = (byte) 0x03;

bytes[7] = (byte) 0x00;
bytes[8] = (byte) 0x04;
bytes[9] = (byte) 0x00;
bytes[10] = (byte) 0x08;
bytes[11] = (byte) 0x81;
bytes[12] = (byte) 0x10;
SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x07C4, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

输出

image-20230310103618530

读取 1 回路 1 号点探测器的当前浓度值(根据寄存器地址映射表查到,1 号探测器对应寄存 器地址为 0BA2H )

image-20230310103646541

byte[] bytes = new byte[7];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x02;

bytes[3] = (byte) 0x01;
bytes[4] = (byte) 0x5A;
bytes[5] = (byte) 0x39;
bytes[6] = (byte) 0xEF;

SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x0BA2, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

** 注意:当前数据为全部除以10后的数据,因为解析和指令是分开的,所以需要根据指定中指定气体单位判断返回结果需不需要乘以10 **

image-20230310103831090

读取 1 回路 3、4、5、6 号探测器的低限报警值(3 号点属性为天然气,单位为%LEL .4 号 点为甲烷,单位为%LEL .5 号点属性为一氧化碳,单位为 μmol/mol,6 号点为氧气,单位为%V/V) 根据寄存器地址映射表查到,3 号探测器对应寄存器地址为 0BA4H

image-20230310103906086

image-20230310103915347

byte[] bytes = new byte[13];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x08;

bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0x64;
bytes[5] = (byte) 0x00;
bytes[6] = (byte) 0x96;

bytes[7] = (byte) 0x01;
bytes[8] = (byte) 0x40;
bytes[9] = (byte) 0x00;
bytes[10] = (byte) 0xD1;
bytes[11] = (byte) 0x38;
bytes[12] = (byte) 0x78;

SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x03E4, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

image-20230310104125705

读取 SFJK-200 外控电源状态( 外控电源状态请参考外控电压状态定义表 ) 1 回路外控电源 对应寄存器地址为 0f82H )

image-20230310104144513

byte[] bytes = new byte[9];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x04;

bytes[3] = (byte) 0x30;
bytes[4] = (byte) 0x30;
bytes[5] = (byte) 0x30;
bytes[6] = (byte) 0x30;

bytes[7] = (byte) 0xE1;
bytes[8] = (byte) 0x28;

SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x0F82, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

image-20230310104319682

读取 SFJK-200 控制器状态(SFJK-200 控制器状态参考控制器状态定义表 ) 根据寄存器地 址映射表查到,对应寄存器地址为 0F8AH

image-20230310104331648

byte[] bytes = new byte[7];
bytes[0] = (byte) 0x01;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x02;

bytes[3] = (byte) 0x00;
bytes[4] = (byte) 0x01;
bytes[5] = (byte) 0x79;
bytes[6] = (byte) 0x8E;

SFJK200Mapper sfjk200Mapper = new SFJK200Mapper();
Map<String, Object> map = sfjk200Mapper.readValue(bytes, 0x0F8A, Map.class);
map.forEach((k, v) -> {
    if (k.equals("data")) {
        List<Map<String, Object>> list = (List<Map<String, Object>>) v;
        list.forEach(System.out::println);
    } else {
        System.out.println(k + ":" + v);
    }
});

image-20230310104459414

** 示例中的CRC校验错误 **

模拟读写

使用工具modbus slave工具

image-20230314161609552

保存至influxdb结果

image-20230315102432432

下载modbus slave测试内容

Mbslave1.mbs Mbslave2.mbs Mbslave3.mbs Mbslave4.mbs Mbslave5.mbs Mbslave6.mbs Mbslave7.mbs

最后是使用的java开发的示例demo