package com.ruoyi.fuzhou.utils.electricitymodbus; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.fuzhou.domain.ReceiveElectricityInfo; import com.ruoyi.fuzhou.enums.DataTypeEnum; import com.ruoyi.fuzhou.utils.oilmodbus.Crc16Utils; import com.ruoyi.fuzhou.utils.watermodbus.FloatInverseWaterParser; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.List; /** * 电表设备数据接入 */ public class ModbusElectricityUtils { public static void main(String[] args) { //利和油设备 String value = getValue("0.0.0.0", 8334, (byte) 35, (byte) 0x03, 20, 1, 3); // String value = getValue("0.0.0.0", 8247, (byte) 1, (byte) 0x03, 13, 2, 3); System.out.println(value); } /** * 查询多个设备项 * * @param ip ip * @param port 端口 * @param list 查询项列表 */ public static JSONObject getValue(String ip, int port, List list) { // 服务端配置 String SERVER_IP = ip; // 监听所有网络接口 int SERVER_PORT = port; // 端口号 ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(SERVER_PORT); System.out.println("🛡️ 服务端已启动,正在监听 " + SERVER_IP + ":" + SERVER_PORT + "..."); serverSocket.setSoTimeout(4000); Socket clientSocket = serverSocket.accept(); System.out.println("🔌 客户端已连接: " + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort()); try (InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) { JSONObject jsonObject = new JSONObject(); for (ReceiveElectricityInfo info : list ) { // 构造请求帧 ByteBuffer requestBuffer = ByteBuffer.allocate(8); if (info.getDeviceAddress() != 0) { requestBuffer.put(info.getDeviceAddress()); // 设备地址 } if (info.getFunctionCode() != 0) { requestBuffer.put(info.getFunctionCode()); // 功能码 } if (info.getRegisterAdress() != 0) { requestBuffer.putShort((short) info.getRegisterAdress().intValue()); // 寄存器地址 } if (info.getRegisterCount() != 0) { requestBuffer.putShort((short) info.getRegisterCount().intValue()); // 寄存器数量 } // 计算CRC校验码 byte[] requestData = requestBuffer.array(); String hex = Crc16Utils.makeCRC(Crc16Utils.bytesToHex(requestData).substring(0, Crc16Utils.bytesToHex(requestData).length() - 4), true); int decimal = Integer.parseInt(hex, 16); requestBuffer.putShort((short) decimal); // CRC校验码 // 发送请求帧 outputStream.write(requestBuffer.array()); System.out.println("📤 已发送 MODBUS 请求: " + bytesToHex(requestBuffer.array())); // 接收设备响应 byte[] response = new byte[1024]; int bytesRead = inputStream.read(response); if (bytesRead == -1) { System.out.println("❌ 未收到设备响应"); continue; } // 打印响应数据 byte[] responseData = new byte[bytesRead]; System.arraycopy(response, 0, responseData, 0, bytesRead); String resultData = bytesToHex(responseData); System.out.println("📥 收到设备响应: " + resultData); // 检查响应长度 if (responseData.length <= 5) { System.out.println("❌ 无效的响应长度: " + responseData.length + " 字节"); continue; } //功能码 byte responseFunctionCode = responseData[1]; //数据字节数 byte byteCount = responseData[2]; byte[] data = new byte[byteCount]; System.arraycopy(responseData, 3, data, 0, byteCount); byte[] crcReceived = new byte[2]; System.arraycopy(responseData, responseData.length - 2, crcReceived, 0, 2); // 检查是否为错误响应(功能码 + 0x80) if ((responseFunctionCode & 0x80) != 0) { byte errorCode = responseData[2]; // 错误码 System.out.println("❌ 设备返回错误响应,错误码: " + errorCode); continue; } if (DataTypeEnum.ELECTRICITY.getCode().equals(info.getDataType())) { if (byteCount == 2) { //解析整形 long value = HexStringToInt.hexStringToIntelc(resultData.substring(6, 6 + byteCount * 2)); jsonObject.put(info.getParamCode(), String.valueOf(value/10.0)); System.out.println(info.getParam() + "的值为" + (value/10.0) + info.getUnit()); } else if (byteCount == 4) { //解析浮点型 long floatValue = HexStringToInt.hexStringToIntelc(resultData.substring(6, 6 + byteCount * 2)); jsonObject.put(info.getParamCode(), String.valueOf(floatValue/100.0)); System.out.println(info.getParam() + "的值为" + floatValue/100.0 + info.getUnit()); } else { continue; } } } serverSocket.close(); return jsonObject; } catch (Exception e) { System.out.println("⚠️ 客户端异常断开: " + e.getMessage()); } finally { clientSocket.close(); } } catch (Exception e) { System.out.println("❌ 服务端启动失败: " + e.getMessage()); } finally { if (serverSocket != null) { try { System.out.println("设备不在线"); serverSocket.close(); } catch (Exception ex) { System.out.println("❌ 服务端关闭失败: " + ex.getMessage()); } } } return null; } /** * @param ip ip * @param port 端口 * @param address 地址码 * @param functionCode 功能码 * @param registerAddress 寄存器地址 * @param registerCount 寄存器数量 */ public static String getValue(String ip, int port, byte address, byte functionCode, int registerAddress, int registerCount, int dataType) { // 服务端配置 String SERVER_IP = ip; // 监听所有网络接口 int SERVER_PORT = port; // 端口号 ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(SERVER_PORT); System.out.println("🛡️ 服务端已启动,正在监听 " + SERVER_IP + ":" + SERVER_PORT + "..."); serverSocket.setSoTimeout(8000); Socket clientSocket = serverSocket.accept(); System.out.println("🔌 客户端已连接: " + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort()); try (InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) { // 构造请求帧 ByteBuffer requestBuffer = ByteBuffer.allocate(8); if (address != 0) { requestBuffer.put(address); // 设备地址 } if (functionCode != 0) { requestBuffer.put(functionCode); // 功能码 } if (registerAddress != 0) { requestBuffer.putShort((short) registerAddress); // 寄存器地址 } if (registerCount != 0) { requestBuffer.putShort((short) registerCount); // 寄存器数量 } // 计算CRC校验码 byte[] requestData = requestBuffer.array(); String hex = Crc16Utils.makeCRC(Crc16Utils.bytesToHex(requestData).substring(0, Crc16Utils.bytesToHex(requestData).length() - 4), true); int decimal = Integer.parseInt(hex, 16); requestBuffer.putShort((short) decimal); // CRC校验码 // 发送请求帧 outputStream.write(requestBuffer.array()); System.out.println("📤 已发送 MODBUS 请求: " + bytesToHex(requestBuffer.array())); // 接收设备响应 byte[] response = new byte[1024]; int bytesRead = inputStream.read(response); if (bytesRead == -1) { System.out.println("❌ 未收到设备响应"); return null; } // 打印响应数据 byte[] responseData = new byte[bytesRead]; System.arraycopy(response, 0, responseData, 0, bytesRead); String resultData = bytesToHex(responseData); System.out.println("📥 收到设备响应: " + resultData); // 检查响应长度 if (responseData.length <= 5) { System.out.println("❌ 无效的响应长度: " + responseData.length + " 字节"); return null; } //功能码 byte responseFunctionCode = responseData[1]; //数据字节数 byte byteCount = responseData[2]; byte[] data = new byte[byteCount]; System.arraycopy(responseData, 3, data, 0, byteCount); byte[] crcReceived = new byte[2]; System.arraycopy(responseData, responseData.length - 2, crcReceived, 0, 2); // 检查是否为错误响应(功能码 + 0x80) if ((responseFunctionCode & 0x80) != 0) { byte errorCode = responseData[2]; // 错误码 System.out.println("❌ 设备返回错误响应,错误码: " + errorCode); return null; } if (DataTypeEnum.ELECTRICITY.getCode().equals(dataType)) { if (byteCount == 2) { //解析整形 long value = HexStringToInt.hexStringToIntelc(resultData.substring(6, 6 + byteCount * 2)); System.out.println("的值为" + (value/10.0) ); } else if (byteCount == 4) { //解析浮点型 long floatValue = HexStringToInt.hexStringToIntelc(resultData.substring(6, 6 + byteCount * 2)); System.out.println( "的值为" + floatValue/100.0); } else { } } } catch (IOException e) { System.out.println("⚠️ 客户端异常断开: " + e.getMessage()); } finally { clientSocket.close(); } } catch (IOException e) { if (serverSocket != null) { System.out.println("设备不在线" + e.getMessage()); } else { System.out.println("❌ 服务端启动失败: " + e.getMessage()); } } finally { try { serverSocket.close(); } catch (IOException ex) { System.out.println("❌ 服务端关闭失败: " + ex.getMessage()); } } return null; } // 将字节数组转换为十六进制字符串 public static String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X", b)); } return sb.toString(); } // CRC16 计算 public static int crc16(byte[] data) { int crc = 0xFFFF; for (byte b : data) { crc ^= (b & 0xFF); for (int i = 0; i < 8; i++) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; } }