107 lines
3.8 KiB
TypeScript
107 lines
3.8 KiB
TypeScript
/**
|
|
* 继电器命令行调试工具 —— 参数化触发按键/配对/原始命令,方便接线调试。
|
|
*
|
|
* 用法(端口/波特率走 .env 的 SERIAL_PORT/SERIAL_BAUD):
|
|
* npx ts-node scripts/relay.ts probe # 查版本(只读握手)
|
|
* npx ts-node scripts/relay.ts status # 读 64 路状态
|
|
* npx ts-node scripts/relay.ts pair remote # 进配对(按 config 默认)
|
|
* npx ts-node scripts/relay.ts pair meter --hold 2500 # 进配对,覆盖时长
|
|
* npx ts-node scripts/relay.ts press remote convex --hold 800 # 点按命名键
|
|
* npx ts-node scripts/relay.ts pulse 34,35 --hold 3000 # 同时脉冲指定通道
|
|
* npx ts-node scripts/relay.ts on 34 / off 34 # 单路通/断
|
|
* npx ts-node scripts/relay.ts raw 55C8210155 # 发原始 16 进制帧
|
|
*/
|
|
import * as dotenv from 'dotenv';
|
|
import * as path from 'path';
|
|
dotenv.config({ path: path.resolve(__dirname, '../.env') });
|
|
|
|
import { SerialController } from '../utils/common/serial_controller';
|
|
import { triggerRelayAction, pressButton } from '../utils/common/relay.helper';
|
|
|
|
function flag(name: string): string | undefined {
|
|
const i = process.argv.indexOf(`--${name}`);
|
|
return i >= 0 ? process.argv[i + 1] : undefined;
|
|
}
|
|
|
|
/** 取位置参数(剔除 --flag 及其紧随的值)。 */
|
|
function positionals(): string[] {
|
|
const argv = process.argv.slice(2);
|
|
const out: string[] = [];
|
|
for (let i = 0; i < argv.length; i++) {
|
|
if (argv[i].startsWith('--')) {
|
|
i++; // 跳过该 flag 的值
|
|
continue;
|
|
}
|
|
out.push(argv[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
async function main() {
|
|
const [cmd, a, b] = positionals();
|
|
const hold = flag('hold') ? parseInt(flag('hold') as string, 10) : undefined;
|
|
|
|
switch (cmd) {
|
|
case 'probe': {
|
|
const c = new SerialController();
|
|
await c.open();
|
|
console.log(await c.queryVersion());
|
|
await c.close();
|
|
break;
|
|
}
|
|
case 'status': {
|
|
const c = new SerialController();
|
|
await c.open();
|
|
console.log('status:', (await c.readStatus()).toString('hex').toUpperCase());
|
|
await c.close();
|
|
break;
|
|
}
|
|
case 'pair': {
|
|
if (!a) throw new Error('用法: pair <device> [--hold ms]');
|
|
await triggerRelayAction(a, 'pairing', hold ? { holdMs: hold } : {});
|
|
break;
|
|
}
|
|
case 'press': {
|
|
if (!a || !b) throw new Error('用法: press <device> <button> [--hold ms]');
|
|
await pressButton(a, b, hold ?? 500);
|
|
break;
|
|
}
|
|
case 'pulse': {
|
|
if (!a) throw new Error('用法: pulse <ch1,ch2,...> [--hold ms]');
|
|
const chs = a.split(',').map((s) => parseInt(s, 10));
|
|
const c = new SerialController();
|
|
await c.open();
|
|
await c.pulseChannels(chs, hold ?? 500);
|
|
console.log(`脉冲通道[${chs.join(',')}] ${hold ?? 500}ms 完成`);
|
|
await c.close();
|
|
break;
|
|
}
|
|
case 'on':
|
|
case 'off': {
|
|
if (!a) throw new Error(`用法: ${cmd} <ch>`);
|
|
const c = new SerialController();
|
|
await c.open();
|
|
const resp = cmd === 'on' ? await c.relayOn(parseInt(a, 10)) : await c.relayOff(parseInt(a, 10));
|
|
console.log(`${cmd} ${a}:`, resp.toString('hex').toUpperCase());
|
|
await c.close();
|
|
break;
|
|
}
|
|
case 'raw': {
|
|
if (!a) throw new Error('用法: raw <hex,如 55C8210155>');
|
|
const bytes = (a.match(/.{1,2}/g) || []).map((h) => parseInt(h, 16));
|
|
const c = new SerialController();
|
|
await c.open();
|
|
console.log('resp:', (await c.send(bytes)).toString('hex').toUpperCase());
|
|
await c.close();
|
|
break;
|
|
}
|
|
default:
|
|
console.log('命令: probe | status | pair <dev> | press <dev> <btn> | pulse <chs> | on <ch> | off <ch> | raw <hex> [--hold ms]');
|
|
}
|
|
}
|
|
|
|
main().catch((e) => {
|
|
console.error('错误:', e.message);
|
|
process.exit(1);
|
|
});
|