From f839541d0843d90adc13df806f125ebea59bcd9a Mon Sep 17 00:00:00 2001 From: serversdown Date: Fri, 25 Sep 2026 00:55:54 -0400 Subject: [PATCH] docs(series4): CORRECT the schedule record -- [6] is the Action bitmask, not [0] A five-entry schedule (start/stop/self-check/start/ACH) overturns the two previous readings of this record, and the operator supplied a Thor screenshot of the schedule as ground truth. [6] is the Action, and the values are powers of two: 2 = Start Monitoring 4 = Stop Monitoring 8 = Self Check 16 = Auto Call Home Bits 1-4 of a bitmask; bit 0 (value 1) is unobserved -- a natural home for the setup-less DUTYCYCLE_START_MONITOR, but that is a guess. Two retractions: * [6] was recorded as "the one unidentified field" and predicted to be the Repeat flag. It is the Action. * [0] was labelled Action, then "Action with repeat folded in". Both wrong. [0] is non-zero only on record 0 -- records 0 and 3 here are the SAME action with different [0] values. It is a schedule-level field carried in the first record, holding Repeat: 3 on, 2 off, matching "Repeat Daily: Disabled" on the Thor screen. The earlier repeat capture was consistent with both readings because it had one start entry and moved one byte. A single-variable test is not always enough; it took four distinct actions to separate the fields. SUB 0x47 is confirmed as the scheduler enable. Previously recorded as "genuinely undetermined" whether it sets or reads -- Thor's notification pane timestamps it: schedule write completes 00:51:29, "successfully SENT" 00:51:31, the 0x47 pair at 00:51:31 and 00:51:33, "successfully ENABLED" 00:51:35. Nothing else sits between the two notifications. params[7] in {1,3} is still open and is more likely a selector than a value, since a lone params[7]=3 also appears at session start. It must be DLE-escaped -- a bare 0x03 truncates the frame. SECOND RETRACTION: setups ARE written as raw .MMB files. This document twice said they are not. Thor used both paths in one session, choosing by whether the setup is active: TEST1.mmb (active) 0xDA -> 0x68/0x73 -> 0x82/0x83 -> 0x71/0x72 test2.mmb (not active) 0x8D \system\setups\test2.mmb -> 0x8E (2192 B) The .MMB file is nearly the compliance block -- 1968/2086 bytes equal (94.3%) at a 4-byte shift, 102 bytes longer, name at offset 38 vs 42. Same structure, different framing. Writing a setup as a file is the cleaner path for SFM: two frames, no 0xDA/0x68/0x82 ritual, and it does not disturb the active setup. Also: file writes are chunked. The schedule's 1,304 bytes went as 1,024 + 280 with each offset = that chunk's length, but the 2,192-byte setup went in one frame, so 1,024 is not a hard ceiling. Rule unexplained, recorded as observed. Capture provenance: the seismo_lab bins were empty (capture not stopped), and the session was recovered from the socat relay log again -- 38 frames each way, 0 bad checksums. That fallback has now saved two captures. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL --- docs/micromate_protocol_reference.md | 145 +++++++++++++++++++-------- 1 file changed, 101 insertions(+), 44 deletions(-) diff --git a/docs/micromate_protocol_reference.md b/docs/micromate_protocol_reference.md index 1111523..f2bda66 100644 --- a/docs/micromate_protocol_reference.md +++ b/docs/micromate_protocol_reference.md @@ -1502,16 +1502,19 @@ 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 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 +offset field size notes +[0] schedule flags 1 record 0 ONLY — 3 = repeat on, 2 = repeat off +[1:4] padding 3 zero in every record observed +[4] 1/2h 1 half-hour slot, 0–47 +[5] Day 1 3 in every record observed — undetermined +[6] Action 1 bitmask: 2 start, 4 stop, 8 self-check, 16 ACH +[7] name length 1 +[8:260] Setup name 252 null-padded; empty for actions that take no setup ``` +⚠ `[0]` and `[6]` were **mislabelled twice** before a five-entry schedule +separated them — see *CORRECTED* below. + 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"*: @@ -1546,56 +1549,110 @@ Action codes, so far: | `0` | **Auto Call Home** | | `3` | **Start monitoring, with setup** | -### The Repeat flag is folded into `Action` (2026-09-25) +### ⚠ CORRECTED — `[6]` is the Action, and it is a bitmask (2026-09-25) -A capture that changed **only** the *Repeat Daily* checkbox — schedule pulled, -repeat disabled, schedule pushed — moved **exactly one byte in the whole -session**: +A five-entry schedule settled this, and it **overturns the two previous +readings of this record.** The operator's Thor screen, captured alongside: ``` -record @0 Action 0x03 → 0x02 (repeat ON → repeat OFF) +actioncheck — Micromate — Repeat Daily: Disabled + 7:30 AM Start Monitoring TEST1 + 8:00 AM Stop Monitoring + 8:30 AM Self Check + 9:00 AM Start Monitoring test2 + 7:30 PM Auto Call Home ``` -Nothing else moved. Record 2 unchanged, `[6]` unchanged, and `0xDA`, `0x68`, -`0x82`, `0x71`, `0x94`, `0x8D` all byte-identical. +Five entries, and the file holds exactly five 260-byte records: -⚠ So **`[6]` is NOT the repeat flag** — the field predicted for that test is still -unidentified. And the earlier label on `[0]` was too simple: it is not a plain -action index, it carries the repeat behaviour too. +| rec | `[0]` | `1/2h` | `Day` | **`[6]`** | len | name | +|---|---|---|---|---|---|---| +| @0 | **2** | 15 = 07:30 | 3 | **2** | 9 | `TEST1.mmb` | +| @260 | 0 | 16 = 08:00 | 3 | **4** | 0 | | +| @520 | 0 | 17 = 08:30 | 3 | **8** | 0 | | +| @780 | 0 | 18 = 09:00 | 3 | **2** | 9 | `test2.mmb` | +| @1040 | 0 | 39 = 19:30 | 3 | **16** | 0 | | -**Leading hypothesis** — `2` and `3` are the two *setup-bearing start* actions the -firmware names, and repeat selects between them: +**`[6]` tracks the action exactly, and the values are powers of two:** -| value | action | why | -|---|---|---| -| `0` | `DUTYCYCLE_CALLHOME` | the 19:30 entry, no setup name | -| `2` | `DUTYCYCLE_START_MONITOR_WITH_SETUP` | repeat **off** | -| `3` | `DUTYCYCLE_START_MONITOR_WITH_SETUP_STOP_COMPLETE` | repeat **on** | +| `[6]` | action | +|---|---| +| `2` | Start Monitoring | +| `4` | Stop Monitoring | +| `8` | Self Check | +| `16` | Auto Call Home | -That reading is supported by the THOR manual's description of what a *repeating* -schedule does on hitting a Start Monitoring event while already monitoring: +Bits 1–4 of a bitmask. **Bit 0 (value `1`) is unobserved** — a natural home for +the setup-less `DUTYCYCLE_START_MONITOR`, but that is a guess, not a finding. -> *"the unit will stop the current monitoring session, run any Auto Call Home -> actions, load the compliance setup and continue monitoring."* +**Two retractions:** -Which is precisely what a name ending `_STOP_COMPLETE` would mean: a repeating -start has to terminate the in-progress session first, a one-shot start does not. -The firmware action name, the manual's behaviour, and the single byte that moved -all agree. +1. `[6]` was recorded as *"the one unidentified field"* and predicted to be the + Repeat flag. It is the **Action**. +2. `[0]` was labelled **Action**, then *"Action with repeat folded in"*. Both + wrong. `[0]` is **non-zero only on record 0** — including here, where record + 0 and record 3 are the same action with different `[0]` values. It is a + **schedule-level field carried in the first record**, and it holds the Repeat + flag: `3` repeat on, `2` repeat off, matching *"Repeat Daily: Disabled"* on + the screen. -⚠ **The enum's ordering is NOT known.** The action names were recovered with -`strings | sort`, so their source order is lost — do **not** infer that `1` is -`DUTYCYCLE_START_MONITOR` merely because it sits between the two known values, -tempting as that is. Three of six codes are observed (`0`, `2`, `3`); the -remaining three need entries that use those actions. +The earlier repeat capture was consistent with both readings because it had one +start entry and changed one byte. A single-variable test is not always enough — +it took a schedule with four distinct actions to separate the two fields. -⚠ Note also that Thor re-pushed the **entire 2,090-byte config block** for a -one-byte schedule change — a third instance of the coupling described in -*The schedule↔config coupling is Thor's, not the protocol's*. +`Day` is `3` on all five records across every capture. Still undetermined. -⚠ 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. +### ✅ `SUB 0x47` is the scheduler enable — confirmed by Thor's own notifications + +Previously recorded as *"genuinely undetermined"* whether `0x47` sets or reads. +Thor's notification pane timestamps it: + +``` +00:51:29 schedule write (0x8E) completes +00:51:31 Thor: "actioncheck has been successfully SENT to ... UM12947" +00:51:31 → 0x47 params[7] = 0x01 +00:51:33 → 0x47 params[7] = 0x03 (on the wire as 10 03 — DLE-escaped) +00:51:35 Thor: "actioncheck was successfully ENABLED on ... UM12947" +``` + +The only frames between *sent* and *enabled* are the `0x47` pair. **`0x47` +performs the enable.** + +⚠ The meaning of `params[7]` ∈ {1, 3} is still open — a single `0x47` with +`params[7] = 3` also appears at *session start*, where nothing is being enabled, +so the byte is more likely a selector than a value. Note it must be +**DLE-escaped**: a bare `0x03` in params truncates the frame at what the device +reads as ETX. + +### 🔑 Setups ARE written as raw `.MMB` files — second retraction + +This document twice stated that setups are *not* pushed as raw `.MMB` blobs and +go only through `0xDA` + the config block. **Wrong.** In this session Thor did +both, choosing by whether the setup is the active one: + +| setup | how it was written | +|---|---| +| `TEST1.mmb` (**active**) | `0xDA` → `0x68`/`0x73` → `0x82`/`0x83` → `0x71`/`0x72` | +| `test2.mmb` (not active) | `0x8D` `\system\setups\test2.mmb` → `0x8E` (2,192 B) | + +So **`\system\setups\.mmb`** is the setup directory, and the generic file +transfer writes there directly. + +The `.MMB` file is *nearly* the compliance block: aligning the two gives +**1,968 / 2,086 bytes equal (94.3%) at a 4-byte shift**. The file is 102 bytes +longer (2,192 vs 2,090) and puts the setup name at offset 38 where the `0x71` +block has it at 42. So the on-disk setup and the wire compliance block are the +same structure with different framing — not two formats. + +**This is the cleaner path for SFM.** Writing a setup as a file needs two frames +and no `0xDA`/`0x68`/`0x82` ritual, and it does not disturb the active setup. + +### File writes are chunked + +The schedule's 1,304 bytes went as **two `0x8E` frames, 1,024 + 280**, each with +`offset` = that chunk's own length. The 2,192-byte setup file went in **one** +frame, so 1,024 is not a hard ceiling — the chunking rule is unexplained and +recorded as observed. ### Six duty-cycle actions, not five