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.
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.