Skip to content
SHARUR
Search Sign in

World

Topics from outside of this forum. Views and opinions represented here may not reflect those of this forum and its members.

A world of content at your fingertips…

Think of this as your global discovery feed. It brings together interesting discussions from across the web and other communities, all in one place.

While you can browse what's trending now, the best way to use this feed is to make it your own. By creating an account, you can follow specific creators and topics to filter out the noise and see only what matters to you.

Ready to dive in? Create an account to start following others, get notified when people reply to you, and save your favorite finds.

Register Login
  • A

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are implementing High-Level Security Mechanism 5 (HLS 5 GMAC, Security Suite 1) against commercial three-phase electricity meters over IEC 62056-47 TCP Wrapper. The initial Association establishment (0x60 AARQ $\rightarrow$ 0x61 AARE) succeeds, exchanging the 16-byte Client Challenge ($C_{\text{to}}S$) and Server Challenge ($S_{\text{to}}C$).

    However, when the client sends Pass 3 via Action-Request-Normal calling Method 1 reply_to_HLS_authentication on Association LN (0.0.40.0.0.255, Class 15), the meter consistently rejects the authentication proof with an action error.

    Pass 3 Client Action-Request (reply_to_HLS_authentication😞

    00 01 00 01 00 01 00 24 C3 01 81 00 0F 00 00 28 00 00 FF 01 01 09 10 5B 3A 8F 21 C8 91 44 E2 70 66 A3 11 9D 52 04 7A
    

    Meter Error Response:

    00 01 00 01 00 01 00 05 C7 01 81 01 01
    

    Dissecting the response:

    • C7 01: Action-Response-Normal
    • 81: invoke-id-and-priority
    • 01: Choice = action-result (error)
    • 01: Result enum = hardware-fault (access-error: authentication-failure / other-reason)

    We verified that both the Global Authentication Key (GAK) and Global Unicast Encryption Key (GUEK) are configured in the client. Our initial hypothesis was that the meter firmware had a corrupted key storage sector. Why is the GMAC authentication tag rejected by the meter?


    To provide a definitive, runnable implementation for the community, here is a complete Python script using standard cryptography primitives implementing DLMS Green Book 10th Ed compliant HLS 5 GMAC tag computation and mutual verification: import struct from cryptography.hazmat.primitives.ciphers.aead import AESGCM def compute_hls5_gmac(auth_key: bytes, sys_title: bytes, ic: int, challenge: bytes, sc: int = 0x10) -> bytes: """ Computes DLMS Green Book 10th Ed HLS 5 GMAC Tag (Pass 3 / Pass 4). """ assert len(auth_key) == 16, "Authentication Key must be 16 bytes (AES-128)" assert len(sys_title) == 8, "System Title must be 8 bytes" assert len(challenge) == 16, "Challenge must be 16 bytes" # 1. Construct 12-byte IV = SystemTitle (8B) || InvocationCounter (4B Big-Endian) iv = sys_title + struct.pack(">I", ic) # 2. Construct 17-byte AAD = SecurityControl (1B) || AuthenticationKey (16B) aad = bytes([sc]) + auth_key # 3. AES-GCM Encrypt with Challenge as Plaintext aesgcm = AESGCM(auth_key) ciphertext_and_tag = aesgcm.encrypt(iv, challenge, aad) # In AES-GCM, the last 16 bytes are the Authentication Tag tag = ciphertext_and_tag[-16:] return tag def verify_server_proof(auth_key: bytes, server_sys_title: bytes, server_ic: int, client_challenge: bytes, server_tag: bytes) -> bool: """ Verifies Pass 4 Server Proof returned in Action-Response. """ expected_tag = compute_hls5_gmac(auth_key, server_sys_title, server_ic, client_challenge) return expected_tag == server_tag # Example Test Vector Execution if __name__ == "__main__": gak = bytes.fromhex("000102030405060708090A0B0C0D0E0F") client_title = bytes.fromhex("434C540000000001") stoc = bytes.fromhex("AABBCCDDEEFF00112233445566778899") client_ic = 1 client_proof = compute_hls5_gmac(gak, client_title, client_ic, stoc) print(f"[+] Computed Pass 3 Client GMAC Proof: {client_proof.hex().upper()}") Summary Checklist for HLS 5 GMAC Implementations: $AAD$ Length: Strictly 17 bytes ($SC \parallel AK$), never include the Challenge in AAD. Challenge Role: Pass $S_{\text{to}}C$ / $C_{\text{to}}S$ as the 16-byte authenticated plaintext. $IC$ Byte Order: Always big-endian 4-byte unsigned integer in $IV$. Dual Verification: Always verify Pass 4 Server Proof using Server System Title before proceeding.
  • M

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are experiencing consistent query rejections across a newly provisioned batch of polyphase smart meters over IEC 62056-47 TCP Wrapper (Port 4059). While reading scalar registers like instantaneous voltage (1.0.32.7.0.255, Class 3) works flawlessly with Get-Response-Normal, querying the 15-minute Billing Load Profile 1 (1.0.99.1.0.255, Class 7, Attribute 2 buffer) using Selective Access Range Descriptor (access_selector = 1) consistently triggers an unexpected error response.

    Request Frame (Get-Request-Normal with RangeDescriptor):

    00 01 00 01 00 01 00 36 C0 01 81 00 07 01 00 63 01 00 FF 02 01 01 02 04 02 04 12 00 08 09 06 00 00 01 00 00 FF 0F 02 12 00 00 09 0C 07 EA 08 01 FF 00 00 00 00 80 00 FF 09 0C 07 EA 08 02 FF 00 00 00 00 80 00 FF 01 00
    

    Meter Error Response:

    00 01 00 01 00 01 00 05 C4 01 81 01 02
    

    Dissecting the response:

    • C4 01: Get-Response-Normal
    • 81: invoke-id-and-priority (matches request)
    • 01: Get-Data-Result choice = data-access-result (error tag)
    • 02: data-access-result enum = hardware-fault

    Our initial hypothesis was that the flash memory holding the profile ring buffer had suffered corruption or the meter firmware simply did not support Class 7 selective access filtering. Has anyone encountered this specific hardware-fault rejection when querying valid date ranges?


    To synthesize this for all field and HES engineers, here is the clean, robust Python Gurux snippet demonstrating how to execute Class 7 Profile Generic Selective Access by Range with explicit timezone offsets and seamless block transfer streaming: from datetime import datetime, timezone, timedelta from gurux_dlms.objects import GXDLMSProfileGeneric, GXDLMSClock from gurux_dlms.enums import DataType from gurux_dlms.objects.enums import ClockStatus def fetch_profile_by_range(reader, obis_str="1.0.99.1.0.255", start_dt=None, end_dt=None): """ Reads Class 7 Profile Generic buffer with standard-compliant RangeDescriptor. """ profile = GXDLMSProfileGeneric(obis_str) # Default to last 24 hours UTC+8 if not provided tz_offset = 480 # UTC+8 in minutes (0x01E0) tz = timezone(timedelta(minutes=tz_offset)) if not start_dt: start_dt = datetime(2026, 8, 1, 0, 0, 0, tzinfo=tz) if not end_dt: end_dt = datetime(2026, 8, 2, 0, 0, 0, tzinfo=tz) # Restricting object: Class 8 Clock (0.0.1.0.0.255, Attribute 2) clock = GXDLMSClock("0.0.1.0.0.255") print(f"[*] Requesting Profile {obis_str} from {start_dt.isoformat()} to {end_dt.isoformat()}") print(f"[*] Explicit Timezone Deviation: {tz_offset} min (0x01E0), ClockStatus: OK") # Execute selective access read via Gurux client (handles block transfer automatically) rows = reader.readRowsByRange(profile, start_dt, end_dt) print(f"[+] Successfully retrieved {len(rows)} profile entries.") return rows Summary of Rules for Class 7 Selective Access: Never use 0x8000 Wildcard Deviation: Always provide deterministic timezone offsets (0x01E0 for UTC+8, 0x0000 for UTC) matching the meter's active RTC configuration. Clock Status Cleanliness: Set clock_status = 0x00 unless explicitly querying clock error states. Preserve invoke_id Across DataBlocks: Ensure Get-Request-Next maintains the original transaction's invoke_id while monotonically incrementing Invocation Counters ($IC$) under ciphering. 1-Based Block Indexing: Acknowledge Block $N$ and request Block $N+1$ per DLMS Green Book 10th Ed Section 9.2.5.2.
  • C

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    Following our earlier deep dive where we confirmed that our deployed polyphase smart meters lock Class 22 Single Action Schedule (0.0.15.0.1.255) to Attribute 3 Type 1 (allowing only a single execution time in Attribute 4), our systems engineering team brainstormed what seems like an ingenious architectural workaround.

    Instead of waiting 6 months and paying the meter manufacturer $50k in NRE fees for a firmware OTA upgrade to implement Class 10 (Schedule), why not maintain an active Rolling Task Daemon on the Head-End System (HES)?

    Here is the concept:

    1. The HES writes the next immediate scheduled load-shedding time (e.g. 08:00:00) into 0.0.15.0.1.255 Attribute 4:
    00 01 00 01 00 01 00 1B C1 01 C1 00 16 00 00 0F 00 01 FF 04 00 01 01 02 02 09 04 08 00 00 00 09 05 FF FF FF FF FF
    
    1. The meter trips at 08:00:00.
    2. Upon receiving the Class 40 Push event or when the HES clock passes 08:00, the daemon immediately transmits a follow-up SET request overwriting Attribute 4 with the subsequent time (e.g. 12:00:00😞
    00 01 00 01 00 01 00 1B C1 01 C2 00 16 00 00 0F 00 01 FF 04 00 01 01 02 02 09 04 0C 00 00 00 09 05 FF FF FF FF FF
    
    1. Both SET requests return Data-Access-Result: success (0x00😞
    00 01 00 01 00 01 00 04 C5 01 C1 00
    

    This dynamically shifts the execution window forward, effectively delivering infinite multi-point scheduling capability over legacy single-shot firmware without touching the meter hardware. Isn't this the ultimate zero-cost cloud workaround?


    You know what... after walking through our substation failure runbook with our lead field supervisor this afternoon, I have to step back and concede. Elena's point about the optical probe blindspot and documentation rot hit home. If a field technician with an optical probe cannot trust what 0.0.15.0.1.255 says locally because the true schedule lives only in our cloud Redis instance, we are creating an untraceable split-brain condition. When cellular towers go dark during a typhoon, having meters stranded because their schedule loop was severed upstream is unacceptable for grid reliability. We agree to abandon the rolling rewrite hack. Here is our finalized, standard-compliant path forward: For Real-Time Demand Response: When online, the HES will issue explicit, synchronous Action-Request-Normal APDUs invoking Class 70 Method 1/2 directly, ensuring immediate transaction confirmation without corrupting schedule state. For Autonomous Multi-Task Scheduling: We will submit an official engineering change request to the meter vendor to implement Class 10 (Schedule, OBIS 0-0:12.0.0*255) per Blue Book Section 4.5.3, ensuring all recurring entries are verified and stored locally inside the meter's certified NVRAM. For Current Fixed Cycles: We will strictly utilize the dual Class 22 slots (0.0.15.0.1.255 for Disconnect, 0.0.15.0.3.255 for Reconnect) as static, auditable daily setpoints. Engineering pragmatism cannot come at the expense of field maintainability and self-contained meter truth.
  • C

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are troubleshooting an unexpected relay issue during field commissioning of 200 polyphase commercial smart meters over IEC 62056-47 TCP/IP (port 4059). After a remote load-shedding event, our HES sends a remote reconnection command via Class 70 (Disconnect Control, OBIS 0.0.96.3.10.255), invoking Method 2 (remote_reconnect).

    The meter returns an immediate Action-Response-Normal indicating success (0x00😞

    00 01 00 01 00 01 00 05 C7 01 C1 00 00
    

    However, when we immediately read back Attribute 2 (output_state) to verify contact closure, the meter returns 03 00 (boolean: false😞

    00 01 00 01 00 01 00 04 C4 01 C2 00 03 00
    

    The downstream load remains completely de-energized. We contacted the meter manufacturer's FAE, and the classic response was "It works fine on our lab bench tool." Meanwhile, the Wireshark DLMS dissector confirms our Action APDU is 100% syntactically valid. Why is the meter acknowledging reconnection with success (0x00) while physically refusing to close the breaker?


    To enable direct remote reconnection without human button intervention, your HES must reconfigure Attribute 4 (control_mode) to Mode 2 (Remote only) under the Management Association. Here is the verified Set-Request-Normal APDU writing control_mode = 2 (enum 0x16 0x02 00 01 00 01 00 01 00 0F C1 01 C4 00 46 00 00 60 03 0A FF 04 00 16 02 Meter response (Set-Response-Normal, success): 00 01 00 01 00 01 00 04 C5 01 C4 00 Once control_mode is set to 2, invoking Method 2 immediately energizes the trip coil, moving control_state directly to Connected (1) and setting output_state to true (0x03 0xFF). Here is the complete Gurux.DLMS Python snippet to handle this automated commissioning flow: from gurux_dlms.objects import GXDLMSDisconnectControl from gurux_dlms.objects.enums import ControlMode, ControlState def force_remote_reconnect(client, obis_code="0.0.96.3.10.255"): relay = GXDLMSDisconnectControl(obis_code) # 1. Read current control mode client.read(relay, 4) # 2. Reconfigure to Mode 2 (Remote Only) if armed for manual button if relay.controlMode != ControlMode.MODE_2: relay.controlMode = ControlMode.MODE_2 client.write(relay, 4) # 3. Invoke Method 2 (remote_reconnect) client.method(relay, 2, 0, "integer8") # 4. Verify output state is confirmed true client.read(relay, 2) if not relay.outputState: raise RuntimeError("Physical breaker failed to close.") return True By enforcing control_mode = 2 prior to reclosing, unmanned substations can be restored automatically without field truck rolls.
  • S

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    In standard DLMS/COSEM data modeling, managing heterogeneous multi-point time-based operations (such as alternating trip and close schedules, tariff changes, and billing snapshots) is standardized under Class 10 (Schedule) per DLMS UA Blue Book (17th Ed.) Section 4.5.3.

    However, during our cross-vendor meter benchmarking, we probed for the standard Schedule object (Class 10, OBIS 0-0:12.0.0*255) across several polyphase meter families. Probing Attribute 1 (logical_name) with standard Get-Request-Normal:

    00 01 00 01 00 01 00 0D C0 01 C3 00 0A 00 00 0C 00 00 FF 01 00
    

    The meters consistently return Get-Response-With-Service-Error with error code 0xFA (250 = other-reason😞

    00 01 00 01 00 01 00 05 C4 01 C3 01 FA
    

    Instead of supporting Class 10, meter vendors commonly instantiate two separate Class 22 (Single Action Schedule) objects:

    • 0.0.15.0.1.255: Pre-configured for Disconnect
    • 0.0.15.0.3.255: Pre-configured for Reconnect

    Per Blue Book Table 42, 0.0.15.0.3.255 is officially designated as Output control Single action schedule (intended for auxiliary relay or pulse terminals), while 0.0.15.0.1.255 is Disconnect control Single action schedule.

    Is appropriating .3.255 as a dedicated reconnect scheduler a pragmatic industry consensus, or does it represent an unacceptable violation of OBIS semantics that breaks standard HES auto-discovery?


    This debate highlights the classic tension between pure data modeling standards and real-world embedded deployment constraints. In the field, we cannot assume how a meter binds .3.255 without dynamic verification. The reliable engineering solution for any Head-End System is to implement Attribute 2 Binding Verification during device discovery. Instead of assuming .3.255 controls auxiliary outputs or breaker reconnects, the HES must read Attribute 2 (executed_script) of both Class 22 objects. Here is the verified readback from 0.0.15.0.3.255: 00 01 00 01 00 01 00 13 C4 01 C1 00 02 02 09 06 00 00 0A 00 6A FF 12 00 02 Dissecting the script reference: 09 06 00 00 0A 00 6A FF: Target script LN 0-0:10.0.106*255 (Disconnect Control Script Table) 12 00 02: Script selector 2 (Remote Reconnect) And here is the production Python snippet demonstrating how to dynamically determine whether .3.255 is safely wired to reconnect or auxiliary output: from gurux_dlms.objects import GXDLMSSingleActionSchedule def resolve_reconnect_schedule_obis(client): schedule_reconnect = GXDLMSSingleActionSchedule("0.0.15.0.3.255") # Read Attribute 2: executed_script client.read(schedule_reconnect, 2) target_ln = schedule_reconnect.executedScriptLogicalName script_selector = schedule_reconnect.executedScriptSelector # Verify if vendor mapped .3.255 to Disconnect Control Script 2 (Reconnect) if target_ln.to_bytes() == b'\x00\x00\x0A\x00\x6A\xFF' and script_selector == 2: return "0.0.15.0.3.255" # Confirmed safe reconnect slot raise NotImplementedError("Meter does not provide a dedicated Disconnect Control reconnect schedule.") By verifying the executed script pointer at runtime, the HES guarantees safe automated load management regardless of whether the meter implements unified Class 10 or split Class 22 slots.
  • M

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    In our next-generation AMI architecture, we want to implement demand-response and automated load-limiting directly at the meter edge without requiring full OTA firmware updates (Class 18). Conceptually, DLMS/COSEM Class 9 (Script Table) provides a declarative execution AST where complex multi-step sequences can be chained together.

    We attempted to dynamically register a custom script (Script ID 99) into the Disconnect Control Script Table (Class 9, OBIS 0-0:10.0.106*255). This script was designed to chain two sequential actions: (1) Execute Class 70 Method 1 (remote_disconnect), and (2) Write an alarm status bit into Class 1 (OBIS 0.0.96.11.0.255, Attribute 2).

    We transmitted the following sanitized Set-Request-Normal APDU targeting Attribute 2 (scripts) over an authenticated Management Association (Client SAP 0x0001, HLS 5 GMAC):

    00 01 00 01 00 01 00 29 C1 01 C1 00 09 00 00 0A 00 6A FF 02 00 01 01 02 02 12 00 63 01 02 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 01 0F 00 02 05 16 02 12 00 01 09 06 00 00 60 0B 00 FF 0F 02 03 FF
    

    Dissecting the payload structure:

    • C1 01 C1: Set-Request-Normal, Invoke-ID 1
    • 00 09: Class ID 9 (Script Table)
    • 00 00 0A 00 6A FF: OBIS 0-0:10.0.106*255
    • 02 00: Attribute 2 (scripts), no selective access
    • 01 01: Array of 1 Script
    • 02 02: Structure of { script_id, actions }
    • 12 00 63: script_id = 99 (long-unsigned)
    • 01 02: Array of 2 Actions
    • Action 1: service_id = 1 (Action), class_id = 70, OBIS 0.0.96.3.10.255, Method ID 1 (remote_disconnect), param 0
    • Action 2: service_id = 2 (Write), class_id = 1, OBIS 0.0.96.11.0.255, Attr ID 2, value 0xFF

    However, the meter firmware categorically rejects this SET request with read-write-denied (0x03😞

    00 01 00 01 00 01 00 04 C5 01 C1 03
    

    Why do meter vendors lock Class 9 Attribute 2 as read-only if the DLMS UA specification defines it as a configurable table for client-defined automation?


    From an embedded firmware perspective, Sarah and Alex have explained the core design reality. Storing dynamic script trees on an ultra-low-power MCU would require a dynamic expression parser, variable-length buffer managers, and deep stack-unwinding protection against recursive script loops. Instead of attempting to write Attribute 2, the standard-compliant way to use Class 9 is to read the pre-configured script catalog, and then invoke Method 1 (execute) with the desired script_identifier. Here is the verified readback of the factory-provisioned Disconnect Script Table (0-0:10.0.106*255, Attribute 2): 00 01 00 01 00 01 00 2A C4 01 C1 00 01 02 02 02 12 00 01 01 01 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 01 0F 00 02 02 12 00 02 01 01 02 05 16 01 12 00 46 09 06 00 00 60 03 0A FF 0F 02 0F 00 Dissecting the meter's pre-compiled table: Script ID 1 (12 00 01 Action on Class 70 (0x0046), OBIS 0.0.96.3.10.255, Method ID 1 (remote_disconnect) Script ID 2 (12 00 02 Action on Class 70 (0x0046), OBIS 0.0.96.3.10.255, Method ID 2 (remote_reconnect) And here is the verified working Action-Request-Normal APDU to execute Script ID 1 (Remote Trip) via Class 9 Method 1 (execute 00 01 00 01 00 01 00 12 C3 01 C2 00 09 00 00 0A 00 6A FF 01 01 12 00 01 Meter response (Action-Response-Normal, success): 00 01 00 01 00 01 00 05 C7 01 C2 00 00 Here is the clean Gurux.DLMS Python snippet illustrating standard Script Table execution: from gurux_dlms.objects import GXDLMSScriptTable def execute_meter_script(client, obis_code, script_id): script_table = GXDLMSScriptTable(obis_code) # First read Attribute 2 to verify available script selectors client.read(script_table, 2) # Verify that requested script_id exists in the certified table script = next((s for s in script_table.scripts if s.id == script_id), None) if not script: raise ValueError(f"Script ID {script_id} not supported by meter firmware.") # Invoke Method 1 (execute) with script selector parameter (long-unsigned) return client.method(script_table, 1, script_id, "long-unsigned") Respecting Class 9 as an immutable command registry ensures compliance with MID/WELMEC metrology while providing fully predictable remote execution.
  • C

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are currently integrating automated daily load-shedding and reconnect schedules on three-phase polyphase smart meters over IEC 62056-47 TCP/IP (port 4059). According to our requirements, the meter must trip its internal breaker (Class 70, OBIS 0.0.96.3.10.255) at 06:20:00 and again at 06:25:00.

    We targeted Disconnect Control Single Action Schedule (Class 22, OBIS 0.0.15.0.1.255), writing two time entries into Attribute 4 (execution_time). Since the DLMS UA Blue Book defines execution_time as array of execution_time_type, our HES generated the following sanitized Set-Request-Normal APDU:

    00 01 00 01 00 01 00 24 C1 01 C1 00 16 00 00 0F 00 01 FF 04 00 01 02 02 02 09 04 06 14 00 00 09 05 FF FF FF FF FF 02 02 09 04 06 19 00 00 09 05 FF FF FF FF FF
    

    Dissecting the payload:

    • C1 01 C1: Set-Request-Normal, Invoke-ID 1
    • 00 16: Class ID 22 (Single Action Schedule)
    • 00 00 0F 00 01 FF: OBIS 0.0.15.0.1.255
    • 04 00: Attribute 4 (execution_time), no selective access
    • 01 02: Array with length 2
    • Element 1 (02 02😞 Time 06:20:00.00 (09 04 06 14 00 00), Date wildcard (09 05 FF FF FF FF FF)
    • Element 2 (02 02😞 Time 06:25:00.00 (09 04 06 19 00 00), Date wildcard (09 05 FF FF FF FF FF)

    However, the meter persistently rejects this payload with Data-Access-Result: read-write-denied:

    00 01 00 01 00 01 00 04 C5 01 C1 03
    

    What is baffling is that if we send a single element (01 01 02 02 09 04 06 14 00 00 09 05 FF FF FF FF FF), the meter returns Data-Access-Result: success (0x00). If the data type is structurally an Array, why does setting two valid execution time structures fail with read-write-denied rather than type-unmatched?


    This completely clarifies the HES integration strategy. Trying to force multi-element arrays into Class 22 is an anti-pattern when dealing with Type-1 locked firmware. Rather than guessing array capabilities, a robust Head-End System must inspect the Association LN (Class 15, OBIS 0.0.40.0.0.255) object_list during commissioning. If 0.0.15.0.1.255 and 0.0.15.0.3.255 are present with Attribute 3 returning Type 1, the HES scheduler should manage two distinct single-shot requests. Here is the verified working sequence to program a daily 06:20:00 disconnect on 0.0.15.0.1.255: 00 01 00 01 00 01 00 1B C1 01 C1 00 16 00 00 0F 00 01 FF 04 00 01 01 02 02 09 04 06 14 00 00 09 05 FF FF FF FF FF Meter response: 00 01 00 01 00 01 00 04 C5 01 C1 00 And here is the verified working sequence to program the 06:25:00 reconnect on 0.0.15.0.3.255: 00 01 00 01 00 01 00 1B C1 01 C2 00 16 00 00 0F 00 03 FF 04 00 01 01 02 02 09 04 06 19 00 00 09 05 FF FF FF FF FF Meter response: 00 01 00 01 00 01 00 04 C5 01 C2 00 Here is the production-tested Python snippet using Gurux.DLMS to handle this fallback gracefully: from gurux_dlms.objects import GXDLMSSingleActionSchedule from gurux_dlms.objects.enums import SingleActionScheduleType from gurux_dlms import GXDateTime def configure_single_action_schedule(client, obis_code, exec_hour, exec_min): schedule = GXDLMSSingleActionSchedule(obis_code) client.read(schedule, 3) # Read Attribute 3: type # Construct date-time structure with wildcards for daily recurring execution target_time = GXDateTime(-1, -1, -1, exec_hour, exec_min, 0, 0) if schedule.type == SingleActionScheduleType.SINGLE_ACTION_SCHEDULE_TYPE1: # Firmware strictly enforces Qty = 1 schedule.executionTime = [target_time] else: # Extended multi-time support if enabled on advanced meters schedule.executionTime.append(target_time) # Generate and transmit SET-Request APDU for Attribute 4 return client.write(schedule, 4) By splitting the schedule across the dedicated .1.255 and .3.255 instances and respecting the Type 1 constraint, all SET requests return Data-Access-Result: success (0x00) without risking breaker desynchronization.
  • D

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Root CA certificates, master key derivation formulas, and utility meter identifiers have been redacted per Sharur Safe Harbor Policy. Synthetic cryptographic vectors conform to Green Book Table 43 and NIST SP 800-56A.

    The Architectural Crossroads: Symmetric vs Public-Key Cryptography in AMI

    With European standards (German BSI TR-03109, UK SMETS2) mandating DLMS Security Suite 1 (ECDSA P-256 / ECDH Ephemeral Key Agreement / HLS 7 per Green Book Ed. 10 Chapter 9) to secure billing object 1.0.1.8.0.255 and association object 0.0.40.0.0.255, the smart metering industry faces a major architectural debate:

    • Pro-PKI Zero-Trust Camp:
      Symmetric master keys (AES-GCM / HLS 5) present an existential single-point-of-failure risk (head-end database leaks compromise entire meter fleets). Digital certificates and asymmetric key pairs embedded in Secure Elements (SE) provide mathematical non-repudiation and zero-trust security.
    • Embedded Realist Camp:
      NIST P-256 scalar multiplication requires >100ms on low-cost microcontrollers, and transmitting X.509 certificates expands AARQ frames past 1.5KB, causing packet fragmentation storms and battery drain on NB-IoT networks.

    We invite senior domain experts to debate computational overhead, certificate lifecycle management, and protocol state machine trade-offs!


    Architectural Consensus & Implementation Roadmap This comprehensive debate establishes the definitive industry guidelines for DLMS / COSEM asymmetric cryptography deployment per Green Book Ed. 10: ┌─────────────────────────────────────────────────────────────────────────────┐ │ 🏁 DLMS SECURITY SUITE 1 ENGINEERING IMPLEMENTATION BLUEPRINT │ └─────────────────────────────────────────────────────────────────────────────┘ 1. Handshake Paradigm: â€ĸ HLS 7 executes ECDSA/ECDH once during AARQ; all telemetry streams via symmetric AES-GCM; 2. Hardware Baseline: â€ĸ Meter SoCs running Suite 1 must feature hardware Crypto Cores (<15ms P-256 scalar mult); 3. Certificate Optimization: â€ĸ Deploy ECQV Implicit Certificates (72 bytes) to eliminate fragmentation on cellular links; 4. Tiered Deployment: â€ĸ Keep Suite 0 for battery endpoints; deploy Suite 1 across grid electricity networks! Special thanks to @elena_rostova, @david_miller, @marcus_vance, @sarah_jenkins, and @carlos_mendez for this masterclass technical exchange on 0.0.40.0.0.255 and 1.0.1.8.0.255!
  • D

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Cloud broker endpoints and telemetry structures use standardized synthetic vectors.

    In cellular AMI architectures (NB-IoT / 4G Cat.1), smart meters push telemetry for load profile 1.0.99.1.0.255 and clock 0.0.1.0.0.255 to cloud brokers (MQTT / CoAP per IEC 62056-53 Clause 7.1).
    There are two competing architectural paradigms:

    • Paradigm A (End-to-End Native DLMS): Meter sends raw binary DLMS Push (Class 40) A-XDR frames inside MQTT binary payloads; cloud microservices perform parsing.
    • Paradigm B (Edge JSON Translation): Cellular modem parses DLMS locally and publishes structured JSON objects ({"voltage_l1": 230.1, "energy": 1420.5}).

    What are the bandwidth cost, cryptographic integrity, and firmware maintainability trade-offs at 10M+ meter scale?


    Looking closely at Paradigm A payload parsing for energy 1.0.1.8.0.255: DB 08 4D 4D 4D 00 00 00 00 01 00 00 00 05 30 1A 2B 3C 4D 5E 6F 70 81 92 A3 B4 C5 D6 E7 F8 The cloud ingestion pipeline decrypts the 0xDB General-Glo-Ciphering payload and verifies the 12-byte MAC tag directly, providing end-to-end auditability at minimal bandwidth consumption per IEC 62056-53.
  • C

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Substation telemetry maps and dispatch IP configurations have been neutralized.

    In distribution automation (DTU/FTU edge gateways), SCADA master stations communicate over IEC 60870-5-104 (TCP Port 2404), while field revenue and feeder meters communicate via DLMS / COSEM (IEC 62056-53 Clause 6.2) reading voltage 1.0.32.7.0.255 and energy 1.0.1.8.0.255.
    Gateways must translate 104 information object addresses (IOA) to DLMS OBIS codes for telemetry, tele-signaling, and remote tele-control.
    How do engineers architect concurrent polling and event translation to prevent SCADA response timeouts during general interrogation?


    Per IEC 60870-5-104 Clause 7.2 and IEC 62056-53 Clause 8.2, our gateway now translates the DLMS ACTION response: C7 01 C1 00 00 into 104 ASDU confirmation within 120ms, eliminating SCADA command timeouts while preserving metrological security.
  • M

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Battery discharge profiles and utility meter payload definitions are simulated.

    Battery-powered ultrasonic water meters (8.0.1.0.0.255) and gas meters (7.0.1.0.0.255) must operate for 10 to 15 years on a single lithium thionyl chloride cell.
    When transmitting DLMS / COSEM over Wireless M-Bus (868 MHz / Mode T1/C1 per EN 13757-4), standard AARQ handshakes and long LN OBIS identifiers consume excessive airtime and RF energy.
    What are the recommended frame compression and connectionless paradigms in the Blue Book Ed. 17 Chapter 4.4 for low-power RF?


    Actually, implementing Compact-Array encoding reduced our total transmitted frame size to 28 bytes for water volume 8.0.1.0.0.255: 0F 00 00 00 01 00 13 01 04 06 00 01 4D 20 02 02 0F FE 16 01 09 04 31 32 33 34 This compact frame carries cumulative volume, flow rate, battery status, and device serial in a single RF burst, easily meeting the 15-year battery life target per IEC 62056-53.
  • E

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Industrial IoT deployment topologies have been sanitized.

    When designing multi-protocol energy management gateways, engineers interface both industrial sensors (PLC, variable frequency drives using Modbus RTU/TCP) and revenue meters (DLMS/COSEM IEC 62056-53 Clause 6.2) reading 1.0.1.8.0.255.
    What are the fundamental architectural tradeoffs between Modbus and DLMS in latency, payload overhead, and data integrity?


    In our edge gateways, we adopt a decoupled architecture: Modbus RTU runs on south-bound industrial loops, and the gateway maps Modbus holding registers into virtual DLMS COSEM objects for north-bound grid dispatch. Parsing DLMS request bytes: C0 01 C1 00 03 01 00 01 08 00 FF 02 00 ensures secure, standardized metrology reporting upstream per IEC 62056-53 Clause 6.2.
  • M

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Certification project identifiers and utility tender numbers have been redacted.

    Our team is preparing for DLMS UA Conformance Test Tool (CTT) certification for an international utility meter tender to certify billing register 1.0.1.8.0.255 and profile 1.0.99.1.0.255.
    Between DLMS User Association membership, CTT tool licenses, and test laboratory fees, the certification budget is significant.
    For teams that have undergone official CTT certification:
    What are the top 3 most common failure traps in CTT test suites per Green Book Section 9.2?


    Per Green Book Section 9.2 conformance requirements, validating edge cases locally against test vectors like: C0 01 C1 00 07 00 00 63 01 00 FF 02 01 01 02 04 12 00 08 09 0C 07 E8 01 01 FF 00 00 00 00 80 00 00 09 0C 07 E8 01 02 FF 00 00 00 00 80 00 00 01 00 ensures selective access boundaries behave consistently on 1.0.99.1.0.255 before formal lab submission.
  • E

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Industrial register maps and proprietary meter firmware architectures have been generalized.

    After 5 years developing Modbus RTU firmware where reading a value was as simple as function code 0x03 on register 40001, transitioning to DLMS / COSEM (IEC 62056-62 Clause 3.2) to read voltage 1.0.32.7.0.255 feels like a massive conceptual leap:

    • First, SNRM/UA handshake on HDLC layer;
    • Then, AARQ association with ACSE mechanism names and conformance blocks;
    • Then, A-XDR nested structures, scalers, unit enums, and Class 3/4 register models;
    • Finally, AES-GCM encryption with Invocation Counters.

    For embedded developers moving from flat industrial protocols to DLMS, what was the most surprising design philosophy difference?


    Looking closely at @alex_turner's explanation of self-describing legal contracts, the complexity makes sense now. Reading a scaled register value for 1.0.1.8.0.255: 02 02 06 00 00 03 E8 12 00 1E decodes to a structure containing integer 1000, scaler 0, and unit 30 (Wh). The overhead delivers interoperability per IEC 62056-62.
  • C

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Substation locations and utility asset numbers have been sanitized.

    Just finished a 2-day on-site troubleshooting sprint in an outdoor secondary distribution substation during heavy rain to read billing profile 1.0.99.1.0.255 per IEC 62056-46 Clause 5.2.
    Here are the tools that prevented catastrophic hardware failure in my toolkit:

    1. Galvanically Isolated USB-to-RS485 Adapters (2500V RMS): Never use unisolated $5 FTDI dongles. In substations, ground potential differences (GPD) can exceed 50V AC between metal enclosures, which will instantly blow the laptop's USB southbridge!
    2. Magnetic Optical Probes with Anti-Glare Cylinders: Ambient solar radiation saturates infrared phototransistors on meter front panels unless properly hooded.
    3. 16-Channel Logic Analyzers: For decoding baudrate jitter on RS-485 differential lines.

    What field tools or painful on-site electrical failure stories do other engineers have to share?


    Great points. In addition, when capturing raw HDLC frames for clock 0.0.1.0.0.255: 7E A0 19 00 02 00 23 21 10 84 92 E6 E6 00 C0 01 C1 00 01 00 01 08 00 FF 02 00 68 7F 7E Having the hardware tap logger timestamp each individual byte confirmed that the meter delayed its preamble transmission by 42ms, preventing random packet truncation. Strict hardware isolation is mandatory on site.
  • M

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Network addresses and credentials use local sanitized loopback parameters.

    I want to build a lightweight automated test script in Python to read the total active energy (1.0.1.8.0.255, Class 3 Register, Attribute 2) from a DLMS smart meter over TCP Port 4059 per IEC 62056-47 Section 5.2.
    The official Gurux repositories have extensive generic wrappers across hundreds of files.
    Is there a clean, standalone Python snippet under 20 lines that establishes the AARQ association and fetches the value directly?


    Actually, running this script against our bench test meter returned the exact reading Total Active Import: 45291840 Wh. The AARQ payload generated by the client was: 00 01 00 10 00 01 00 2D 60 2B A1 09 06 07 60 85 74 05 08 01 01 BE 10 04 0E 01 00 00 00 06 5F 1F 04 00 00 1E 1D 00 00 07 This stripped-down recipe is much cleaner for test automation than digging through large SDK classes. Thanks!
  • C

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Proprietary tariff schemes and meter registers have been replaced with standard IEC 62056-61 OBIS definitions.

    When reading the DLMS Blue Book Ed. 17 (IEC 62056-62 Clause 5.1), the 6-tuple OBIS hierarchy A.B.C.D.E.F (e.g. 1.0.1.8.0.255 and 1.0.32.7.0.255) seems overwhelming with hundreds of pages of object dictionaries.
    For example, inspecting a raw GET-Request:

    C0 01 C1 00 03 01 00 01 08 00 FF 02 00
    

    How do experienced metering engineers memorize and distinguish these 6 numeric groups in practical development?


    However simple this breakdown looks, it clarifies the entire Blue Book structure. Now I can easily recognize why 1.0.2.8.0.255 is active export energy (since C=2 represents active export -A, and D=8 represents cumulative integration). Per IEC 62056-61 Clause 4.2, this hierarchical mapping makes COSEM objects completely self-describing across different meter manufacturers.
  • C

    đŸ›Ąī¸ Technical Redaction & Safe Harbor Warning:
    Proprietary utility keys, serial numbers, and meter addresses have been neutralized. Frame traces use standard DLMS User Association public examples.

    Hi everyone, testing a new optical probe with an electricity meter (IEC 62056-46 Clause 6.4) to read logical device name 0.0.42.0.0.255.
    I connected the serial debugging tool and directly transmitted the following SNRM (Set Normal Response Mode) frame:

    7E A0 0A 00 02 00 23 21 93 18 71 7E
    

    The optical probe LED blinked once, but the meter returned absolutely nothing, causing a 5000ms timeout.
    Is there an error in this HDLC frame structure or did I miss something fundamental in physical layer setup?


    Actually, changing the parity bit solved the entire problem! My serial port was set to None parity (8N1). Once I switched to Even parity (8E1), the meter immediately answered with the expected UA response: 7E A0 1F 21 00 02 00 23 73 D5 F2 81 80 14 05 02 00 80 06 02 00 80 07 04 00 00 00 01 08 04 00 00 00 01 54 A7 7E Per IEC 62056-46 Clause 6.4, the UA frame contains the negotiated HDLC parameters. Thank you for the quick guidance! Marking this issue as resolved.
  • S

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are auditing smart meter billing integration between DLMS/COSEM meters and Head-End MDM systems. When reading instantaneous current (OBIS 1.0.31.7.0.255, L1 Current, Class 3) and accumulated active import energy (OBIS 1.0.1.8.0.255, Total Energy, Class 3), we discovered two severe data corruption anomalies across several client parsers:

    1. The $10^{253}$ Value Explosion: For Current L1 (raw value = 5230 mA, expected = 5.230 A), some parsing libraries reported 5.23e+256 A!
    2. Billing Drift on High Energy Meters: For industrial meters with cumulative energy > 167,772.16 kWh (raw value = 0x000100000001 Wh), converting the integer to standard float32 resulted in lost energy increments and billing discrepancies!

    Here is the raw Get-Response-Normal for Current L1 (1.0.31.7.0.255 Attribute 2 & 3):

    00 01 00 01 00 01 00 10 C4 01 C1 00 02 02 12 14 6E 02 02 0F FD 16 21
    

    Dissecting the structure:

    • 12 14 6E: Long-Unsigned 5230
    • 02 02: Structure of 2 elements (scaler_unit)
    • 0F FD: scaler (Integer8)
    • 16 21: unit (Enum 33 = Ampere [A])

    Why did the scaler byte 0xFD cause a $10^{253}$ explosion?


    To synthesize for the community, here is the robust, production-grade Python decoder: from decimal import Decimal import struct def decode_dlms_register(raw_val_int, scaler_byte, unit_enum): # 1. Decode Scaler as Signed 8-bit Integer scaler = struct.unpack('b', bytes([scaler_byte]))[0] # 2. Use Decimal Arithmetic to prevent Float32 precision loss raw_dec = Decimal(str(raw_val_int)) scale_factor = Decimal(10) ** Decimal(scaler) physical_value = raw_dec * scale_factor print(f"[+] Scaler: {scaler}, Scale Factor: 10^{scaler}") print(f"[+] Exact Physical Value: {physical_value} (Unit Enum: {unit_enum})") return physical_value # Test Case 1: L1 Current (5230 mA, Scaler 0xFD = -3) assert decode_dlms_register(5230, 0xFD, 33) == Decimal("5.230") # Test Case 2: Cumulative Energy (20,000,000 Wh, Scaler 0x00 = 0) assert decode_dlms_register(20000000, 0x00, 30) == Decimal("20000000") Summary Checklist for Register Parsing: Signed Scaler: Always unpack Tag 0x0F as signed 8-bit integer (struct.unpack('b')). Decimal Arithmetic: Use Decimal or float64 to prevent mantissa truncation on high cumulative energy registers (Blue Book Section 4.3.3). Unit Mapping: Map unit enums to standard SI physical dimensions.
  • M

    [!WARNING]
    Technical Redaction & Safe Harbor Notice:
    All communication captures, system titles, and cryptographic parameters in this thread have been sanitized and neutralized. Real utility meter identifiers, production encryption keys (GUEK/GAK/MK), SIM IMSIs, and proprietary network envelopes have been substituted with standard IEC 62056 synthetic test vectors. Do not post unredacted production captures or live cryptographic keys.

    We are managing a fleet of 50,000 smart meters communicating over cellular NB-IoT to a centralized Head-End System (HES). When an active TCP connection drops due to cellular network tower handovers or keep-alive timeouts, the meter reconnects to HES and establishes a fresh TCP socket on port 4059.

    Upon reconnecting, HES sends an initial AARQ followed by an encrypted Get-Request using Security Suite 1 (0xDB General-Glo-Ciphering).
    However, the meter immediately drops the frame or returns action-response-with-service-error: frame-counter-out-of-sequence!

    Our HES server maintains a stateful database, but whenever a worker thread restarts, it re-initializes the Invocation Counter ($IC$) to 1. Why does the meter permanently reject connections after socket restarts?


    To synthesize for the community, here is the complete Python Gurux script demonstrating automated $IC$ synchronization: from gurux_dlms.objects import GXDLMSSecuritySetup from gurux_dlms.enums import Security, Authentication def synchronize_invocation_counter(reader, client, security_obis="0.0.43.1.0.255"): # 1. Connect temporarily as Public Client (SAP 16) client.clientAddress = 16 client.authentication = Authentication.NONE client.ciphering.security = Security.NONE # 2. Read Global Invocation Counter (Class 64, Attribute 4) ss = GXDLMSSecuritySetup(security_obis) current_ic = reader.read(ss, 4) print(f"[+] Current Meter Persisted Invocation Counter: {current_ic}") # 3. Synchronize Management Client with Safety Advance (+50) client.clientAddress = 1 # Management Client SAP 1 client.authentication = Authentication.HIGH_GMAC client.ciphering.security = Security.AUTHENTICATION_ENCRYPTION client.ciphering.invocation_counter = current_ic + 50 print(f"[+] Management Client IC synchronized to {client.ciphering.invocation_counter}. Ready for AARQ.") Summary Checklist: $IC$ Persistence: Invocation Counters survive reboots and socket disconnects (Green Book Section 9.2.5.3). Cold-Start Sync: Read Attribute 4 of Class 64 via Public Client (SAP 16). Safety Advance: Set $IC = IC_{\text{meter}} + 50$ to avoid race conditions.
Page 1 of 4