AI_UIAutomation/utils/common/relay.helper.ts

83 lines
3.2 KiB
TypeScript

/**
* 继电器高层动作 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<T>(
opts: RelayActionOptions,
fn: (c: SerialController) => Promise<T>
): Promise<T> {
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<number> {
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<number[]> {
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;
}