指令发送和返回添加功能码验证

This commit is contained in:
wangshilong 2024-11-26 14:25:09 +08:00
parent 8107bfdcda
commit d5b46b8e37
3 changed files with 80 additions and 2 deletions

View File

@ -2,8 +2,10 @@ package com.iot.modbus_rtcp.netty;
import com.iot.modbus_rtcp.config.EquipmentIPProperties; import com.iot.modbus_rtcp.config.EquipmentIPProperties;
import com.iot.modbus_rtcp.dto.ModbusCommandDto; import com.iot.modbus_rtcp.dto.ModbusCommandDto;
import com.iot.modbus_rtcp.utils.ModbusFunctionCodeEnums;
import com.iot.modbus_rtcp.utils.SpringUtil; import com.iot.modbus_rtcp.utils.SpringUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -40,9 +42,12 @@ public class ModbusSender {
private Map<String, List<ModbusCommandDto>> split(List<ModbusCommandDto> modbusCommandBoList) { private Map<String, List<ModbusCommandDto>> split(List<ModbusCommandDto> modbusCommandBoList) {
Map<String, List<ModbusCommandDto>> map = new HashMap<>(); Map<String, List<ModbusCommandDto>> map = new HashMap<>();
modbusCommandBoList.stream().forEach(modbusCommandBo -> { modbusCommandBoList.forEach(modbusCommandBo -> {
if (modbusCommandBo.getIdentifier() == null) { if (modbusCommandBo.getIdentifier() == null) {
return; throw new NullPointerException("Invalid gateway identifier");
}
if (!ModbusFunctionCodeEnums.isHandlerHexCode(StringUtils.substring(modbusCommandBo.getCommand(), 2, 2))) {
throw new RuntimeException("Not support command: " + modbusCommandBo.getCommand());
} }
List<ModbusCommandDto> list = map.getOrDefault(modbusCommandBo.getIdentifier(), new ArrayList<>()); List<ModbusCommandDto> list = map.getOrDefault(modbusCommandBo.getIdentifier(), new ArrayList<>());

View File

@ -2,11 +2,13 @@ package com.iot.modbus_rtcp.netty;
import com.iot.modbus_rtcp.dto.CommandTypeComparable; import com.iot.modbus_rtcp.dto.CommandTypeComparable;
import com.iot.modbus_rtcp.dto.ModbusCommandDto; import com.iot.modbus_rtcp.dto.ModbusCommandDto;
import com.iot.modbus_rtcp.utils.ModbusFunctionCodeEnums;
import com.iot.modbus_rtcp.utils.SpringUtil; import com.iot.modbus_rtcp.utils.SpringUtil;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
@ -53,6 +55,14 @@ public class SyncHandler extends ChannelInboundHandlerAdapter {
if (CommandTypeComparable.CommandType.CONTROL.equals(message.getType())) { if (CommandTypeComparable.CommandType.CONTROL.equals(message.getType())) {
return; return;
} }
if (!ModbusFunctionCodeEnums.isHandlerHexCode(StringUtils.substring(msg.toString(), 2, 2))) {
log.warn("Gateway {} fails to send command {} to return data: {}",
channel.getIdentifier(), message.getCommand(), msg);
// TODO 可在此处添加设备告警
return;
}
String json = message.getKey() + "/" + System.currentTimeMillis() + "/" + msg; String json = message.getKey() + "/" + System.currentTimeMillis() + "/" + msg;
log.info("推数据到MQ({}): {}", channel.getCollectQueue(), json); log.info("推数据到MQ({}): {}", channel.getCollectQueue(), json);
try { try {

View File

@ -0,0 +1,63 @@
package com.iot.modbus_rtcp.utils;
import com.iot.modbus_rtcp.dto.CommandTypeComparable;
import lombok.Getter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
/**
* @author <a href="mailto:shilong.wang@alpha-ess.com">王仕龙</a>
* 2024/11/26 13:43
*/
@Getter
public enum ModbusFunctionCodeEnums {
READ_COILS(1, CommandTypeComparable.CommandType.COLLECTION, "读取线圈状态", "", "读取一组逻辑线圈的当前状态(ON/OFF)"),
READ_DISCRETE_INPUTS(2, CommandTypeComparable.CommandType.COLLECTION, "读取输入状态", "", "读取一组开关输入的当前状态(ON/OFF)"),
READ_HOLDING_REGISTERS(3, CommandTypeComparable.CommandType.COLLECTION, "读取保持寄存器", "整数,字符型,状态字,浮点型", "在一个或多个保持寄存器中取得当前的二进制值"),
READ_INPUT_REGISTERS(4, CommandTypeComparable.CommandType.COLLECTION, "读取输入寄存器", "整数,状态字,浮点型", "在一个或多个输入寄存器中取得当前的二进制值"),
WRITE_COIL(5, CommandTypeComparable.CommandType.CONTROL, "强置单线圈", "", "强置一个逻辑线圈的通断状态"),
WRITE_REGISTER(6, CommandTypeComparable.CommandType.CONTROL, "预置单寄存器", "整数,字符型,状态字,浮点型", "把具体二进值装入一个保持寄存器"),
// READ_EXCEPTION_STATUS(7, CommandTypeComparable.CommandType.COLLECTION, "读取异常状态", "", "取得8个内部线圈的通断状态这8个线圈的地址由控制器决定用户逻辑可以将这些线圈定义以说明从机状态短报文适宜于迅速读取状态"),
// READ_EXCEPTION_STATUS(8, CommandTypeComparable.CommandType.COLLECTION, "回送诊断校验", "", "把诊断校验报文送从机,以对通信处理进行评鉴"),
WRITE_COILS(15, CommandTypeComparable.CommandType.CONTROL, "强置多线圈", "", "强置一串连续逻辑线圈的通断"),
WRITE_REGISTERS(16, CommandTypeComparable.CommandType.CONTROL, "预置多寄存器", "整数,字符型,状态字,浮点型", "把具体的二进制值装入一串连续的保持寄存器"),
// REPORT_SLAVE_ID(17, CommandTypeComparable.CommandType.COLLECTION, "报告从机标识", "字符型", "可使主机判断编址从机的类型及该从机运行指示灯的状态"),
;
private final int code;
private final String name;
private final String dataType;
private final String description;
private final CommandTypeComparable.CommandType commandType;
ModbusFunctionCodeEnums(int code, CommandTypeComparable.CommandType commandType, String name, String dataType, String description) {
this.code = code;
this.name = name;
this.dataType = dataType;
this.commandType = commandType;
this.description = description;
}
public String getHexCode() {
return Integer.toHexString(this.code);
}
public static Collection<ModbusFunctionCodeEnums> getAllControlCode() {
return Arrays.stream(values())
.filter(item -> Objects.equals(CommandTypeComparable.CommandType.CONTROL, item.getCommandType()))
.toList();
}
public static Collection<ModbusFunctionCodeEnums> getAllCollectionCode() {
return Arrays.stream(values())
.filter(item -> Objects.equals(CommandTypeComparable.CommandType.COLLECTION, item.getCommandType()))
.toList();
}
public static boolean isHandlerHexCode(String hexCode) {
return Arrays.stream(values()).anyMatch(item -> Objects.equals(item.getHexCode(), hexCode));
}
}