/** * 继电器高层动作 helper —— 用语义名驱动物理按键,所有参数可配/可传,不写死。 * * 典型用法(添加流程前置): * await enterPairingMode('remote'); // 按 config 默认(凸+凹 3s) * await enterPairingMode('meter', { holdMs: 2500 }); // 临时覆盖时长 * await pressButton('remote', 'convex', 800); // 单键点按 * * 端口/波特率默认走 env(SERIAL_PORT/SERIAL_BAUD),也可经 opts 传入。 * 默认每次自建并关闭控制器(一次性动作);要在一个会话里连续操作,传 opts.controller 复用。 */ import { SerialController, SerialOptions } from './serial_controller'; import { resolveRelayAction, resolveRelayButton } from '../../config/relay.config'; export interface RelayActionOptions extends SerialOptions { /** 覆盖配置里的按住时长(毫秒)。 */ holdMs?: number; /** 复用已打开的控制器(不则自建并在结束时关闭)。 */ controller?: SerialController; } /** 用一个已开/自建的控制器执行 fn,自建的用完即关。 */ async function withController( opts: RelayActionOptions, fn: (c: SerialController) => Promise ): Promise { if (opts.controller) return fn(opts.controller); const c = new SerialController(opts); await c.open(); try { return await fn(c); } finally { await c.close(); } } /** * 触发设备的命名动作(默认 'pairing' 进配对):按 config 解析通道列表+时长, * 多通道则同帧"同时按下",按住后整体释放。返回实际触发的通道与时长。 */ export async function triggerRelayAction( device: string, action = 'pairing', opts: RelayActionOptions = {} ): Promise<{ channels: number[]; holdMs: number; desc?: string }> { const resolved = resolveRelayAction(device, action); const holdMs = opts.holdMs ?? resolved.holdMs; await withController(opts, (c) => c.pulseChannels(resolved.channels, holdMs)); console.log(`relay: ${device}.${action} → 通道[${resolved.channels.join(',')}] 按住 ${holdMs}ms${resolved.desc ? ' (' + resolved.desc + ')' : ''}`); return { ...resolved, holdMs }; } /** 让设备进入添加/配对模式(= triggerRelayAction(device,'pairing'))。 */ export function enterPairingMode(device: string, opts: RelayActionOptions = {}) { return triggerRelayAction(device, 'pairing', opts); } /** 点按设备某个命名按键 ms 毫秒(单键)。 */ export async function pressButton( device: string, button: string, ms = 500, opts: RelayActionOptions = {} ): Promise { const ch = resolveRelayButton(device, button); await withController(opts, (c) => c.pulse(ch, ms)); console.log(`relay: 点按 ${device}.${button} → 通道 ${ch} ${ms}ms`); return ch; } /** 同时按住一组命名按键 ms 毫秒后释放(任意组合)。 */ export async function pressButtonsTogether( device: string, buttons: string[], ms = 500, opts: RelayActionOptions = {} ): Promise { const channels = buttons.map((b) => resolveRelayButton(device, b)); await withController(opts, (c) => c.pulseChannels(channels, ms)); console.log(`relay: 同时按 ${device}.[${buttons.join('+')}] → 通道[${channels.join(',')}] ${ms}ms`); return channels; }