docs(series4): the ACH session, from the THOR manual -- and I was asking the wrong question
Brian uploaded the Instantel manuals (gitignored, manuals/). The THOR Operator
Manual Rev 08 settles the thing this document called the blocker for a homebrew
receiver.
I had written that what gates a receiver is "how it learns an event was accepted
so it stops re-sending it." There is no such mechanism to find, because the unit
does not track it. Per THOR manual 6.2.2.2 an ACH session is a list of
SERVER-chosen actions -- Copy events, Copy monitor log, Delete events and Logs
from Unit, Set Date/Time -- and "Only applies to events not previously
downloaded" is computer-side bookkeeping. The manual's own warning proves copy
and delete are decoupled: enable delete but disable copy and "the events and logs
will be deleted without being uploaded."
That is exactly the model our Series III ACH server already implements
(ach_state.json high-water mark, erase as a deliberate separate step). No new
mechanism is needed for Series IV. A receiver needs: accept, identify, walk the
events (already solved), keep our own high-water mark, optionally erase. The
ERASE OPCODES are now the only genuinely missing piece and stay on the unsafe
list.
Other things the manual settles:
* The session is server-driven, matching the firmware state machine. Scheduled
and event-triggered ACH differ: with Monitoring While Calling Home enabled, an
event-triggered session will NOT delete events or sync time. So a receiver
that relies on erase to avoid re-reading would silently never erase on those
units -- the high-water mark has to be primary, erase an optimisation.
* Session Time Out is unit-side only, which places it in callhome.MMB -- another
reason to read that file with 0x94.
* Units are routed by serial number with wildcards, so the serial is presented
early enough for a server to dispatch on it.
* THOR requires Idle for ACH setup too, confirming the greyed-out send is
deliberate policy rather than a device refusal.
* THOR exposes four schedule actions; the firmware has five. 6.3.2 step 8
("A Unit Setup must exist") is THOR's own requirement, while the same section
says the unit "will execute any actions in a schedule using its current
settings" -- the two pull opposite ways, consistent with START_MONITOR
existing and THOR never emitting it.
* Schedule fields to look for when the entry is decoded: action, setup name,
time, day-or-week, day selection, repeat. The captured entry has seven bytes
before the name, the right order of magnitude for that list.
Flagged: the manual's filter example contradicts its own table (it has UM* and MP*
backwards). The table is right.
Marked throughout as vendor documentation rather than observed bytes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
This commit is contained in:
@@ -1301,6 +1301,125 @@ Worth noting the histogram (`…81`) and the loudest waveform (`…84`) report
|
||||
the histogram's single 1-minute interval spans the whole thumping session, so
|
||||
its maximum should equal the loudest event in it.
|
||||
|
||||
## What the THOR manual settles about the ACH session (2026-09-24)
|
||||
|
||||
Source: `manuals/723U0201 THOR Operator Manual Rev 08.pdf` §6.2, §3.6.
|
||||
⚠ **This is vendor documentation, not observed bytes.** It tells us the shape of
|
||||
the session and the vocabulary; it does not give opcodes. Treated as a strong
|
||||
prior, not as confirmed protocol.
|
||||
|
||||
### 🔑 A unit does NOT learn that an event was accepted — the server decides
|
||||
|
||||
This document previously listed, as the thing *gating any homebrew receiver*:
|
||||
|
||||
> how a unit announces itself, and **how it learns an event was accepted so it
|
||||
> stops re-sending it.**
|
||||
|
||||
**That was the wrong question.** There is no acknowledgement mechanism to
|
||||
discover, because the unit is not tracking what has been collected. Per §6.2.2.2
|
||||
the ACH session is a list of **server-chosen actions**, and two of them are
|
||||
independent:
|
||||
|
||||
| ACH action | what it does |
|
||||
|---|---|
|
||||
| **Copy events** | downloads events — *"Only applies to events not previously downloaded"* |
|
||||
| **Copy monitor log** | downloads the monitor log |
|
||||
| **Delete events and Logs from Unit** | **explicitly** deletes them from the unit |
|
||||
| **Set Date/Time** | unit synchronises its clock **from the computer** |
|
||||
| Send Events / Schedule to Vision | Instantel cloud, not relevant to us |
|
||||
|
||||
"Not previously downloaded" is **computer-side bookkeeping**. The unit keeps its
|
||||
events until a server tells it to erase them, and the manual's own warning proves
|
||||
the two are decoupled:
|
||||
|
||||
> ⚠ *"If you enable 'Delete Events and Logs from Unit' but disable 'Copy Events'.
|
||||
> The events and logs will be deleted without being uploaded."*
|
||||
|
||||
A server that never issues the delete simply re-reads the same events forever.
|
||||
|
||||
**This is exactly the model our Series III ACH server already implements** —
|
||||
`ach_state.json` with `downloaded_keys` / `max_downloaded_key`, and erase as a
|
||||
separate deliberate step. No new mechanism is needed for Series IV.
|
||||
|
||||
So a homebrew receiver needs: accept the connection, identify the unit, walk the
|
||||
events (already solved — `0x08`/`0x1E`/`0x0A`/`0x5A`), keep our own high-water
|
||||
mark, and *optionally* erase. **The erase opcodes are the only genuinely missing
|
||||
piece**, and they remain on the unsafe list.
|
||||
|
||||
### The session is server-driven
|
||||
|
||||
Which matches the firmware's state machine and its
|
||||
`CMD_EXIT_CALL_HOME_DELETE_EVENTS_START_MONITORING` /
|
||||
`Call Home Deleting Events` strings: the unit dials in, then waits to be told
|
||||
what to do, and returns to monitoring when the server is finished.
|
||||
|
||||
Scheduled ACH and event-triggered ACH behave differently (§3.6.1):
|
||||
|
||||
- **Event-triggered** (ACH enabled on the unit, an event occurred) — *"Records
|
||||
events + transfer data, no stopping to monitor."* Governed by **Monitoring
|
||||
While Calling Home**; with MWCH enabled *"the monitor log will not be copied,
|
||||
events will not be deleted, and time will not synchronize"*.
|
||||
- **Scheduled** — *"Stop monitoring + transfer data (or delete events, or
|
||||
synchronize)."* Monitoring stops and in-progress events complete first.
|
||||
|
||||
⚠ Worth noting for SFM: with MWCH on, an event-triggered session **cannot**
|
||||
delete or sync. A receiver that relies on erase to avoid re-reading will
|
||||
silently never erase on those units. Our high-water mark must be the primary
|
||||
mechanism, with erase as an optimisation — which is how Series III already does it.
|
||||
|
||||
### Session Time Out is unit-side only
|
||||
|
||||
§6.2 is explicit that THOR configures ACH on both ends *"with one exception; the
|
||||
Session Time Out. This must be configured directly on the unit."* That matches
|
||||
the firmware's `CallHome.SessionTimeout` field, and means it lives in
|
||||
`callhome.MMB` rather than anywhere THOR reaches — one more reason to read that
|
||||
file with `0x94`.
|
||||
|
||||
### Unit identification is by serial number, with wildcards
|
||||
|
||||
§6.2.2.2: filters match against the serial number the unit presents, `*`
|
||||
wildcards allowed, best-match wins — `UM*` all Micromates, `MP*` all Minimate
|
||||
Pros, `BE`/`BC` Minimate Plus variants.
|
||||
|
||||
So **the unit announces its serial early enough for the server to route on it.**
|
||||
`SUB 0x15` returns the serial and is in Thor's standard preamble, which is
|
||||
consistent, though the inbound direction has still never been observed.
|
||||
|
||||
⚠ The manual's worked example contradicts its own table — it says *"To filter
|
||||
Micromate units type MP*"* and *"To filter Minimate Pro units type UM*"*, which is
|
||||
backwards. The table is right. Noted so nobody copies the error.
|
||||
|
||||
### Thor requires Idle for configuration
|
||||
|
||||
§6.2.1 step 3: *"The Monitoring Mode must be 'Idle'."* Independent confirmation
|
||||
that the greyed-out send observed on the bench is deliberate Thor policy, applied
|
||||
to ACH setup as well as compliance setup — and still not evidence the device
|
||||
refuses.
|
||||
|
||||
### The schedule's actions, from the UI side
|
||||
|
||||
§3.6 lists exactly **four** actions THOR exposes: Start monitoring, Stop
|
||||
monitoring, Self-check, Auto Call Home. The firmware has **five** — it also has
|
||||
a setup-less `DUTYCYCLE_START_MONITOR`.
|
||||
|
||||
§3.6.2 step 8 confirms the coupling is Thor's own requirement: *"Select the
|
||||
appropriate Action and the Unit Setup. (A Unit Setup must exist…)"* — while §3.6.2
|
||||
step 1 notes *"The unit will execute any actions in a schedule using its current
|
||||
settings."* The two statements sit a paragraph apart and pull in opposite
|
||||
directions, which is consistent with `START_MONITOR` existing and THOR never
|
||||
emitting it.
|
||||
|
||||
Also from §3.6: schedules are **Day or Week** ("Select Day… Select Week"), have a
|
||||
**Repeat Daily / Repeat Weekly** flag, carry a Name, Description and Unit Type,
|
||||
and *"Saving a schedule will only store it on the computer, it must still be sent
|
||||
to the unit and enabled"* — which is why the capture shows `0x8E` (send) and
|
||||
`0x47` (enable) as separate steps.
|
||||
|
||||
Those are the fields to look for when the schedule entry is finally decoded:
|
||||
**action, setup name, time, day-or-week, day selection, repeat.** The one
|
||||
captured entry (`03 00 00 00 0f 03 02 …`) has seven bytes before the name, which
|
||||
is the right order of magnitude for that field list.
|
||||
|
||||
## Thor's conventions vs the protocol's requirements
|
||||
|
||||
**SFM is not meant to reimplement Thor.** Thor is the only available teacher of
|
||||
@@ -1460,11 +1579,16 @@ Also unknown:
|
||||
|
||||
- Whether `0x10` bytes inside **request params** need stuffing. (Write-frame
|
||||
**data** stuffing *is* now settled — `10 XX` → `XX`; see *The write path*.)
|
||||
- Everything about the **call-home session** — the device-initiated direction
|
||||
has not been observed at all. Specifically: how a unit announces itself,
|
||||
and **how it learns an event was accepted so it stops re-sending it.**
|
||||
That last question gates any homebrew receiver and cannot be answered over
|
||||
USB.
|
||||
- The **call-home session's bytes** — the device-initiated direction has still
|
||||
not been observed at all, and cannot be over USB.
|
||||
|
||||
✅ **The second half of this item is resolved** (2026-09-24, from the THOR
|
||||
manual): "how it learns an event was accepted so it stops re-sending it" was
|
||||
the wrong question — **it does not learn.** Collection state is server-side
|
||||
bookkeeping and erase is a separate, optional, server-issued action. See
|
||||
*What the THOR manual settles about the ACH session*. What remains unknown is
|
||||
the framing of the inbound session and the **erase opcodes**, not any
|
||||
acknowledgement mechanism.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user