package com.ruoyi.fuzhou.utils;
|
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.fuzhou.domain.ReceiveModuleInfo;
|
import com.ruoyi.fuzhou.utils.electricitymodbus.HexStringToInt;
|
import com.ruoyi.fuzhou.utils.oilmodbus.Crc16Utils;
|
import com.ruoyi.fuzhou.utils.watermodbus.FloatInverseWaterParser;
|
|
import java.io.InputStream;
|
import java.io.OutputStream;
|
import java.net.ServerSocket;
|
import java.net.Socket;
|
import java.nio.ByteBuffer;
|
import java.nio.ByteOrder;
|
|
public class ModbusYdkfmjUtils {
|
public static JSONObject getValue(ReceiveModuleInfo rmi) throws Exception {
|
ServerSocket serverSocket = null;
|
try {
|
serverSocket = new ServerSocket(rmi.getPort());
|
System.out.println("🛡️ 服务端已启动,正在监听 " + rmi.getIp() + ":" + rmi.getPort() + "...");
|
serverSocket.setSoTimeout(1500);
|
Socket clientSocket = serverSocket.accept();
|
System.out.println("🔌 客户端已连接: " + clientSocket.getInetAddress().getHostAddress() + ":" + clientSocket.getPort());
|
|
try (clientSocket; InputStream inputStream = clientSocket.getInputStream(); OutputStream outputStream = clientSocket.getOutputStream()) {
|
ByteBuffer buffer = getRequestBuffer(rmi);
|
outputStream.write(buffer.array()); // 发送请求帧
|
System.out.println("📤 已发送 MODBUS 请求: " + Crc16Utils.bytesToHex(buffer.array()));
|
|
byte[] response = new byte[1024];
|
int bytesRead = inputStream.read(response); // 接收设备响应
|
if (bytesRead == -1) {
|
System.out.println("❌ 未收到设备响应");
|
throw new Exception("未收到设备响应");
|
}
|
|
byte[] data = new byte[bytesRead];
|
System.arraycopy(response, 0, data, 0, bytesRead);
|
|
return getValue(data, rmi);
|
} catch (Exception ex) {
|
System.out.println("⚠️ 客户端异常断开: " + ex.getMessage());
|
throw ex;
|
}
|
} catch (Exception e) {
|
System.out.println("❌ 服务端启动失败: " + e.getMessage());
|
throw e;
|
} finally {
|
if (serverSocket != null) {
|
try {
|
System.out.println("设备不在线");
|
serverSocket.close();
|
} catch (Exception ex) {
|
System.out.println("❌ 服务端关闭失败: " + ex.getMessage());
|
}
|
}
|
}
|
}
|
|
private static ByteBuffer getRequestBuffer(ReceiveModuleInfo rmi) {
|
ByteBuffer buffer = ByteBuffer.allocate(8); // 构造请求帧
|
if (rmi.getDeviceAddress() != 0) buffer.put(rmi.getDeviceAddress()); // 设备地址
|
if (rmi.getFunctionCode() != 0) buffer.put(rmi.getFunctionCode()); // 功能码
|
if (rmi.getRegisterAdress() != 0) buffer.putShort((short) rmi.getRegisterAdress().intValue()); // 寄存器地址
|
if (rmi.getRegisterCount() != 0) buffer.putShort((short) rmi.getRegisterCount().intValue()); // 寄存器数量
|
|
byte[] bytes = buffer.array(); // 计算CRC校验码
|
String hex = Crc16Utils.makeCRC(Crc16Utils.bytesToHex(bytes).substring(0, Crc16Utils.bytesToHex(bytes).length() - 4), true);
|
int decimal = Integer.parseInt(hex, 16);
|
buffer.putShort((short) decimal); // CRC校验码
|
|
return buffer;
|
}
|
|
private static JSONObject getValue(byte[] data, ReceiveModuleInfo rmi) throws Exception {
|
String result = Crc16Utils.bytesToHex(data);
|
System.out.println("📥 收到设备响应: " + result); // 打印响应数据
|
|
if (data.length < 6) {
|
System.out.println("❌ 无效的响应长度: " + data.length + " 字节");
|
throw new Exception("无效的响应长度: " + data.length + " 字节");
|
}
|
|
byte byteCount = data[2]; // 数据字节数
|
byte[] bytes = new byte[byteCount];
|
System.arraycopy(data, 3, bytes, 0, byteCount);
|
byte[] crcReceived = new byte[2];
|
System.arraycopy(data, data.length - 2, crcReceived, 0, 2);
|
|
byte functionCode = data[1]; // 功能码
|
if ((functionCode & 0x80) != 0) { // 检查是否为错误响应(功能码 + 0x80)
|
byte errorCode = data[2]; // 错误码
|
System.out.println("❌ 设备返回错误响应,错误码: " + errorCode);
|
throw new Exception("设备返回错误响应,错误码: " + errorCode);
|
}
|
|
JSONObject jsonObject = new JSONObject();
|
String src = result.substring(6, 6 + byteCount * 2);
|
if (src.length() == 8) {
|
byte[] arr = FloatInverseWaterParser.hexStringToByteArray(src);
|
byte[] reversedBytes = FloatInverseWaterParser.reverseByteArray(arr); // 解析为浮点数(大端字节顺序)
|
float floatValue = FloatInverseWaterParser.parseAsFloat(reversedBytes, ByteOrder.LITTLE_ENDIAN);
|
jsonObject.put(rmi.getParamCode(), floatValue);
|
System.out.println(rmi.getParam() + "的值为" + floatValue + rmi.getUnit());
|
} else {
|
long value = HexStringToInt.hexStringToInt(src);
|
jsonObject.put(rmi.getParamCode(), value);
|
System.out.println(rmi.getParam() + "的值为" + value + rmi.getUnit());
|
}
|
|
return jsonObject;
|
}
|
|
|
public static void main(String[] args) throws Exception {
|
// 模拟发送数据
|
ReceiveModuleInfo rmi = new ReceiveModuleInfo();
|
rmi.setIp("0.0.0.0");
|
rmi.setPort(8379);
|
rmi.setParam("获取开关状态");
|
rmi.setParamCode("getStatus");
|
rmi.setUnit("");
|
rmi.setDeviceAddress((byte) (1 & 0XFF));
|
rmi.setFunctionCode((byte) (3 & 0XFF));
|
rmi.setRegisterAdress(50);
|
rmi.setRegisterCount(1);
|
ByteBuffer requestBuffer = getRequestBuffer(rmi);
|
System.out.println("requestBuffer = " + Crc16Utils.bytesToHex(requestBuffer.array()));
|
|
// 模拟接收数据
|
ByteBuffer responseBuffer = ByteBuffer.allocate(7);
|
responseBuffer.put((byte) (0x1));
|
responseBuffer.put((byte) (0x3));
|
responseBuffer.put((byte) (0x2));
|
responseBuffer.put((byte) (0x0));
|
responseBuffer.put((byte) (0x1));
|
responseBuffer.put((byte) (0x79));
|
responseBuffer.put((byte) (0x84));
|
String resp = Crc16Utils.bytesToHex(responseBuffer.array());
|
System.out.println("responseBuffer = " + resp);
|
|
JSONObject jsonObject = getValue(responseBuffer.array(), rmi);
|
System.out.println("json = " + jsonObject.toJSONString());
|
}
|
|
|
public static boolean getYdkfmStatus(ReceiveModuleInfo rmi) throws Exception {
|
|
return true;
|
}
|
|
public static boolean ctrlYdkfm(ReceiveModuleInfo rmi, Boolean flag) throws Exception {
|
|
return true;
|
}
|
}
|