import { Socket } from "node:net"; import { Buffer } from "node:buffer"; interface ModbusRTUTestOptions { ip: string; port: number; frameHexStrings?: string[]; } interface ModbusRTUTestResult { connected: boolean; message: string; response?: string; error?: string; } /** * Modbus RTU设备连接 * @param options 连接参数 {ip, port, frameHexStrings} * @returns 连接结果 */ export async function modbusRTUConnection( options: ModbusRTUTestOptions ): Promise { try { const { ip, port, frameHexStrings } = options; if (!ip || !port) { throw new Error("缺少IP或端口参数"); } const socket = new Socket(); const timeout = 2000; // 默认测试帧: 设备地址2, 功能码4(读取输入寄存器), 起始地址0, 读取2个寄存器 const defaultTestFrame = [0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xF8]; let testFrame; if (frameHexStrings) { // 16进制字符串数组格式处理 if (!Array.isArray(frameHexStrings)) { throw new Error("测试帧格式错误: 必须是16进制字符串数组"); } try { testFrame = Buffer.from(frameHexStrings.map(s => parseInt(s, 16))); } catch (e) { throw new Error("测试帧格式错误: 16进制字符串转换失败"); } } else { testFrame = Buffer.from(defaultTestFrame); } return await new Promise((resolve) => { socket.setTimeout(timeout); socket.on('connect', () => { socket.write(testFrame); }); socket.on('data', (data) => { const hexResponse = data.toString('hex'); socket.destroy(); resolve({ connected: true, message: "连接成功", response: hexResponse }); }); socket.on('timeout', () => { socket.destroy(); resolve({ connected: false, message: "连接超时" }); }); socket.on('error', (error) => { socket.destroy(); resolve({ connected: false, message: `连接失败: ${error.message}` }); }); socket.connect(Number(port), ip); }); } catch (error: unknown) { console.error("Modbus RTU测试连接错误:", error); const message = error instanceof Error ? error.message : "未知错误"; return { connected: false, message: `测试连接失败: ${message}` }; } } /** * 读取Modbus RTU寄存器数据 * @param address 设备地址 * @param register 寄存器地址 * @param length 读取长度 * @returns 寄存器数据数组 */ export async function readModbusRTU( address: string, register: number, length: number ): Promise { try { const [ip, portStr] = address.split(':'); const port = parseInt(portStr); if (!ip || !port) { throw new Error("设备地址格式错误,应为IP:PORT"); } // 构建读取输入寄存器命令帧 const frame = [ 0x02, // 设备地址 0x04, // 功能码(读取输入寄存器) (register >> 8) & 0xFF, // 寄存器地址高字节 register & 0xFF, // 寄存器地址低字节 (length >> 8) & 0xFF, // 长度高字节 length & 0xFF, // 长度低字节 0x71, 0xF8 // CRC校验(示例值) ]; const result = await modbusRTUConnection({ ip, port, frameHexStrings: frame.map(b => b.toString(16)) }); if (result.connected && result.response) { // 解析返回数据(示例) const bytes = Buffer.from(result.response, 'hex'); const data = []; for (let i = 3; i < bytes.length - 2; i++) { data.push(bytes[i]); } return data; } return null; } catch (error) { console.error("读取Modbus寄存器失败:", error); return null; } }