| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- package com.water.iot.adapter.impl;
-
- import com.water.iot.adapter.AdapterInfo;
- import com.water.iot.adapter.AdapterStatus;
- import com.water.iot.adapter.DeviceAdapter;
- import com.water.iot.model.DeviceCommand;
- import com.water.iot.model.DeviceInfo;
- import java.io.IOException;
- import java.net.InetAddress;
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * Modbus TCP 协议适配器
- */
- public class ModbusTcpAdapter implements DeviceAdapter {
-
- private String host;
- private int port;
- private AdapterStatus status = AdapterStatus.DISCONNECTED;
- private long connectionTime;
- private Map<String, DeviceInfo> connectedDevices = new HashMap<>();
-
- public ModbusTcpAdapter(String host, int port) {
- this.host = host;
- this.port = port;
- }
-
- @Override
- public String getProtocol() {
- return "modbus_tcp";
- }
-
- @Override
- public void onMessage(byte[] payload) {
- System.out.println("Modbus TCP 接收到设备数据: " + bytesToHex(payload));
-
- try {
- // 解析Modbus TCP帧
- if (payload.length >= 7) {
- int transactionId = ((payload[0] & 0xFF) << 8) | (payload[1] & 0xFF);
- int protocolId = ((payload[2] & 0xFF) << 8) | (payload[3] & 0xFF);
- int length = ((payload[4] & 0xFF) << 8) | (payload[5] & 0xFF);
- int unitId = payload[6];
-
- System.out.printf("Modbus TCP: Transaction=%d, Protocol=%d, Length=%d, UnitId=%d%n",
- transactionId, protocolId, length, unitId);
-
- // 处理Modbus请求
- if (protocolId == 0 && length > 0) {
- processModbusRequest(payload, unitId);
- }
- }
- } catch (Exception e) {
- System.err.println("处理Modbus TCP消息时出错: " + e.getMessage());
- }
- }
-
- private void processModbusRequest(byte[] payload, int unitId) {
- if (payload.length >= 8) {
- int functionCode = payload[7] & 0xFF;
-
- switch (functionCode) {
- case 0x01: // 读线圈状态
- handleReadCoils(payload, unitId);
- break;
- case 0x02: // 读离散输入
- handleReadDiscreteInputs(payload, unitId);
- break;
- case 0x03: // 保持寄存器
- handleReadHoldingRegisters(payload, unitId);
- break;
- case 0x04: // 输入寄存器
- handleReadInputRegisters(payload, unitId);
- break;
- case 0x05: // 写单个线圈
- handleWriteSingleCoil(payload, unitId);
- break;
- case 0x06: // 写单个寄存器
- handleWriteSingleRegister(payload, unitId);
- break;
- case 0x0F: // 写多个线圈
- handleWriteMultipleCoils(payload, unitId);
- break;
- case 0x10: // 写多个寄存器
- handleWriteMultipleRegisters(payload, unitId);
- break;
- default:
- System.out.println("未处理的Modbus功能码: 0x" + Integer.toHexString(functionCode));
- }
- }
- }
-
- private void handleReadHoldingRegisters(byte[] payload, int unitId) {
- if (payload.length >= 12) {
- int startAddress = ((payload[8] & 0xFF) << 8) | (payload[9] & 0xFF);
- int quantity = ((payload[10] & 0xFF) << 8) | (payload[11] & 0xFF);
-
- System.out.printf("读取保持寄存器: 起始地址=%d, 数量=%d%n", startAddress, quantity);
-
- // 这里应该实际读取设备数据,这里返回模拟数据
- byte[] response = generateModbusResponse(0x03, unitId, startAddress, quantity);
- // 在实际实现中,这里应该发送响应给设备
- }
- }
-
- private void handleReadInputRegisters(byte[] payload, int unitId) {
- if (payload.length >= 12) {
- int startAddress = ((payload[8] & 0xFF) << 8) | (payload[9] & 0xFF);
- int quantity = ((payload[10] & 0xFF) << 8) | (payload[11] & 0xFF);
-
- System.out.printf("读取输入寄存器: 起始地址=%d, 数量=%d%n", startAddress, quantity);
- }
- }
-
- private void handleWriteSingleRegister(byte[] payload, int unitId) {
- if (payload.length >= 12) {
- int address = ((payload[8] & 0xFF) << 8) | (payload[9] & 0xFF);
- int value = ((payload[10] & 0xFF) << 8) | (payload[11] & 0xFF);
-
- System.out.printf("写入单个寄存器: 地址=%d, 值=%d%n", address, value);
- }
- }
-
- private byte[] generateModbusResponse(int functionCode, int unitId, int startAddress, int quantity) {
- // 模拟生成Modbus响应
- byte[] response = new byte[9 + quantity * 2];
- response[0] = (byte) (functionCode + 0x80); // 响应
- response[1] = (byte) unitId;
- response[2] = (byte) (quantity * 2 >> 8);
- response[3] = (byte) (quantity * 2);
-
- // 填充模拟数据
- for (int i = 0; i < quantity; i++) {
- int index = 5 + i * 2;
- response[index] = (byte) (i * 100 >> 8);
- response[index + 1] = (byte) (i * 100 & 0xFF);
- }
-
- return response;
- }
-
- @Override
- public void sendCommand(String deviceSn, DeviceCommand cmd) {
- System.out.println("发送Modbus命令到设备 " + deviceSn + ": " + cmd.getCommandType());
-
- // 根据命令类型生成对应的Modbus请求
- switch (cmd.getCommandType()) {
- case "read":
- generateReadCommand(cmd);
- break;
- case "write":
- generateWriteCommand(cmd);
- break;
- case "control":
- generateControlCommand(cmd);
- break;
- default:
- System.err.println("不支持的命令类型: " + cmd.getCommandType());
- }
- }
-
- private void generateReadCommand(DeviceCommand cmd) {
- // 生成读寄存器命令
- int address = Integer.parseInt(cmd.getParameterKey());
- int quantity = Integer.parseInt(cmd.getParameterValue().toString());
-
- System.out.printf("生成读命令: 地址=%d, 数量=%d%n", address, quantity);
- }
-
- private void generateWriteCommand(DeviceCommand cmd) {
- // 生成写寄存器命令
- int address = Integer.parseInt(cmd.getParameterKey());
- int value = Integer.parseInt(cmd.getParameterValue().toString());
-
- System.out.printf("生成写命令: 地址=%d, 值=%d%n", address, value);
- }
-
- private void generateControlCommand(DeviceCommand cmd) {
- // 生成控制命令(如开关阀门)
- String action = cmd.getParameterKey();
- int address = Integer.parseInt(cmd.getParameterValue().toString());
-
- System.out.printf("生成控制命令: 动作=%s, 地址=%d%n", action, address);
- }
-
- @Override
- public DeviceInfo parseDeviceInfo(byte[] payload) {
- System.out.println("解析Modbus设备信息: " + bytesToHex(payload));
-
- // 根据Modbus协议解析设备信息
- DeviceInfo deviceInfo = new DeviceInfo("MODBUS_001", "Modbus设备", "flow_meter");
- deviceInfo.setManufacturer("Simatic");
- deviceInfo.setProtocolVersion("Modbus TCP");
-
- // 解析设备属性
- Map<String, Object> properties = new HashMap<>();
- properties.put("connectionType", "TCP");
- properties.put("baudRate", 115200);
- properties.put("parity", "even");
- deviceInfo.setProperties(properties);
-
- return deviceInfo;
- }
-
- @Override
- public AdapterStatus getStatus(String deviceSn) {
- return status;
- }
-
- @Override
- public boolean connect() {
- try {
- // 尝试连接到Modbus TCP服务器
- InetAddress address = InetAddress.getByName(host);
- if (address.isReachable(5000)) {
- status = AdapterStatus.CONNECTED;
- connectionTime = System.currentTimeMillis();
- System.out.println("Modbus TCP 适配器连接成功: " + host + ":" + port);
- return true;
- } else {
- status = AdapterStatus.ERROR;
- System.err.println("无法连接到Modbus TCP服务器: " + host + ":" + port);
- return false;
- }
- } catch (IOException e) {
- status = AdapterStatus.ERROR;
- System.err.println("Modbus TCP连接失败: " + e.getMessage());
- return false;
- }
- }
-
- @Override
- public void disconnect() {
- status = AdapterStatus.DISCONNECTED;
- connectedDevices.clear();
- System.out.println("Modbus TCP 适配器已断开连接");
- }
-
- @Override
- public AdapterInfo getAdapterInfo() {
- return new AdapterInfo("ModbusTCP适配器", "modbus_tcp", "1.0", "支持Modbus TCP协议的设备适配");
- }
-
- private String bytesToHex(byte[] bytes) {
- StringBuilder sb = new StringBuilder();
- for (byte b : bytes) {
- sb.append(String.format("%02X ", b));
- }
- return sb.toString();
- }
- }
|