feat: support 17-byte ADC status from updated vendor protocol

Protocol update adds FFE4 Status format: 7×PD sensors (little-endian)
+ VBAT battery voltage (mV) + XOR checksum = 17 bytes.

- parseVendorStatus: handles 1-byte heartbeat, 17-byte ADC, 33-byte params
- handleValueChange: ADC type extracts PD array + battery % from VBAT
- Battery calculated as linear 3000mV(0%) to 4200mV(100%)
- PD data passed through status event for treatment pages
- Updated protocol doc with full byte table and old/new comparison
这个提交包含在:
Guoguo
2026-05-19 03:54:15 -07:00
父节点 0feb900a1d
当前提交 3fd7578163
修改 3 个文件,包含 85 行新增84 行删除
+24 -2
查看文件
@@ -85,11 +85,33 @@ function handleValueChange(res) {
if (protocol.PROTOCOL_MODE === 'vendor_33') {
var parsed = protocol.parseVendorStatus(res.value)
emit('vendor_raw', parsed)
if (parsed.is_heartbeat) {
if (parsed.type === 'heartbeat') {
emit('heartbeat', { value: parsed.heartbeat })
return
}
if (parsed.ios) {
if (parsed.type === 'adc') {
var vbatMv = parsed.vbat
var batteryPct = Math.min(100, Math.max(0, Math.round((vbatMv - 3000) / (4200 - 3000) * 100)))
emit('status', {
mode_state: protocol.MODE_STATE.ACTIVE,
region_mask: protocol.REGION.FULL_FACE,
wavelength: 0,
brightness: 0,
remaining_ms: 0,
error_code: 0,
battery: batteryPct,
temperature: 0,
bind_status: 1,
subscription: 1,
pd: parsed.pd,
vbat: vbatMv
})
return
}
if (parsed.type === 'params' && parsed.ios) {
var anyActive = false
for (var i = 0; i < parsed.ios.length; i++) {
if (parsed.ios[i].red || parsed.ios[i].infrared || parsed.ios[i].uv || parsed.ios[i].warm_yellow) {
+18 -2
查看文件
@@ -197,7 +197,22 @@ function buildVendorCommand33(options) {
function parseVendorStatus(buffer) {
var bytes = bufferToBytes(buffer)
if (bytes.length === 1) {
return { heartbeat: bytes[0], is_heartbeat: true, raw_hex: bytesToHex(bytes) }
return { type: 'heartbeat', heartbeat: bytes[0], is_heartbeat: true, raw_hex: bytesToHex(bytes) }
}
if (bytes.length === 17) {
var checksum = xorChecksum(bytes.slice(0, 16))
var pds = []
for (var p = 0; p < 7; p++) {
pds.push(bytes[p * 2] | (bytes[p * 2 + 1] << 8))
}
return {
type: 'adc',
is_heartbeat: false,
pd: pds,
vbat: bytes[14] | (bytes[15] << 8),
checksum_ok: checksum === bytes[16],
raw_hex: bytesToHex(bytes)
}
}
if (bytes.length === 33) {
var ios = []
@@ -210,6 +225,7 @@ function parseVendorStatus(buffer) {
})
}
return {
type: 'params',
is_heartbeat: false,
ios: ios,
hold_time: (bytes[30] << 8) | bytes[31],
@@ -217,7 +233,7 @@ function parseVendorStatus(buffer) {
raw_hex: bytesToHex(bytes)
}
}
return { is_heartbeat: false, raw_bytes: bytes, raw_hex: bytesToHex(bytes) }
return { type: 'unknown', is_heartbeat: false, raw_bytes: bytes, raw_hex: bytesToHex(bytes) }
}
// --- frame encoding/decoding ---