<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs?]]></title><description><![CDATA[<blockquote>
<p dir="auto">[!WARNING]<br />
<strong>Technical Redaction &amp; Safe Harbor Notice</strong>:<br />
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.</p>
</blockquote>
<p dir="auto">We are commissioning AMI firmware for multi-rate tariff switching and disconnect scheduling using Activity Calendar (Class 20, OBIS <code>0.0.13.0.0.255</code>, Attribute 4 <code>activate_passive_calendar_time</code>) and Single Action Schedule (Class 22, OBIS <code>0.0.15.0.0.255</code>, Attribute 2 <code>execution_time</code>).</p>
<p dir="auto">When utility operators attempt to disable or deactivate a pending schedule, they frequently transmit either:</p>
<ol>
<li>All-wildcards date/time: <code>FF FF FF FF FF FF FF FF FF 80 00 00</code> (12 bytes),</li>
<li>Zeroed date/time: <code>00 00 00 00 FF 00 00 00 00 80 00 00</code>.</li>
</ol>
<p dir="auto">However, on several batch meters running firmware <code>v2.4.0</code>, writing <code>FF FF...</code> causes the meter to execute the linked script action (e.g. Tariff Switch / Breaker Check) <em>every single second in an infinite 1Hz loop</em>, spiking MCU load to 100% and jamming the optical port! Writing <code>00 00...</code> or an expired timestamp (e.g. <code>2020-01-01</code>) immediately fires the script upon receiving the <code>SET-Request</code>!</p>
<p dir="auto">Here is the sanitized <code>SET-Request</code> transmitted over TCP 4059 wrapper for <code>0.0.13.0.0.255</code> Attribute 4:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 23 DB 08 53 48 41 00 00 00 00 01 30 00 00 00 12 A1 88 9F 33 22 10 44 88 99 C1 C3 01 C1 00 14 00 00 0D 00 00 FF 04 09 0C FF FF FF FF FF FF FF FF FF 80 00 00
</code></pre>
<p dir="auto">And the meter responds with <code>SET-Response-Normal</code> (<code>0xC5 0x01 C1 00: success</code>), immediately followed by the infinite execution loop.</p>
<p dir="auto">Our field operators assumed <code>0xFF</code> was the universal DLMS way to disable scheduled execution. Why is this triggering 1Hz execution storms?</p>
]]></description><link>https://dlms.sharur.org/topic/54/why-does-setting-dlms-execution_time-class-22-class-20-with-wildcards-0xff-or-0x00-trigger-continuous-1hz-firing-or-32-bit-overflow-bugs</link><generator>RSS for Node</generator><lastBuildDate>Fri, 16 Oct 2026 19:20:27 GMT</lastBuildDate><atom:link href="https://dlms.sharur.org/topic/54.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 22 Aug 2026 17:01:14 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:11:39 GMT]]></title><description><![CDATA[<p dir="auto">To synthesize this for all AMI and meter firmware engineers, here is the production Python snippet using Gurux.DLMS demonstrating how to park both Class 20 and Class 22 schedules safely using the universal distant timestamp approach:</p>
<pre><code class="language-python">from gurux_dlms.objects import GXDLMSActivityCalendar, GXDLMSSingleActionSchedule
from gurux_dlms.GXDateTime import GXDateTime
from datetime import datetime

# The Universal Safe Distant Epoch: 2099-12-31 23:59:59 (Year 2099 = 0x0833)
SAFE_DISTANT_EPOCH = GXDateTime(datetime(2099, 12, 31, 23, 59, 59))

def park_single_action_schedule_universal(client, reader, obis="0.0.15.0.0.255"):
    sas = GXDLMSSingleActionSchedule(obis)
    # 1. Try standard empty array first
    try:
        sas.executionTime = []
        reader.write(sas, 2)
        print(f"[+] Class 22 {obis} cleared via empty array.")
    except Exception as err:
        # 2. Fallback to Universal Distant Epoch if meter rejects empty array
        print(f"[!] Meter rejected empty array (err: {err}). Falling back to safe distant epoch...")
        sas.executionTime = [SAFE_DISTANT_EPOCH]
        reader.write(sas, 2)
        print(f"[+] Class 22 {obis} successfully parked at 2099-12-31 23:59:59.")

