import { buildA7Packets } from '../core/packet' /** * 校验 WiFi 入参,规则来源于 profile.wifi。 */ function validateWifi(profile, ssid, password) { const errors = [] if (!ssid || ssid.length > profile.wifi.maxSsidLength) { errors.push(`SSID 长度需在 1-${profile.wifi.maxSsidLength} 之间`) } if (password.length < profile.wifi.minPasswordLength || password.length > profile.wifi.maxPasswordLength) { errors.push(`密码长度需在 ${profile.wifi.minPasswordLength}-${profile.wifi.maxPasswordLength} 之间`) } const invalidChars = profile.wifi.invalidChars || [] if (invalidChars.some((char) => ssid.includes(char))) { errors.push(`SSID 不能包含特殊字符: ${invalidChars.join(' ')}`) } if (errors.length) { throw new Error(errors.join(';')) } } /** * 监听协议状态通知,等待 WiFi 配网状态码返回。 */ function waitForWifiState(ble, timeout = 8000) { return new Promise((resolve, reject) => { let timer = null let off = null const clearAll = () => { if (timer) { clearTimeout(timer) } if (off) { off() } } timer = setTimeout(() => { clearAll() reject(new Error('等待 WiFi 状态超时')) }, timeout) off = ble.on('protocol:state', (payload) => { if (![1, 2, 3, 4].includes(payload.stateCode)) { return } clearAll() resolve(payload.stateCode) }) }) } /** * WiFi 配网模块:负责打包并发送 ssid|password,随后等待状态通知。 */ export function createWifiModule(ble) { async function configureWifi(ssid, password, options = {}) { const profile = ble.getProfile() const targetSsid = String(ssid || '') const targetPass = String(password || '') validateWifi(profile, targetSsid, targetPass) const { wifi } = ble.getState().characteristics if (!wifi || !wifi.uuid) { throw new Error('未发现 UUID_WIFI 特征值') } const payload = `${targetSsid}|${targetPass}` const packets = buildA7Packets(payload, profile.packet) // 按分包顺序逐包发送,保持设备端解析一致性。 for (const packet of packets) { await ble.writeCharacteristic(wifi.uuid, packet) } const stateCode = await waitForWifiState(ble, options.timeout || 8000) return { success: stateCode === 3, stateCode } } return { configureWifi } }