package com.ruoyi.fuzhou.utils;
|
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.fuzhou.domain.ReceiveOilInfo;
|
import com.ruoyi.fuzhou.domain.ReceiveSlmInfo;
|
import com.ruoyi.fuzhou.domain.ReceiveWeatherInfo;
|
import com.ruoyi.fuzhou.enums.DataTypeEnum;
|
import com.ruoyi.fuzhou.utils.oilmodbus.Crc16Utils;
|
import com.ruoyi.fuzhou.utils.oilmodbus.ModbusFloatParserLittleUtil;
|
import com.ruoyi.fuzhou.utils.oilmodbus.ModbusFloatParserUtil;
|
|
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 ModbusSlmServerUtils {
|
public static void main(String[] args) {
|
//
|
// //质量流量
|
//String value = getValue("0.0.0.0", 8140, (byte) 0x05, (byte) 0x04, 167, 0x0002, 1);
|
//// //利和油设备
|
//// String value = getValue("0.0.0.0", 8247, (byte) 1, (byte) 3, 13, 2, 12);
|
// System.out.println(value);
|
|
String dataStr="{\n" +
|
" \"LA\" : \n" +
|
" {\n" +
|
" \"x\" : \"122.145105\",\n" +
|
" \"y\" : \"29.947085\"\n" +
|
" },\n" +
|
" \"LB\" :\n" +
|
" {\n" +
|
" \"x\" : \"122.144408\",\n" +
|
" \"y\" : \"29.947062\"\n" +
|
" },\n" +
|
" \"POS\" : \n" +
|
" {\n" +
|
" \"x\" : \"0.000000\",\n" +
|
" \"y\" : \"0.000000\"\n" +
|
" },\n" +
|
" \"aiddata\" : \n" +
|
" {\n" +
|
" \"ROT\" : \"0\",\n" +
|
" \"SOG\" : \"0\",\n" +
|
" \"aalarm\" : \"Er\",\n" +
|
" \"adis\" : \"Er\",\n" +
|
" \"angle\" : \"Er\",\n" +
|
" \"anglealarm\" : \"Er\",\t\n" +
|
" \"aspeed\" : \"Er\",\n" +
|
" \"balarm\" : \"Er\",\n" +
|
" \"bdis\" : \"Er\",\n" +
|
" \"bspeed\" : \"Er\",\n" +
|
" \"direction\" : \"1\",\n" +
|
" \"flowdirection\" : \"Na\",\n" +
|
" \"flowspeed\" : \"Na\",\t\n" +
|
" \"humidity\" : \"98.00\",\n" +
|
" \"airpressure\":\"1009\",\n" +
|
" \"status\" : \"0\", \n" +
|
" \"temperature\" : \"23.10\",\n" +
|
" \"tidelevel\" : \"Na\",\n" +
|
" \"visibility\" : \"20000.00\",\n" +
|
" \"waveheight\" : \"Na\",\n" +
|
" \"windirection\" : \"888.00\",\n" +
|
" \"windpower\" : \"16.00\",\n" +
|
" \"windspeed\" : \"888.00\"\n" +
|
" },\n" +
|
"\"berthname\":\"泊位名称\",\n" +
|
"\"boatname\":\"船舶名称\",\n" +
|
" \"mmsi\" : \"\",\n" +
|
" \"timestamp\" : \"1621924763\"\n" +
|
"}";
|
|
|
|
|
System.out.println("1111");
|
|
}
|
/**
|
* @param ip ip
|
* @param port 端口
|
* @param list 查询项列表
|
*/
|
public static JSONObject getValue(String ip, int port, List<ReceiveSlmInfo> 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();
|
ReceiveSlmInfo info=list.get(0);
|
|
// 接收设备响应
|
byte[] response = new byte[1024];
|
int bytesRead = inputStream.read(response);
|
|
if (bytesRead == -1) {
|
System.out.println("❌ 未收到激光雷达设备响应");
|
serverSocket.close();
|
return jsonObject;
|
}
|
// 打印响应数据
|
byte[] responseData = new byte[bytesRead];
|
System.arraycopy(response, 0, responseData, 0, bytesRead);
|
String resultData = new String(responseData);
|
System.out.println("📥 收到激光雷达设备响应: " + resultData);
|
// 检查响应长度
|
if (resultData.length()< 30) {
|
System.out.println("❌ 无效的响应长度: " + resultData.length() + " 字节");
|
|
}
|
|
String dataStr=resultData;
|
|
|
JSONObject obj=JSONObject.parseObject(dataStr);
|
if(obj.getString("berthname")!=null){
|
jsonObject.put("berthname", obj.getString("berthname"));
|
System.out.println("⚠️ 激光雷达berthname字段值: " + obj.getString("berthname"));
|
}
|
if(obj.getString("boatname")!=null){
|
jsonObject.put("boatname", obj.getString("boatname"));
|
System.out.println("⚠️ 激光雷达boatname字段值: " + obj.getString("boatname"));
|
}
|
|
JSONObject aiddataObj=obj.getJSONObject("aiddata");
|
if(aiddataObj!=null){
|
if(aiddataObj.getString("status")!=null){
|
jsonObject.put("status", aiddataObj.getString("status"));
|
System.out.println("⚠️ 激光雷达status字段值: " + aiddataObj.getString("status"));
|
}
|
if(aiddataObj.getString("adis")!=null){
|
jsonObject.put("adis", aiddataObj.getString("adis"));
|
System.out.println("⚠️ 激光雷达adis字段值: " + aiddataObj.getString("adis"));
|
}
|
if(aiddataObj.getString("bdis")!=null){
|
jsonObject.put("bdis", aiddataObj.getString("bdis"));
|
System.out.println("⚠️ 激光雷达bdis字段值: " + aiddataObj.getString("bdis"));
|
}
|
if(aiddataObj.getString("aspeed")!=null){
|
jsonObject.put("aspeed", aiddataObj.getString("aspeed"));
|
System.out.println("⚠️ 激光雷达aspeed字段值: " + aiddataObj.getString("aspeed"));
|
}
|
if(aiddataObj.getString("bspeed")!=null){
|
jsonObject.put("bspeed", aiddataObj.getString("bspeed"));
|
System.out.println("⚠️ 激光雷达bspeed字段值: " + aiddataObj.getString("bspeed"));
|
}
|
if(aiddataObj.getString("aalarm")!=null){
|
jsonObject.put("aalarm", aiddataObj.getString("aalarm"));
|
System.out.println("⚠️ 激光雷达aalarm字段值: " + aiddataObj.getString("aalarm"));
|
}
|
if(aiddataObj.getString("balarm")!=null){
|
jsonObject.put("balarm", aiddataObj.getString("balarm"));
|
System.out.println("⚠️ 激光雷达balarm字段值: " + aiddataObj.getString("balarm"));
|
}
|
if(aiddataObj.getString("status")!=null){
|
jsonObject.put("status", aiddataObj.getString("status"));
|
System.out.println("⚠️ 激光雷达status字段值: " + aiddataObj.getString("status"));
|
}
|
|
}
|
|
serverSocket.close();
|
return jsonObject;
|
} catch (Exception e) {
|
System.out.println("⚠️ 激光雷达客户端异常断开: " + e.getMessage());
|
} finally {
|
clientSocket.close();
|
}
|
} catch (Exception e) {
|
if (serverSocket != null) {
|
try {
|
System.out.println("激光雷达设备不在线" + e.getMessage());
|
serverSocket.close();
|
} catch (Exception ex) {
|
System.out.println("❌ 激光雷达服务端关闭失败: " + ex.getMessage());
|
}
|
} else {
|
System.out.println("❌ 激光雷达服务端启动失败: " + e.getMessage());
|
}
|
}
|
return null;
|
}
|
|
|
public static JSONObject getValueTest(String ip, int port, List<ReceiveWeatherInfo> list) {
|
JSONObject jsonObject = new JSONObject();
|
ReceiveWeatherInfo info=list.get(0);
|
// 构造请求帧
|
ByteBuffer requestBuffer = ByteBuffer.allocate(8);
|
if (info.getDeviceAddress() != 0) {
|
requestBuffer.put(info.getDeviceAddress()); // 设备地址
|
}
|
if (info.getFunctionCode() != 0) {
|
requestBuffer.put(info.getFunctionCode()); // 功能码
|
}
|
|
requestBuffer.putShort((short) info.getRegisterAdress().intValue()); // 寄存器地址
|
|
|
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校验码
|
// 发送请求帧
|
|
System.out.println("📤 已发送激光雷达 MODBUS 请求: " + bytesToHex(requestBuffer.array()));
|
// 接收设备响应
|
byte[] response = new byte[1024];
|
|
|
// int bytesRead = inputStream.read(response);
|
|
|
// int bytesRead = Integer.parseInt(res, 16);
|
// if (bytesRead == -1) {
|
// System.out.println("❌ 未收到激光雷达设备响应");
|
//
|
// }
|
//// 打印响应数据
|
// byte[] responseData = new byte[bytesRead];
|
// System.arraycopy(response, 0, responseData, 0, bytesRead);
|
// String resultData = bytesToHex(responseData);
|
String resultData="01030A014A00B60112033103F68534";
|
System.out.println("📥 收到激光雷达设备响应: " + resultData);
|
// 检查响应长度
|
if (resultData.length()< 30) {
|
System.out.println("❌ 无效的响应长度: " + resultData.length() + " 字节");
|
|
}
|
|
String data=resultData.substring(6,resultData.length()-1);
|
|
|
//风速
|
int fengsu=Integer.parseInt(data.substring(0,4),16)/100;
|
System.out.println("激光雷达设备 风速解析为: " + fengsu);
|
|
//风向
|
int fengxiang=Integer.parseInt(data.substring(4,8),16)/100;
|
System.out.println("激光雷达设备 风速解析为: " + fengsu);
|
//温度
|
int wendu=Integer.parseInt(data.substring(8,12),16)/100;
|
System.out.println("激光雷达设备 风速解析为: " + fengsu);
|
//湿度
|
int shidu=Integer.parseInt(data.substring(12,16),16)/100;
|
System.out.println("激光雷达设备 风速解析为: " + fengsu);
|
//大气压
|
int daqiya=Integer.parseInt(data.substring(16,20),16)/100;
|
System.out.println("激光雷达设备 风速解析为: " + fengsu);
|
//crc
|
|
|
return jsonObject;
|
|
}
|
|
/**
|
* @param ip ip
|
* @param port 端口
|
* @param list 查询项列表
|
*/
|
public static JSONObject getLijiuValue(String ip, int port, List<ReceiveOilInfo> 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 (ReceiveOilInfo 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];
|
try {
|
Thread.sleep(5000);
|
} catch (Exception ex) {
|
ex.printStackTrace();
|
}
|
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.OIL.getCode().equals(info.getDataType())) {
|
byte[] bytes = ModbusFloatParserUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserUtil.parseAsFloat(bytes, ByteOrder.BIG_ENDIAN);
|
jsonObject.put(info.getParamCode(), String.valueOf(String.format("%.3f",floatValue)));
|
} else if (DataTypeEnum.LIJIUOIL.getCode().equals(info.getDataType())) {
|
byte[] bytes = ModbusFloatParserLittleUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
byte[] reorderedBytes = ModbusFloatParserLittleUtil.reorderBytesForFloat(bytes);
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserLittleUtil.parseAsFloat(reorderedBytes, ByteOrder.BIG_ENDIAN);
|
jsonObject.put(info.getParamCode(), String.valueOf(String.format("%.3f",floatValue)));
|
} else if (DataTypeEnum.LIJIUJUN.getCode().equals(info.getDataType())) {
|
//todo 未做处理
|
byte[] bytes = ModbusFloatParserLittleUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
byte[] reorderedBytes = ModbusFloatParserLittleUtil.reorderBytesForFloat(bytes);
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserLittleUtil.parseAsFloat(reorderedBytes, ByteOrder.BIG_ENDIAN);
|
jsonObject.put(info.getParamCode(), String.valueOf(String.format("%.3f",floatValue)));
|
} else if (DataTypeEnum.NIGDETUIYOU.getCode().equals(info.getDataType())) {
|
//todo 未做处理
|
byte[] bytes = ModbusFloatParserLittleUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
byte[] reorderedBytes = ModbusFloatParserLittleUtil.reorderBytesForFloat(bytes);
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserLittleUtil.parseAsFloat(reorderedBytes, ByteOrder.BIG_ENDIAN);
|
jsonObject.put(info.getParamCode(), String.valueOf(String.format("%.3f",floatValue)));
|
serverSocket.close();
|
}
|
}
|
return jsonObject;
|
} catch (Exception e) {
|
System.out.println("厦门利旧客户端异常断开: " + e.getMessage());
|
} finally {
|
clientSocket.close();
|
}
|
} catch (Exception e) {
|
if (serverSocket != null) {
|
try {
|
System.out.println("厦门利旧油设备不在线" + e.getMessage());
|
serverSocket.close();
|
} catch (Exception ex) {
|
System.out.println("厦门利旧油服务端关闭失败: " + ex.getMessage());
|
}
|
} else {
|
System.out.println("厦门利旧油服务端启动失败: " + e.getMessage());
|
}
|
}
|
return null;
|
}
|
|
/**
|
* @param ip ip
|
* @param port 端口
|
* @param address 地址码
|
* @param functionCode 功能码
|
* @param registerAddress 寄存器地址
|
* @param registerCount 寄存器数量
|
* @param dataType 结果数据类型
|
*/
|
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];
|
try {
|
Thread.sleep(3000);
|
} catch (Exception ex) {
|
ex.printStackTrace();
|
}
|
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.OIL.getCode().equals(dataType)) {
|
byte[] bytes = ModbusFloatParserUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserUtil.parseAsFloat(bytes, ByteOrder.BIG_ENDIAN);
|
return String.valueOf(floatValue);
|
} else if (DataTypeEnum.LIJIUOIL.getCode().equals(dataType)) {
|
byte[] bytes = ModbusFloatParserLittleUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
byte[] reorderedBytes = ModbusFloatParserLittleUtil.reorderBytesForFloat(bytes);
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserLittleUtil.parseAsFloat(reorderedBytes, ByteOrder.BIG_ENDIAN);
|
return String.valueOf(floatValue);
|
} else if (DataTypeEnum.LIJIUJUN.getCode().equals(dataType)) {
|
byte[] bytes = ModbusFloatParserUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserUtil.parseAsFloat(bytes, ByteOrder.BIG_ENDIAN);
|
return String.valueOf(floatValue);
|
} else if (DataTypeEnum.NIGDETUIYOU.getCode().equals(dataType)) {
|
//todo 未做处理
|
byte[] bytes = ModbusFloatParserLittleUtil.hexStringToByteArray(resultData.substring(6, 6 + byteCount * 2));
|
byte[] reorderedBytes = ModbusFloatParserLittleUtil.reorderBytesForFloat(bytes);
|
// 解析为浮点数(大端字节顺序)
|
float floatValue = ModbusFloatParserLittleUtil.parseAsFloat(reorderedBytes, ByteOrder.BIG_ENDIAN);
|
return String.valueOf(floatValue);
|
}
|
} catch (IOException e) {
|
System.out.println("⚠️ 客户端异常断开: " + e.getMessage());
|
} finally {
|
clientSocket.close();
|
}
|
} catch (IOException e) {
|
if (serverSocket != null) {
|
try {
|
System.out.println("设备不在线" + e.getMessage());
|
serverSocket.close();
|
} catch (IOException ex) {
|
System.out.println("❌ 服务端关闭失败: " + ex.getMessage());
|
}
|
} else {
|
System.out.println("❌ 服务端启动失败: " + e.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;
|
}
|
}
|