UNPKG

matterbridge-bthome

Version:
53 lines (52 loc) 1.85 kB
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 }; }