| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- 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<ModbusRTUTestResult> {
- 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<number[] | null> {
- 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;
- }
- }
|