Repository navigation
Stable names for every value
Every value now carries a name that identifies what it measures, independent of its unit and its position in the telegram. Consumers can build identifiers from it that survive a meter reordering its records.
info.name and info.extensionNames
const { name, extensionNames, storageNo, tariff, functionField } = value.info;
const id = [name, ...extensionNames].join("_");info.namenames the quantity: an energy isenergywhether the meter reports it in Wh or in GJ, a flow temperature isflow_temperaturein °C and in °F.info.extensionNameslists the VIF extensions which change what a value means, e.g.["negative"]for an energy which only accumulates negative contributions, or["per_hour"]for a volume per hour. Extensions which only scale the value or report an error have no name.
The names were generated once from the descriptions of the VIF tables and are frozen now. They are part of the API from now on: a name only changes with a new major version. They are snake_case, contain no unit, and a test checks every entry of the tables against these rules. A VIF the parser does not know is named after its code (unknown_vif_fd_25), so two of them stay apart.
Record errors
A meter can mark a value as broken, e.g. with "data error" or "no data available". Such a value keeps its name — it is still the same quantity — and info.recordError states the error, e.g. data_error. It is not set for a sound value, so a consumer can skip a broken reading instead of storing it as a real one.
Function field
info.functionField states whether a value is an instantaneous, maximum or minimum value or one during an error state. It used to be available only from the verbose data records.
The built-in descriptions as a starting point
A configured handler replaces the built-in one for its manufacturer instead of adding to it. getManufacturerSpecificDescriptions() returns the descriptions shipped with the parser as plain data, so you can change what needs changing and keep the rest, including the names of the values:
const { ITW } = getManufacturerSpecificDescriptions();
ITW[0].deviceType = [0x1a, 0x1b];
const parser = new WirelessMbusParser({
manufacturerSpecificHandlers: { ITW: createManufacturerSpecificHandler(ITW) },
});The result is a copy and survives JSON, so it can be written to a configuration file as it is.
Also in this release
- A manufacturer specific value and a field of a declarative handler can state a
nameof their own; otherwise it is derived from the legacy name - The record error "data overflow" was described as "undefined"
- The package is built with tsdown instead of tsup, TypeScript 6 and pnpm 12. The type declarations are formatted differently but declare exactly the same API, and the bundles decode every test telegram identically
No breaking changes. info only gains fields. Code which compares whole info objects will see the new ones. Node 22 or newer, as before.
Full changelog: https://github.com/lvogt/wireless-mbus-parser#changelog