128 lines
3.1 KiB
JavaScript
128 lines
3.1 KiB
JavaScript
import {bytesToHex, bytesToMac} from '../utils/hex'
|
||
import {joinLowHigh, readUint16LE, toUint8Array} from '../utils/bytes'
|
||
|
||
/**
|
||
* 解析 UUID_STATE 的状态字节,转为有符号 8bit。
|
||
*/
|
||
export function parseStateCode(payload) {
|
||
const bytes = toUint8Array(payload)
|
||
if (!bytes.length) {
|
||
return null
|
||
}
|
||
|
||
return bytes[0] > 127 ? bytes[0] - 256 : bytes[0]
|
||
}
|
||
|
||
/**
|
||
* 解析 UUID_MSG 设备信息(ED713/ED719 通用字段优先)。
|
||
*/
|
||
export function parseDeviceInfo(payload) {
|
||
const bytes = toUint8Array(payload)
|
||
|
||
if (!bytes.length) {
|
||
return {
|
||
raw: bytes,
|
||
mac: '',
|
||
bindStatus: null,
|
||
productId: null,
|
||
deviceType: null,
|
||
wifiStatus: null,
|
||
cellularStatus: null
|
||
}
|
||
}
|
||
|
||
const macBytes = bytes.slice(0, 6)
|
||
const bindStatus = bytes.length > 6 ? bytes[6] : null
|
||
const productId = bytes.length > 10 ? joinLowHigh(bytes[10], bytes[9]) : null
|
||
const deviceType = bytes.length > 14 ? bytes[14] : null
|
||
const wifiStatus = bytes.length > 15 ? bytes[15] : null
|
||
const cellularStatus = bytes.length > 16 ? bytes[16] : null
|
||
|
||
return {
|
||
raw: bytes,
|
||
mac: bytesToMac(macBytes),
|
||
bindStatus,
|
||
productId,
|
||
deviceType,
|
||
wifiStatus,
|
||
cellularStatus,
|
||
baseBoardVersion: bytes.length > 11 ? bytes[11] : null,
|
||
coreBoardVersion: bytes.length > 12 ? bytes[12] : null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ED713 雷达数据解析。
|
||
* 协议帧长度不足时返回 valid:false,交由上层决定是否忽略。
|
||
*/
|
||
export function parseEd713Radar(payload) {
|
||
const bytes = toUint8Array(payload)
|
||
|
||
if (bytes.length < 60) {
|
||
return {
|
||
type: 'ED713',
|
||
valid: false,
|
||
reason: 'LENGTH_LT_60',
|
||
raw: bytes
|
||
}
|
||
}
|
||
|
||
return {
|
||
type: 'ED713',
|
||
valid: true,
|
||
raw: bytes,
|
||
peopleCount: bytes[24],
|
||
peopleLocalDecimeter: bytes[25],
|
||
peopleState: bytes[26],
|
||
heartRate: bytes[28],
|
||
respRate: bytes[29],
|
||
activityState: bytes[30],
|
||
moveIndex: bytes[35],
|
||
waveNum: bytes[37],
|
||
respWave: Array.from(bytes.slice(38, 58)),
|
||
narrowFlag: bytes[59]
|
||
}
|
||
}
|
||
|
||
/**
|
||
* ED719 雷达数据解析。
|
||
* 屏蔽区数量由 shieldNum 控制,每块固定 9 字节。
|
||
*/
|
||
export function parseEd719Radar(payload) {
|
||
const bytes = toUint8Array(payload)
|
||
|
||
if (bytes.length < 24) {
|
||
return {
|
||
type: 'ED719',
|
||
valid: false,
|
||
reason: 'LENGTH_LT_24',
|
||
raw: bytes
|
||
}
|
||
}
|
||
|
||
const shieldNum = bytes[27] || 0
|
||
const shieldStart = 28
|
||
const shieldBlockLength = Math.min(Math.max(shieldNum, 0), 4) * 9
|
||
|
||
return {
|
||
type: 'ED719',
|
||
valid: true,
|
||
raw: bytes,
|
||
eventState: bytes[4],
|
||
peopleState: bytes[5],
|
||
peopleNum: bytes[6],
|
||
installHeight: readUint16LE(bytes, 8),
|
||
installMode: bytes[10],
|
||
beeperOn: bytes[11],
|
||
leftDist: readUint16LE(bytes, 12),
|
||
rightDist: readUint16LE(bytes, 14),
|
||
frontDist: readUint16LE(bytes, 16),
|
||
backDist: readUint16LE(bytes, 18),
|
||
sensitive: bytes[20],
|
||
stateDelay: readUint16LE(bytes, 22),
|
||
shieldNum,
|
||
shieldZoneRaw: Array.from(bytes.slice(shieldStart, shieldStart + shieldBlockLength)),
|
||
wallOption: bytes[shieldStart + shieldBlockLength] ?? null
|
||
}
|
||
}
|