From 4a1cccf3f585a492facc1473fb49fdf68c74fb58 Mon Sep 17 00:00:00 2001 From: serversdown Date: Thu, 24 Sep 2026 21:40:05 -0400 Subject: [PATCH] docs(series4): the schedule file is DECODED -- two records, five confirmations The operator supplied the ground truth: entry 1 is "start monitoring TEST1" at 07:30, entry 2 is "Auto Call Home" at 19:30. That decodes the file completely. The body is two 260-byte records plus four zero bytes = 524 exactly, and every non-zero byte falls inside them: [0] Action (0 = Auto Call Home, 3 = start monitoring with setup) [1:4] padding [4] 1/2h half-hour slot, 0-47 [5] Day [6] ?? the one unidentified field [7] name length [8:260] setup name, null-padded record @ 0: Action=3 1/2h=15 -> 07:30 Day=3 [6]=2 namelen=9 "TEST1.mmb" record @260: Action=0 1/2h=39 -> 19:30 Day=3 [6]=16 namelen=0 (no setup) Five independent confirmations, no fitting: 1. Slots 15 and 39 match the stated 07:30 and 19:30 on a 30-minute grid, and 39-15 = 24 slots = exactly 12 hours. 2. The length byte reads 9 for TEST1.mmb, 40 for the long name in the read capture, and 0 for the Auto Call Home entry. 3. Auto Call Home carries NO setup name -- direct proof that a schedule entry can exist with no setup attached, which is what the earlier DUTYCYCLE_START_MONITOR finding predicted from the firmware side. 4. The 260-byte stride lands record 2's 1/2h exactly at [264]. 5. 2 x 260 + 4 = 524, the whole body, nothing left over. CORRECTION: `27 03 10` at [264] was recorded in the previous commit as a possible trailer. It is record 2's 1/2h, Day and [6] fields. I had assumed the file held one record and read the second one as padding -- the non-zero bytes were sitting there the whole time. Still open: [6] (2 on the start entry, 16 on the ACH entry -- a Repeat or Day/Week capture would isolate it), the four remaining action codes, and whether the file can hold unused record slots. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL --- docs/micromate_protocol_reference.md | 87 ++++++++++++++++++---------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/docs/micromate_protocol_reference.md b/docs/micromate_protocol_reference.md index f600869..112015f 100644 --- a/docs/micromate_protocol_reference.md +++ b/docs/micromate_protocol_reference.md @@ -1011,10 +1011,10 @@ the record mode" works: an entry says *at this time, load this setup*. It also means the scheduler and the setup list are coupled — deleting a setup that a schedule references is a foot-gun worth checking before we ever expose either. -⚠ **The entry internals are NOT decoded.** One entry, one capture, no -variation to diff against. `03 00 00 00 0f 03 02` and `27 03 10` are recorded -as observed bytes, nothing more. Decoding needs schedules that differ in a -known way — two entries, or one entry at a different time of day. +✅ **The entry internals ARE decoded** — see *The schedule record format* below. +The file turned out to hold **two** 260-byte records, not one: `27 03 10` is the +second record's time/day fields, not a trailer. `1/2h` is a half-hour slot and +both times check out against what the operator entered. ### `SUB 0x47` — the scheduler enable, probably @@ -1490,42 +1490,69 @@ other schedules — or the operator's own saved work — depend on. Nothing in protocol or the ack reports that this happened. Validating the reference instead of rewriting the referent avoids the whole class of problem. -### The schedule record format, from the firmware's own debug printf +### ✅ The schedule record format — DECODED (2026-09-24) + +A debug printf in the scheduler names the fields outright: ``` SCHEDULER : _ReadRecord(%d) -> %s (Action=%u, 1/2h=%u, Day=%u, Setup="%s") [WDAY=%d] ``` -That names the fields outright, and they fit the captured record: +The captured file is **two 260-byte records plus four zero bytes** — 524 bytes +exactly. Every non-zero byte in the file falls inside those two records. -| offset | field | read capture | write capture | -|---|---|---|---| -| `[0]` | **Action** | `03` | `03` | -| `[1:4]` | zero — padding, or `Action` is a uint32 | `00 00 00` | `00 00 00` | -| `[4]` | **1/2h** — half-hour slot | `0f` = 15 | `0f` = 15 | -| `[5]` | **Day** | `03` | `03` | -| `[6]` | unidentified (`WDAY`?) | `02` | `02` | -| `[7]` | **name length** | `0x28` = **40** | `0x09` = **9** | -| `[8:]` | **Setup** name | 40-char name | `TEST1.mmb` | -| `[264]` | trailer | `27 03 10` | `27 03 10` | +``` +offset field size notes +[0] Action 1 (or uint32 LE at [0:4] — both are zero-extended here) +[1:4] padding 3 zero in both records +[4] 1/2h 1 half-hour slot, 0–47 +[5] Day 1 3 in both records +[6] ?? 1 the one unidentified field +[7] name length 1 +[8:260] Setup name 252 null-padded +``` -**The length byte is what anchors this** — it reads 40 for the 40-character name -and 9 for `TEST1.mmb`, in the same position, in both directions. The layout is -not a guess. +Decoded against the operator's own description of what they entered — +*"start monitoring TEST1 at 7:30 AM, Auto Call Home at 7:30 PM"*: -`1/2h` implies **30-minute resolution, 48 slots per day**. Slot 15 would be -07:30 if counted from midnight — plausible but ⚠ **unconfirmed**, since the -schedule's actual time was not recorded alongside the capture. One question to -the operator settles it. +| | record @0 | record @260 | +|---|---|---| +| `Action` | **3** | **0** | +| `1/2h` | 15 → **07:30** ✅ | 39 → **19:30** ✅ | +| `Day` | 3 | 3 | +| `[6]` | 2 | 16 | +| name length | 9 | **0** | +| Setup | `TEST1.mmb` | *(none)* ✅ | -⚠ Still unknown, and all answerable with **one schedule containing two entries**: +**Five independent confirmations**, no fitting required: -- the **record stride** and how many records the file holds (one record was - captured; `27 03 10` at `[264]` may be a trailer or a second record's head) -- whether `Action` is one byte or a uint32 -- the **action code values** — `03` is presumably - `DUTYCYCLE_START_MONITOR_WITH_SETUP` but the enum's base is unknown -- `[6]`, and how `Day` and `WDAY` divide the work +1. Slot 15 = 07:30 and slot 39 = 19:30, both matching the operator's stated + times, on a 30-minute grid — and 39 − 15 = 24 slots = exactly 12 hours. +2. The name-length byte reads 9 for `TEST1.mmb`, 40 for the 40-character name in + the read capture, and **0** for the Auto Call Home entry. +3. **Auto Call Home carries no setup name** — which is what it should do, and + direct proof that a schedule entry can exist with no setup attached. +4. The 260-byte stride lands the second record's `1/2h` exactly at `[264]`. +5. `2 × 260 + 4 = 524`, the whole body, with nothing left over. + +⚠ **Correction:** the `27 03 10` bytes at `[264]` were previously recorded here as +a possible trailer. They are **record 2's `1/2h`, `Day` and `[6]` fields**. Not +a trailer — a second record hiding behind an assumption that the file held one. + +Action codes, so far: + +| value | action | +|---|---| +| `0` | **Auto Call Home** | +| `3` | **Start monitoring, with setup** | + +⚠ `[6]` is the one field still unidentified — `2` on the start entry, `16` on the +Auto Call Home entry. It is not the name length and not the time. A capture +that changes only the **Repeat** checkbox, or switches Day↔Week, would isolate it. + +⚠ Also still unknown: whether the file can hold more than the records in use +(both captures had every used record contiguous from offset 0), and the remaining +four action codes. ### Six duty-cycle actions, not five