Skip to content

v1.6.0

Latest

Choose a tag to compare

@lvogt lvogt released this 26 Sep 20:51

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.name names the quantity: an energy is energy whether the meter reports it in Wh or in GJ, a flow temperature is flow_temperature in °C and in °F.
  • info.extensionNames lists 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 name of 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