83 lines
2.4 KiB
JavaScript
83 lines
2.4 KiB
JavaScript
import { writeA7Payload } from '../core/packet'
|
||
import { waitForProtocolState } from '../core/stateWait'
|
||
|
||
const WIFI_FINAL_STATE_CODES = Object.freeze([1, 2, 3])
|
||
|
||
/**
|
||
* 校验 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(';'))
|
||
}
|
||
}
|
||
|
||
function requireAuthorized(ble) {
|
||
const state = ble.getState()
|
||
|
||
if (!state.auth || state.auth.keyMatched !== true) {
|
||
throw new Error('请先完成密钥鉴权,再发送 WiFi 配置')
|
||
}
|
||
}
|
||
|
||
/**
|
||
* WiFi 配网模块:负责打包发送 ssid|password,并等待 STATE 回执。
|
||
*/
|
||
export function createWifiModule(ble) {
|
||
async function configureWifi(ssid, password, options = {}) {
|
||
const profile = ble.getProfile()
|
||
const targetSsid = String(ssid || '').trim()
|
||
const targetPass = String(password || '').trim()
|
||
|
||
validateWifi(profile, targetSsid, targetPass)
|
||
requireAuthorized(ble)
|
||
|
||
const { wifi } = ble.getState().characteristics
|
||
if (!wifi || !wifi.uuid) {
|
||
throw new Error('未发现 UUID_WIFI 特征值')
|
||
}
|
||
|
||
const payload = `${targetSsid}|${targetPass}`
|
||
|
||
// 协议要求 WiFi 参数按 0xA7 分包发送到 UUID_WIFI(F401)。
|
||
await writeA7Payload(ble, wifi.uuid, payload, profile.packet, {
|
||
packetInterval: Number(options.packetInterval) || 0
|
||
})
|
||
|
||
const stateEvent = await waitForProtocolState(ble, {
|
||
// 仅等待最终态,避免在“连接中(4)”时过早返回导致页面提前结束流程。
|
||
allowedCodes: WIFI_FINAL_STATE_CODES,
|
||
rejectOnUnexpected: false,
|
||
timeout: options.timeout || 12000,
|
||
timeoutMessage: '等待 WiFi 状态超时'
|
||
})
|
||
|
||
const stateCode = Number(stateEvent.stateCode)
|
||
|
||
return {
|
||
success: stateCode === 3,
|
||
stateCode
|
||
}
|
||
}
|
||
|
||
return {
|
||
configureWifi,
|
||
requireAuthorized
|
||
}
|
||
}
|