SEC_Warehouse/utils/ble/protocols/profiles.js

139 lines
3.0 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
})
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
}