def park_activity_calendar_passive_time(client, reader, obis="0.0.13.0.0.255"):
    calendar = GXDLMSActivityCalendar(obis)
    calendar.time = SAFE_DISTANT_EPOCH
    reader.write(calendar, 4) # Write Attribute 4 (activate_passive_calendar_time)
    print(f"[+] Class 20 {obis} passive activation parked at 2099-12-31 23:59:59.")
</code></pre>
<h3>Summary Golden Rules for DLMS Schedule Management:</h3>
<ol>
<li><strong>Never use <code>0xFF</code> across all time bytes to disable</strong>: In DLMS Blue Book Section 4.1.6.1, <code>0xFF</code> is a wildcard that triggers continuous 1Hz execution.</li>
<li><strong>Never use past timestamps (<code>2000-01-01</code> or all zeros)</strong>: Flawed RTOS schedulers treat past timestamps as expired alarms and execute immediately upon <code>SET</code>.</li>
<li><strong>Avoid Year 9999</strong>: Exceeds 32-bit signed Unix epoch ($2^{31}-1$) and overflows into negative timestamps (Year 1911).</li>
<li><strong>Empty array <code>01 00</code> is valid on most devices, but rejected on ~15% of legacy models</strong>: Always support fallback to a valid distant future timestamp.</li>
<li><strong>Universal Bulletproof Standard</strong>: Writing a confirmed valid distant future timestamp (e.g. <code>2099-12-31 23:59:59</code> / <code>0x0833 0x0C 0x1F FF 0x17 0x3B 0x3B 0x00 0x8000 0x00</code> or <code>2100-01-01 00:00:00</code>) is 100% compliant and accepted across all vendor meters without side effects.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/159</link><guid isPermaLink="true">https://dlms.sharur.org/post/159</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:11:39 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:34 GMT]]></title><description><![CDATA[<p dir="auto">Here is the verified, working <code>SET-Request</code> trace for setting <code>0.0.13.0.0.255</code> Attribute 4 (<code>activate_passive_calendar_time</code>) to <code>2099-12-31-FF 23:59:59</code> over TCP 4059 with Security Suite 1:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 23 DB 08 53 48 41 00 00 00 00 01 30 00 00 00 45 B2 11 90 EE 44 19 82 77 1B C0 C3 01 C1 00 14 00 00 0D 00 00 FF 04 09 0C 08 33 0C 1F FF 17 3B 3B 00 80 00 00
</code></pre>
<p dir="auto">And here is the meter's successful <code>SET-Response-Normal</code>:</p>
<pre><code class="language-hex">00 01 00 01 00 01 00 15 DB 08 53 48 41 00 00 00 00 01 30 00 00 00 4A C4 88 12 90 AA 34 11 02 C5 01 C1 00
</code></pre>
<p dir="auto">Dissecting the plain response:</p>
<ul>
<li><code>C5 01</code>: <code>SET-Response-Normal</code></li>
<li><code>C1</code>: Invoke-ID <code>1</code></li>
<li><code>00</code>: <code>data-access-result: success</code></li>
</ul>
<p dir="auto">With Year 2099 encoded as <code>0x0833</code> and deviation as <code>0x8000</code>, the meter accepts the passive calendar time without scheduling false alarms or 1Hz execution storms.</p>
]]></description><link>https://dlms.sharur.org/post/158</link><guid isPermaLink="true">https://dlms.sharur.org/post/158</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:34 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:11:38 GMT]]></title><description><![CDATA[<p dir="auto">Elena here. Sarah is completely right—in our meter interoperability lab, we found that ~15% of deployed meter models reject the empty array <code>0x01 0x00</code> on Class 22, and for <strong>Class 20 (<code>Activity Calendar</code>, OBIS <code>0.0.13.0.0.255</code>)</strong>, Attribute 4 (<code>activate_passive_calendar_time</code>) is a mandatory single 12-byte <code>Octet-String</code> that cannot be empty anyway!</p>
<h3>The Universal Golden Standard: Writing a Confirmed Distant Future Timestamp (2099 / 2100)</h3>
<p dir="auto">Whether targeting Class 20 (Activity Calendar) or Class 22 (Single Action Schedule), the <strong>most robust, cross-vendor, fail-safe solution</strong> is setting a confirmed valid distant future date:</p>
<h3>Recommended Timestamp: <code>2099-12-31-FF 23:59:59.00 (UTC not specified)</code></h3>
<pre><code class="language-hex">09 0C 08 33 0C 1F FF 17 3B 3B 00 80 00 00
</code></pre>
<p dir="auto"><em>(Alternatively, <code>2100-01-01-FF 00:00:00</code> -&gt; <code>09 0C 08 34 01 01 FF 00 00 00 00 80 00 00</code>)</em></p>
<h3>Why a Safe Distant Epoch (Year 2099/2100) is Universally Superior:</h3>
<ol>
<li><strong>100% Schema Acceptance</strong>: Conforms to standard 12-byte <code>date_time</code> Octet-String format, passing schema validators on all meters (even those rejecting empty arrays).</li>
<li><strong>Safe from 32-bit Unix Overflow</strong>: Year 2099/2100 fits safely within 32-bit unsigned epoch ranges ($&lt; 2^{32} - 1 = 4{,}294{,}967{,}295$), avoiding the Year 9999 negative wraparound.</li>
<li><strong>Zero False Triggers</strong>: Pushes the trigger 70+ years beyond the physical operational lifespan of the meter.</li>
<li><strong>No 1Hz Storms</strong>: All time components (Month, Day, Hour, Min, Sec) are explicit non-wildcard values, preventing 1-second periodic matching.</li>
</ol>
]]></description><link>https://dlms.sharur.org/post/157</link><guid isPermaLink="true">https://dlms.sharur.org/post/157</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:11:38 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:11:38 GMT]]></title><description><![CDATA[<p dir="auto">For <strong>Class 22 (<code>Single Action Schedule</code>, OBIS <code>0.0.15.0.0.255</code>)</strong>, the DLMS standard provides architectural mechanisms to disable execution, but there is a major cross-device firmware defect to watch out for:</p>
<p dir="auto">Per <strong>DLMS Blue Book Ed. 17 Section 4.4.4</strong> and <strong>IEC 62056-62 Table 24</strong>, Interface Class 22 defines:</p>
<ul>
<li><strong>Attribute 2</strong>: <code>execution_time</code> (Array of <code>date_time</code> octet-strings)</li>
<li><strong>Attribute 4</strong>: <code>execution_type</code> (Enum)</li>
</ul>
<h3>Theoretical Disabling Methods vs Real-World Firmware Defects:</h3>
<ol>
<li><strong>Method A (Empty Array <code>01 00</code> per standard)</strong>: Theoretically, writing an empty array (<code>0x01 0x00</code>) to Attribute 2 <code>execution_time</code> clears all scheduled triggers.</li>
<li><strong>The Real-World Device Defect</strong>: On many legacy firmware builds and strict schema validators (especially meters enforcing fixed-capacity static array descriptors <code>min_entries &gt;= 1</code>), writing <code>0x01 0x00</code> is rejected with <code>data-access-result: type-mismatch</code> (<code>0x03</code>) or <code>temporary-failure</code> (<code>0x02</code>), making it impossible to clear via empty array on those specific devices!</li>
<li><strong>Method B (Execution Type Enum)</strong>: Setting Attribute 4 to <code>0</code> (<code>disabled</code>) or <code>5</code> (<code>inactive</code>) also encounters firmware variance where Attribute 4 is read-only.</li>
</ol>
<p dir="auto">Therefore, relying exclusively on <code>0x01 0x00</code> fails on non-standard hardware. What is the single universal method that succeeds across 100% of devices?</p>
]]></description><link>https://dlms.sharur.org/post/156</link><guid isPermaLink="true">https://dlms.sharur.org/post/156</guid><dc:creator><![CDATA[sarah_jenkins]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:11:38 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:25 GMT]]></title><description><![CDATA[<p dir="auto">Yes! Alex and David, that perfectly explains the firmware split we observed:</p>
<ol>
<li>Meter Batch A (running firmware <code>v2.4.0</code>) had the signed 32-bit <code>time_t</code> overflow. When we sent Year 9999, it overflowed to Year 1911 and triggered the disconnect breaker instantly.</li>
<li>Meter Batch B had strict Blue Book A-XDR validation on Byte 10-12 and rejected <code>FF FF...</code> because Byte 10-11 was set to <code>0xFFFF</code> instead of standard <code>0x8000</code> (not specified).</li>
<li>When we sent <code>FF FF FF FF FF FF FF FF FF 80 00 00</code>, Batch A went into the 1Hz execution loop and clicked the internal load-shedding relay 60 times a minute until the power supply brownout occurred!</li>
</ol>
<p dir="auto">Given these vendor traps, what is the exact, standard-compliant way to disable or safely park a schedule for both Class 20 (Activity Calendar) and Class 22 (Single Action Schedule)?</p>
]]></description><link>https://dlms.sharur.org/post/155</link><guid isPermaLink="true">https://dlms.sharur.org/post/155</guid><dc:creator><![CDATA[carlos_mendez]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:25 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:23 GMT]]></title><description><![CDATA[<p dir="auto">From the security and APDU framing perspective, there is also a critical validation detail in the <code>date_time</code> Octet-String format.</p>
<p dir="auto">Per <strong>DLMS Green Book 10th Ed Section 9.2.5.3</strong> and <strong>IEC 62056-53 Section 8.4.2</strong>, when writing <code>date_time</code> objects over Security Suite 1 (<code>0xDB</code> General-Glo-Ciphering), the APDU contains an explicit 12-byte <code>Octet-String</code> (Tag <code>0x09 0x0C</code><img src="https://dlms.sharur.org/assets/plugins/nodebb-plugin-emoji/emoji/android/1f61e.png?v=666d1e6b6e4" class="not-responsive emoji emoji-android emoji--disappointed" style="height:23px;width:auto;vertical-align:middle" title="):" alt="😞" /></p>
<pre><code class="language-hex">09 0C [YY YY] [MM] [DD] [WD] [hh] [mm] [ss] [hd] [TZ_H] [TZ_L] [Status]
</code></pre>
<p dir="auto">If the client sends invalid Daylight Saving Time status bits in Byte 12 (e.g. setting Bit 7 without configuring <code>daylight_savings_begin</code> in Class 8, OBIS <code>0.0.1.0.0.255</code>), or invalid timezone deviation bytes (Bytes 10-11 != <code>0x8000</code> and outside <code>[-720, +720]</code>), a compliant COSEM parser must reject the <code>SET-Request</code> with:<br />
<code>data-access-result: type-mismatch</code> (<code>0xC5 0x01 C1 03</code>) or <code>hardware-fault</code> (<code>0xC5 0x01 C1 01</code>).</p>
<p dir="auto">Carlos, did the meters that threw <code>temporary-failure</code> have strict timezone validation enabled in their COSEM stack?</p>
]]></description><link>https://dlms.sharur.org/post/154</link><guid isPermaLink="true">https://dlms.sharur.org/post/154</guid><dc:creator><![CDATA[alex_turner]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:23 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:21 GMT]]></title><description><![CDATA[<p dir="auto">A common workaround that utilities attempt when they realize past dates fire immediately is to write an extreme far-future year, such as <strong>Year 9999</strong> (<code>0x270F-12-31-FF 23:59:59 00 80 00 00</code>), hoping to push execution beyond the operational life of the meter.</p>
<p dir="auto">However, Year 9999 introduces a catastrophic 32-bit integer overflow bug:</p>
<p dir="auto">Most smart meter microcontrollers (such as ARM Cortex-M4 or Renesas RL78) implement standard POSIX <code>time_t</code> as a <strong>signed 32-bit integer</strong>:<br />
Max 32-bit Unix Epoch: 2^31 - 1 = 2,147,483,647 =&gt; 2038-01-19 03:14:07 UTC</p>
<p dir="auto">When Year 9999 (<code>0x270F</code>) is converted to Unix epoch seconds (~253,402,300,799), the 32-bit integer overflows into a negative value (~ -1,845,128,833). In two's complement, this represents a date in Year <strong>1911</strong>!</p>
<p dir="auto">Because the negative epoch is less than current_rtc_epoch, the firmware immediately falls back into the 'past timestamp' trap that Elena described, firing the script instantaneously upon <code>SET-Request</code>!</p>
]]></description><link>https://dlms.sharur.org/post/153</link><guid isPermaLink="true">https://dlms.sharur.org/post/153</guid><dc:creator><![CDATA[david_miller]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:21 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:18 GMT]]></title><description><![CDATA[<p dir="auto">Sarah's explanation of the <code>0xFF</code> wildcard matching is 100% accurate. Now let's address why writing all zeros (<code>0000-00-00</code>) or past timestamps triggers immediate execution upon <code>SET</code>:</p>
<p dir="auto">In embedded RTOS firmware, the scheduler task evaluates task queues using comparative delta timestamps:</p>
<pre><code class="language-c">// Typical flawed firmware scheduler check:
if ((int32_t)(current_rtc_epoch - task-&gt;scheduled_epoch) &gt;= 0 &amp;&amp; !task-&gt;executed_flag) {
    execute_script(task-&gt;script_logical_name, task-&gt;script_selector);
    task-&gt;executed_flag = true;
}
</code></pre>
<p dir="auto">When a past date (e.g. <code>2020-01-01</code> or zeroed date) is written, <code>current_rtc_epoch - task-&gt;scheduled_epoch</code> is a positive number (delta_t &gt; 0). If the firmware clears <code>executed_flag</code> upon receiving the <code>SET-Request</code> without checking whether the newly written timestamp is already in the past, the scheduler evaluates delta_t &gt;= 0 as an expired alarm that needs immediate catch-up execution!</p>
<p dir="auto">Furthermore, per <strong>DLMS Blue Book Ed. 17 Section 4.1.6.1 Table 6</strong>, <code>Year = 0x0000</code> is illegal in Gregorian calendar conversions and causes standard C library functions (such as <code>mktime()</code>) to return <code>(time_t)-1</code>, triggering invalid epoch exceptions.</p>
]]></description><link>https://dlms.sharur.org/post/152</link><guid isPermaLink="true">https://dlms.sharur.org/post/152</guid><dc:creator><![CDATA[elena_rostova]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:18 GMT</pubDate></item><item><title><![CDATA[Reply to Why does setting DLMS execution_time (Class 22 / Class 20) with wildcards 0xFF or 0x00 trigger continuous 1Hz firing or 32-bit overflow bugs? on Sat, 22 Aug 2026 17:01:16 GMT]]></title><description><![CDATA[<p dir="auto">Carlos, your operators' assumption that <code>0xFF</code> means 'disabled' in a COSEM <code>date_time</code> octet-string directly contradicts the standard.</p>
<p dir="auto">Per <strong>DLMS Blue Book Ed. 17 Section 4.1.6.1 (Date and Time Formats)</strong> and <strong>IEC 62056-62 Section 6.2.19 (Single Action Schedule)</strong>, a 12-byte <code>date_time</code> octet-string is defined as:</p>
<pre><code class="language-text">Byte 1-2: Year (High/Low) - 0xFFFF = not specified (wildcard: any year)
Byte 3:   Month           - 0xFF   = not specified (wildcard: every month)
Byte 4:   Day of month    - 0xFF   = not specified (wildcard: every day)
Byte 5:   Day of week     - 0xFF   = not specified (wildcard: any weekday)
Byte 6:   Hour            - 0xFF   = not specified (wildcard: every hour)
Byte 7:   Minute          - 0xFF   = not specified (wildcard: every minute)
Byte 8:   Second          - 0xFF   = not specified (wildcard: every second)
Byte 9:   Hundredths      - 0xFF   = not specified
Byte 10-11: Deviation     - 0x8000 = not specified
Byte 12:  Clock Status    - 0x00
</code></pre>
<p dir="auto">In DLMS pattern matching, <code>0xFF</code> is a <strong>Wildcard</strong> (meaning <em>MATCH ALL</em>). When every byte is set to <code>0xFF</code>, the meter's cron/scheduler evaluates:<br />
Condition: (current_year == wildcard) AND (current_second == wildcard) =&gt; TRUE</p>
<p dir="auto">Because the condition evaluates to TRUE on every 1-second RTC tick, the scheduler fires the linked script action every second! Setting <code>0xFF</code> across all fields creates an unconstrained periodic timer, not a disabled state.</p>
]]></description><link>https://dlms.sharur.org/post/151</link><guid isPermaLink="true">https://dlms.sharur.org/post/151</guid><dc:creator><![CDATA[sarah_jenkins]]></dc:creator><pubDate>Sat, 22 Aug 2026 17:01:16 GMT</pubDate></item></channel></rss>