feat: modbus enableCRC
This commit is contained in:
parent
051046e891
commit
d67cda3462
10
config.json
10
config.json
@ -1,8 +1,10 @@
|
||||
{
|
||||
"hostPort": "COM10",
|
||||
"devicePort": "COM11",
|
||||
"baudRate": 19200,
|
||||
"hostPort": "/dev/cu.usbserial-350",
|
||||
"devicePort": "/dev/cu.usbserial-230",
|
||||
"baudRate": 9600,
|
||||
"dataBits": 8,
|
||||
"stopBits": 1,
|
||||
"parity": "none"
|
||||
"parity": "none",
|
||||
"protocol": "custom",
|
||||
"enableCRC": false
|
||||
}
|
@ -5,10 +5,11 @@
|
||||
"bin": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "ts-node src/idnex.ts",
|
||||
"dev": "ts-node src/index.ts",
|
||||
"start": "node dist/index.js",
|
||||
"exe": "nexe dist/index.js --build --resource /Users/daoyouyun/.codes/serial-proxy/nodejs/node-v20.18.0-win-x64.zip --output serial-proxy.exe",
|
||||
"pkg": "pkg . --targets=node18-win-x64 --output=serial-proxy.exe"
|
||||
"pkg": "pkg . --targets=node18-win-x64 --output=serial-proxy.exe",
|
||||
"pkg-arm": "pkg dist/index.js --targets=node18-win-arm64 --output=serial-proxy.exe"
|
||||
},
|
||||
"dependencies": {
|
||||
"serialport": "^11.0.0"
|
||||
|
57
src/index.ts
57
src/index.ts
@ -10,6 +10,8 @@ interface Config {
|
||||
dataBits: 8 | 5 | 6 | 7 | undefined;
|
||||
stopBits: 1 | 2 | 1.5 | undefined;
|
||||
parity: 'none' | 'even' | 'odd' | 'mark' | 'space';
|
||||
protocol: 'custom' | 'modbus';
|
||||
enableCRC?: boolean;
|
||||
}
|
||||
|
||||
function loadConfig(): Config {
|
||||
@ -30,7 +32,9 @@ function loadConfig(): Config {
|
||||
logFile: raw.logFile || path.resolve(process.cwd(), 'serial.log'),
|
||||
dataBits: raw.dataBits || 8,
|
||||
stopBits: raw.stopBits || 1,
|
||||
parity: raw.parity || 'none'
|
||||
parity: raw.parity || 'none',
|
||||
protocol: raw.protocol === 'modbus' ? 'modbus' : 'custom',
|
||||
enableCRC: raw.enableCRC === true
|
||||
};
|
||||
|
||||
return config;
|
||||
@ -40,30 +44,52 @@ function loadConfig(): Config {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function formatTime(date: Date): string {
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} `
|
||||
+ `${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
||||
}
|
||||
|
||||
function formatLogLine(direction: string, data: Buffer): string {
|
||||
function formatLogLine(direction: string, data: Buffer, protocol: 'custom' | 'modbus'): string {
|
||||
const timestamp = formatTime(new Date());
|
||||
const hex = data.toString('hex').toUpperCase().replace(/(.{2})/g, '$1 ').trim();
|
||||
|
||||
if (protocol === 'modbus') {
|
||||
return `${timestamp} ${direction} HEX: ${hex}`;
|
||||
} else {
|
||||
const ascii = data.toString().replace(/[^\x20-\x7E]/g, '.');
|
||||
return `${timestamp} ${direction} HEX: ${hex} ASCII: ${ascii}`;
|
||||
}
|
||||
}
|
||||
|
||||
function logAndPrint(stream: fs.WriteStream, direction: string, data: Buffer) {
|
||||
const line = formatLogLine(direction, data);
|
||||
function logAndPrint(stream: fs.WriteStream, direction: string, data: Buffer, protocol: 'custom' | 'modbus') {
|
||||
const line = formatLogLine(direction, data, protocol);
|
||||
stream.write(line + '\n');
|
||||
console.log(line);
|
||||
}
|
||||
|
||||
function calculateCRC16(buffer: Buffer): Buffer {
|
||||
let crc = 0xFFFF;
|
||||
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
crc ^= buffer[i];
|
||||
for (let j = 0; j < 8; j++) {
|
||||
if ((crc & 0x0001) !== 0) {
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const lo = crc & 0xFF;
|
||||
const hi = (crc >> 8) & 0xFF;
|
||||
return Buffer.from([lo, hi]);
|
||||
}
|
||||
|
||||
function startProxy(config: Config) {
|
||||
|
||||
|
||||
const { hostPort, devicePort, baudRate, dataBits, stopBits, parity, logFile } = config;
|
||||
const { hostPort, devicePort, baudRate, dataBits, stopBits, parity, logFile, protocol, enableCRC } = config;
|
||||
|
||||
const logStream = fs.createWriteStream(logFile, { flags: 'a' });
|
||||
|
||||
@ -71,12 +97,19 @@ function startProxy(config: Config) {
|
||||
const device = new SerialPort({ path: devicePort, baudRate, dataBits, stopBits, parity });
|
||||
|
||||
host.on('data', data => {
|
||||
logAndPrint(logStream, '[主机 → 设备]', data);
|
||||
device.write(data);
|
||||
let outData = data;
|
||||
|
||||
if (protocol === 'modbus' && enableCRC) {
|
||||
const crc = calculateCRC16(data);
|
||||
outData = Buffer.concat([data, crc]);
|
||||
}
|
||||
|
||||
logAndPrint(logStream, '[主机 → 设备]', outData, protocol);
|
||||
device.write(outData);
|
||||
});
|
||||
|
||||
device.on('data', data => {
|
||||
logAndPrint(logStream, '[设备 → 主机]', data);
|
||||
logAndPrint(logStream, '[设备 → 主机]', data, protocol);
|
||||
host.write(data);
|
||||
});
|
||||
|
||||
@ -87,6 +120,8 @@ function startProxy(config: Config) {
|
||||
主机端:${hostPort}
|
||||
设备端:${devicePort}
|
||||
波特率:${baudRate}
|
||||
协议类型:${protocol}
|
||||
CRC 校验:${enableCRC ? '启用' : '关闭'}
|
||||
日志文件:${logFile}`);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user