matterbridge-bthome
Version:
Matterbridge BTHome plugin
53 lines (52 loc) • 1.85 kB
JavaScript
import { BTHOME_SPEC } from './BTHomeSpec.js';
export function decodeBTHome(buf) {
const info = buf.readUInt8(0);
const version = (info >> 5) & 0b00000111;
const encrypted = Boolean(info & 0b00000001);
const trigger = Boolean(info & 0b00000100);
const readings = {};
const unknown = [];
let offset = 1;
const ids = [];
while (offset < buf.length) {
const id = buf.readUInt8(offset++);
ids.push(id);
const spec = BTHOME_SPEC[id];
if (!spec) {
unknown.push(`0x${id.toString(16)} → 0x${buf.slice(offset - 1).toString('hex')}`);
break;
}
let value;
if (spec.parser) {
value = spec.parser(buf, offset);
if (spec.bytes != null) {
offset += spec.bytes;
}
else {
const len = buf.readUInt8(offset);
offset += 1 + len;
}
}
else {
if (spec.bytes == null) {
throw new Error(`BTHome spec for ${spec.name} is missing 'bytes'`);
}
const bytes = spec.bytes;
const factor = spec.factor ?? 1;
const raw = spec.signed ? buf.readIntLE(offset, bytes) : buf.readUIntLE(offset, bytes);
value = parseFloat((raw * factor).toFixed(Math.log10(1 / factor)));
offset += bytes;
}
const count = ids.filter((existingId) => existingId === id).length;
let name = spec.name;
if (count > 1) {
name = spec.name + `:${count}`;
if (spec.name in readings) {
readings[spec.name + ':1'] = readings[spec.name];
delete readings[spec.name];
}
}
readings[name] = value;
}
return { version, encrypted, trigger, readings, unknown };
}