144 lines
3.2 KiB
JavaScript
144 lines
3.2 KiB
JavaScript
import { toFullUuid } from '../utils/uuid'
|
||
|
||
// ED713 / ED719 当前协议共用的服务与特征 UUID。
|
||
const COMMON_UUIDS = Object.freeze({
|
||
SERVICE: '00F4',
|
||
WIFI: 'F401',
|
||
KEY: 'F402',
|
||
CMD: 'F403',
|
||
MSG: 'F501',
|
||
STATE: 'F301',
|
||
RADAR: 'F302'
|
||
})
|
||
|
||
// UUID_STATE 常用状态码语义映射。
|
||
const COMMON_STATE_MAP = Object.freeze({
|
||
1: 'WIFI_PARAM_INVALID',
|
||
2: 'WIFI_CONNECT_FAILED',
|
||
3: 'WIFI_CONNECT_SUCCESS',
|
||
4: 'WIFI_CONNECTING',
|
||
5: 'BIND_SUCCESS',
|
||
6: 'BIND_FAILED',
|
||
7: 'KEY_MATCH_SUCCESS',
|
||
8: 'KEY_MATCH_FAILED'
|
||
})
|
||
|
||
export const DEVICE_PROFILE = Object.freeze({
|
||
UNKNOWN: 'UNKNOWN',
|
||
ED713: 'ED713',
|
||
ED719: 'ED719'
|
||
})
|
||
|
||
/**
|
||
* 生成设备 profile 模板:
|
||
* 包含 UUID、分包规则、鉴权策略、WiFi 校验、雷达命令能力。
|
||
*/
|
||
function buildCommonProfile(id) {
|
||
return {
|
||
id,
|
||
uuids: {
|
||
service: toFullUuid(COMMON_UUIDS.SERVICE),
|
||
wifi: toFullUuid(COMMON_UUIDS.WIFI),
|
||
key: toFullUuid(COMMON_UUIDS.KEY),
|
||
cmd: toFullUuid(COMMON_UUIDS.CMD),
|
||
msg: toFullUuid(COMMON_UUIDS.MSG),
|
||
state: toFullUuid(COMMON_UUIDS.STATE),
|
||
radar: toFullUuid(COMMON_UUIDS.RADAR)
|
||
},
|
||
stateMap: { ...COMMON_STATE_MAP },
|
||
packet: {
|
||
head: 0xA7,
|
||
chunkSize: 18,
|
||
maxChunk: 15
|
||
},
|
||
auth: {
|
||
keyLength: 16,
|
||
supportsUnboundState: false,
|
||
unboundStateCode: null
|
||
},
|
||
wifi: {
|
||
maxSsidLength: 32,
|
||
minPasswordLength: 8,
|
||
maxPasswordLength: 63,
|
||
invalidChars: ['+', '#', '&', '=', '|', '<', '>', '^', '"', '\\']
|
||
},
|
||
radar: {
|
||
notifySignature: null,
|
||
startCommand: 0xA1,
|
||
stopCommand: 0xA2,
|
||
parseMode: 'GENERIC'
|
||
},
|
||
cmd: {
|
||
supportsNarrowMode: false,
|
||
supportsFallParam67: false
|
||
}
|
||
}
|
||
}
|
||
|
||
const unknownProfile = buildCommonProfile(DEVICE_PROFILE.UNKNOWN)
|
||
|
||
const ed713Profile = {
|
||
...buildCommonProfile(DEVICE_PROFILE.ED713),
|
||
auth: {
|
||
keyLength: 16,
|
||
supportsUnboundState: true,
|
||
unboundStateCode: -1
|
||
},
|
||
radar: {
|
||
notifySignature: 0x7C,
|
||
startCommand: 0xA1,
|
||
stopCommand: 0xA2,
|
||
parseMode: 'ED713'
|
||
},
|
||
cmd: {
|
||
supportsNarrowMode: true,
|
||
supportsFallParam67: false
|
||
}
|
||
}
|
||
|
||
const ed719Profile = {
|
||
...buildCommonProfile(DEVICE_PROFILE.ED719),
|
||
radar: {
|
||
notifySignature: 0x67,
|
||
startCommand: 0xA1,
|
||
stopCommand: 0xA2,
|
||
parseMode: 'ED719'
|
||
},
|
||
cmd: {
|
||
supportsNarrowMode: false,
|
||
supportsFallParam67: true
|
||
}
|
||
}
|
||
|
||
export const BLE_PROFILE_MAP = Object.freeze({
|
||
[DEVICE_PROFILE.UNKNOWN]: unknownProfile,
|
||
[DEVICE_PROFILE.ED713]: ed713Profile,
|
||
[DEVICE_PROFILE.ED719]: ed719Profile
|
||
})
|
||
|
||
/**
|
||
* 根据设备型号获取对应 BLE Profile 配置。
|
||
* @param {string} profileId 设备型号ID,默认 UNKNOWN
|
||
* @returns {object} profile 配置对象
|
||
*/
|
||
export function getBleProfile(profileId = DEVICE_PROFILE.UNKNOWN) {
|
||
return BLE_PROFILE_MAP[profileId] || BLE_PROFILE_MAP[DEVICE_PROFILE.UNKNOWN]
|
||
}
|
||
|
||
/**
|
||
* 根据雷达帧签名字节粗略推断设备类型。
|
||
*/
|
||
export function guessProfileByRadarFrame(frame = new Uint8Array()) {
|
||
const signature = frame[3]
|
||
|
||
if (signature === 0x7C) {
|
||
return DEVICE_PROFILE.ED713
|
||
}
|
||
|
||
if (signature === 0x67) {
|
||
return DEVICE_PROFILE.ED719
|
||
}
|
||
|
||
return DEVICE_PROFILE.UNKNOWN
|
||
}
|