import { describe, it, beforeAll, afterAll, expect } from 'vitest'; import { DeviceDriver } from '../../drivers/types'; import { createDriver } from '../../drivers/factory'; import { TestReporter } from '../../utils/test-reporter'; import { sleep, addDeviceWithSerialPairing, findDeviceNameOnHomepage, saveAddedDevice, onesAdd, curtain3PostConnect, curtainPostConnect, } from '../../utils/common'; import { getDeviceName, getModelName } from '../../config/device.config'; import * as dotenv from 'dotenv'; import * as path from 'path'; dotenv.config({ path: path.resolve(__dirname, '../../.env') }); const deviceName = getDeviceName('curtain', 'CURTAIN_DEVICE'); const model = getModelName('curtain', 'CURTAIN_DEVICE'); // 型号名(锚点用) // curtain 与 curtain3 校准流程不同:按型号区分 relay 设备 + 连接后流程 const isCurtain3 = /curtain\s*3|curtain3/i.test(model); const RELAY_DEVICE = isCurtain3 ? 'curtain3' : 'curtain'; const ADD_ANCHOR = onesAdd('curtain', model); // 首页实际设备名匹配(真机名如 "Curtain 89" / "Curtain3 2B" 带 2 位十六进制后缀); // 要求十六进制后缀,避免误匹配校准页提示文字(如 "...SwitchBot Curtain to the desired...")。可用 env 覆盖 const CURTAIN_PATTERN = process.env.CURTAIN_PATTERN || 'Curtain\\w*\\s+[0-9A-Fa-f]{2}\\b'; // 是否做行程校验(需设备装在真实导轨上);默认跳过(Install and calibrate later),CURTAIN_CALIBRATE=1 开启 const CALIBRATE = process.env.CURTAIN_CALIBRATE === '1'; describe('Curtain Connect - 添加窗帘设备(串口配对 + 行程校验)', () => { let driver: DeviceDriver; let reporter: TestReporter; beforeAll(async () => { driver = createDriver(); await driver.createSession(); reporter = new TestReporter('Curtain_Connect', driver.platform.toUpperCase()); }); afterAll(async () => { reporter.generate(); await driver.destroySession(); }); it(`${ADD_ANCHOR} 通过BLE添加窗帘设备`, { timeout: 360000 }, async () => { const start = Date.now(); try { const existing = await findDeviceNameOnHomepage(driver, CURTAIN_PATTERN); if (existing) { console.log(`${existing}已在首页,跳过重新添加`); saveAddedDevice('curtain', existing); reporter.record(`${ADD_ANCHOR} 添加窗帘设备`, 'SKIP', Date.now() - start, `${existing}已存在, 无需重新添加`); return; } const result = await addDeviceWithSerialPairing(driver, { categoryName: 'Curtain', // curtain / curtain3 同一添加入口 deviceKeyword: deviceName, relayDevice: RELAY_DEVICE, // 按开关键 2s(curtain ch39 / curtain3 ch37) registryCategory: 'curtain', namePattern: CURTAIN_PATTERN, // 连接后专属流程:选模式 + (curtain3 的行程校验 / curtain 稍后校准) postConnectSteps: (d) => isCurtain3 ? curtain3PostConnect(d, { calibrate: CALIBRATE }) : curtainPostConnect(d, { calibrate: CALIBRATE }), }); expect(result).toBe(true); const elapsed = ((Date.now() - start) / 1000).toFixed(1); reporter.record(`${ADD_ANCHOR} 添加窗帘设备`, 'PASS', Date.now() - start, `${model}添加成功${CALIBRATE ? '(含行程校验)' : ''}, 耗时${elapsed}s`); } catch (e: any) { const ss = await driver.screenshot().catch(() => ''); reporter.record(`${ADD_ANCHOR} 添加窗帘设备`, 'FAIL', Date.now() - start, e.message, ss); throw e; } }); });