UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

126 lines (115 loc) 3.42 kB
import { ZWaveError, ZWaveErrorCodes } from "@zwave-js/core/safe"; import { NVMFile } from "../files/NVMFile"; import { FragmentType, ObjectType, PageStatus } from "./consts"; import type { NVM3Object } from "./object"; import type { NVM3Page } from "./page"; /** Counts the number of unset bits in the given word */ export function computeBergerCode(word: number, numBits: number = 32): number { let ret = word; // Mask the number of bits we're interested in if (numBits < 32) { ret &= (1 << numBits) - 1; } // And count the bits, see http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel ret = ret - ((ret >> 1) & 0x55555555); ret = (ret & 0x33333333) + ((ret >> 2) & 0x33333333); ret = (((ret + (ret >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24; return numBits - ret; } export function validateBergerCode( word: number, code: number, numBits: number = 32, ): void { if (computeBergerCode(word, numBits) !== code) { throw new ZWaveError( "Berger Code validation failed!", ZWaveErrorCodes.NVM_InvalidFormat, ); } } export function computeBergerCodeMulti( words: number[], numBits: number, ): number { let ret = 0; for (const word of words) { ret += computeBergerCode(word, Math.min(numBits, 32)); if (numBits < 32) break; numBits -= 32; } return ret; } export function validateBergerCodeMulti( words: number[], numBits: number, ): void { let actual = 0; let expected: number; for (const word of words) { actual += computeBergerCode(word, Math.min(numBits, 32)); if (numBits < 32) { const maskSize = 32 - numBits; const mask = (1 << maskSize) - 1; expected = (word >>> numBits) & mask; break; } numBits -= 32; } if (actual !== expected!) { throw new ZWaveError( "Berger Code validation failed!", ZWaveErrorCodes.NVM_InvalidFormat, ); } } export function mapToObject<T, TMap extends Map<string | number, T>>( map: TMap, ): Record<string, T> { const obj: Record<string | number, T> = {}; for (const [key, value] of map) { obj[key] = value; } return obj; } export function dumpPage(page: NVM3Page, json: boolean = false): void { console.log(` `); console.log(`read page (offset 0x${page.header.offset.toString(16)}):`); console.log(` version: ${page.header.version}`); console.log(` eraseCount: ${page.header.eraseCount}`); console.log(` status: ${PageStatus[page.header.status]}`); console.log(` encrypted: ${page.header.encrypted}`); console.log(` pageSize: ${page.header.pageSize}`); console.log(` writeSize: ${page.header.writeSize}`); console.log(` memoryMapped: ${page.header.memoryMapped}`); console.log(` deviceFamily: ${page.header.deviceFamily}`); console.log(""); console.log(` objects:`); for (const obj of page.objects) { dumpObject(obj, json); } } export function dumpObject(obj: NVM3Object, json: boolean = false): void { try { if (json) { const file = NVMFile.from(obj); console.log(`${JSON.stringify(file.toJSON(), null, 2)}`); console.log(); return; } } catch { // ignore } const prefix = json ? "" : " "; console.log(`${prefix}· key: 0x${obj.key.toString(16)}`); console.log(`${prefix} type: ${ObjectType[obj.type]}`); console.log(`${prefix} fragment type: ${FragmentType[obj.fragmentType]}`); if (obj.data) { console.log( `${prefix} data: ${obj.data.toString("hex")} (${ obj.data.length } bytes)`, ); } console.log(); }