97 lines
2.4 KiB
JavaScript
97 lines
2.4 KiB
JavaScript
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
|
||
}
|
||
}
|