SFJK-200 可燃气体控制器 MODBUS 通讯协议
工具包引入
<dependency>
<groupId>cn.allbs</groupId>
<artifactId>allbs-model</artifactId>
<version>0.6.0</version>
</dependency>
源码下载
引用站外地址
解析工具的源码下载
github
解析&生成过程中自定义参数说明
应用场景 | 参数值 | 参数说明 |
---|---|---|
指令生成 | 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);
结果
解析示例
读取 SFJK-200 控制器配置点数( 未配置点数时,返回回路 x 的值为 0x00 )所有请求数据 及响应数据均以 16 进制数据进行交换
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));
读取探测器属性及单位 ( 读取 1 回路 1 号点探测的浓度及属性,根据寄存器地址映射表查 到,1 号探测器对应寄存器地址为 0002H )数据高字节代表单位,低字节代表属性。
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));
连续读取 1 回路 3、4、5、6 号探测器属性及单位。(根据寄存器地址映射表查到 3 号探测 器从 0004H 地址开始 )
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);
}
});
读取 1 回路 1 号探测器的低限报警值( 假设 1 号探测器属性为甲烷,单位为%LEL.根据寄存 器地址映射表查到,1 号探测器对应寄存器地址为 03E2H)
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 **
读取 1 回路 3、4、5、6 号探测器的低限报警值(3 号点属性为天然气,单位为%LEL .4 号 点为甲烷,单位为%LEL .5 号点属性为一氧化碳,单位为 μmol/mol,6 号点为氧气,单位为%V/V) 根据寄存器地址映射表查到,3 号探测器对应寄存器地址为 03E4H
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 **
读取单个探测器状态(状态参考探测器状态定义)根据寄存器地址映射表查到,1 号探测器 对应寄存器地址为 07C2H
示例
代码
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);
}
});
输出
** 示例CRC存在问题 **
读取 1 回路 3、4、5、6 号探测器的状态(根据寄存器地址映射表查到,3 号探测器对应寄 存器地址为 07C4H)
示例
代码
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);
}
});
输出
读取 1 回路 1 号点探测器的当前浓度值(根据寄存器地址映射表查到,1 号探测器对应寄存 器地址为 0BA2H )
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 **
读取 1 回路 3、4、5、6 号探测器的低限报警值(3 号点属性为天然气,单位为%LEL .4 号 点为甲烷,单位为%LEL .5 号点属性为一氧化碳,单位为 μmol/mol,6 号点为氧气,单位为%V/V) 根据寄存器地址映射表查到,3 号探测器对应寄存器地址为 0BA4H
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);
}
});
读取 SFJK-200 外控电源状态( 外控电源状态请参考外控电压状态定义表 ) 1 回路外控电源 对应寄存器地址为 0f82H )
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);
}
});
读取 SFJK-200 控制器状态(SFJK-200 控制器状态参考控制器状态定义表 ) 根据寄存器地 址映射表查到,对应寄存器地址为 0F8AH
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);
}
});
** 示例中的CRC校验错误 **
模拟读写
使用工具modbus slave工具
保存至influxdb结果
下载modbus slave测试内容
Mbslave1.mbs Mbslave2.mbs Mbslave3.mbs Mbslave4.mbs Mbslave5.mbs Mbslave6.mbs Mbslave7.mbs最后是使用的java开发的示例demo
引用站外地址
demo下载
github
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ALLBS!
评论