Indeed, creating a more generic decoder would require quite some effort, I think. You could add some sanity checks though, like to ensure that the first byte indeed indicates the “standard” message format, and that you see the expected “DIF” and “VIF” values for the readings that you want to extract.
Just for future reference:
Meanwhile I found that “BCD” refers to binary-coded decimal, which for M-Bus indeed uses half-bytes (nibbles; 4 bits) for each digit. And things like “BCD8” then refer to 8 digit values, which need 8 nibbles, hence 4 bytes. (So, for each digit in a BCD value you’ll only see the hexadecimal values of 0x0 thru 0x9; 0xA thru 0xF are never used, which is a slight waste of bandwidth. But well, you cannot change that.)
So, you’re right about how to get the actual values.
I could not quickly find a pure JavaScript library for some generic M-Bus decoding. Reading a bit more on the M-Bus/Meter-Bus protocol, it seems that generic decoding still needs a hardcoded decision tree for expected “VIF” values (whereas “DIF” values can be used to determine the length and type regardless the VIF, but it seems many possible DIF values are never used in this very device).
Even when limiting to this very device, it seems that small errors in the Elvaco documentation will require a lot of extra field testing. Like the length of xxxxxx
does not always match the number of expected bytes: the excerpt of the documentation above claims Energy is always 6 bytes and BCD8, but nevertheless shows 7 bytes in, e.g., 0CFB00xxxxxxxx
. So, that should either read 0CFB00xxxxxx
which would then be BCD6, or Energy could be 8 bytes in some cases? Also 0C06xxxxxxxx
is listed twice in the same short excerpt, and Power is documented as “BCD8” which should probably read “BCD6”. That’s already 3 errors while quickly browsing one page in the specification.
Finally, a generic decoder would need to include the unit in its output (like apparently Energy can be one of MWh, kWh, MJ or GJ) which then needs to be respected during further processing, or the decoder would need to convert it to a single unit.