OBIS 1.0.32.7.0.255 Phase A Voltage Scaler-Unit 0xFF Parsing Bug (-1 vs 255 Exponent)
-
Overview
When querying Class 3 (Register) object
1.0.32.7.0.255(Phase A Instantaneous Voltage), our data collector parsed a raw voltage value of2200with scaler0xFFand produced a catastrophic measurement reading:2200000000000000000000 V(2.2 x 10^27 V).DLMS APDU Response Trace
C4 01 C1 00 00 02 02 12 08 98 02 02 0F FF 16 23ASN.1 Type Dissection
C4 01 C1:GET-Response-Normal(Invoke-Id-And-PriorityC1)00 00: Data-Access-Resultsuccess(0)02 02: Structure of 2 elements12 08 98: Element 1 ->double-long-unsigned(Value = 2200 /0x0898)02 02: Element 2 -> Structure of 2 elements (Scaler_Unit_Type)0F FF: Scaler ->Integer8(0xFF)16 23: Unit ->enum(35 =0x23= VoltsV)
Root Cause
Per DLMS Blue Book Section 4.3.3, the
scalerfield is of typeInteger8(signed 8-bit integer) in two's complement representation.0xFF=-1(Scaling factor is $10^{-1} = 0.1$)- Correct calculation: $2200 \times 10^{-1} = 220.0\text{ V}$
- The bug: The parsing library treated
0xFFasuint8_t(255), evaluating $2200 \times 10^{255}$ and overflowing database decimal columns!
-
This is one of the classic pitfalls in DLMS COSEM client implementations!
Here is the safe deserialization snippet in Python:
import struct def decode_scaler_unit(scaler_byte, unit_enum): # 'b' ensures signed 8-bit integer interpretation (-128 to 127) signed_scaler = struct.unpack('b', bytes([scaler_byte]))[0] multiplier = 10 ** signed_scaler return signed_scaler, multiplier scaler, mult = decode_scaler_unit(0xFF, 35) print(f"Scaler: {scaler}, Multiplier: {mult}, Voltage: {2200 * mult} V") # Output: Scaler: -1, Multiplier: 0.1, Voltage: 220.0 V -
Note that for Class 4 (Extended Register) and Class 5 (Demand Register), the scaler-unit structure is identical, but is followed by a
statusoctet-string or bit-string and an optionalcapture_time(Octet-String, 12 bytes). If you don't enforce signedint8decoding across all register classes, power factor and reactive energy registers with negative scalers will corrupt downstream analytics. -
Thanks Elena! We applied the signed
int8cast in the collection pipeline parser. All phase voltages (A/B/C:1.0.32.7.0.255,1.0.52.7.0.255,1.0.72.7.0.255) now correctly read 220.4V, 219.8V, and 220.1V.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login