docs: update protocol reference with v0.9.0 erase-all protocol

Changelog section:
- 5 new entries (2026-04-11): erase-all confirmation, SUB 0x06 purpose
  resolved, §7.11 added, §14.6 ACH session lifecycle marked IMPLEMENTED

§5.1 Request Commands:
- SUB 0x06 description updated: "EVENT STORAGE RANGE READ" (not "CHANNEL
  CONFIG READ"), token=0xFE, last 8 bytes = first/last stored event keys
- SUB 0xA3 added: ERASE ALL BEGIN — standard build_bw_frame, token=0xFE, ack 0x5C
- SUB 0xA2 added: ERASE ALL CONFIRM — standard build_bw_frame, token=0xFE, ack 0x5D

§5.2 Response SUBs:
- 0x06→0xF9 marked CONFIRMED 2026-04-11
- 0xA3→0x5C and 0xA2→0x5D added with CONFIRMED status

§7.11 (new section): Erase-All Protocol
- Full wire sequence (6 request/response pairs)
- SUB 0x06 storage range payload layout (36 bytes, last 8 = first/last key)
- Post-erase key counter reset: device restarts from 0x01110000
- Implementation notes pointing to client.py and ach_server.py

§14.6 ACH Session Lifecycle:
- Removed "Future" label — fully implemented in bridges/ach_server.py
- Added step 6 (optional erase), step 8 (DCD/DTR auto-resume)
- Documents ach_server.py flags and ach_state.json schema
- Notes RV55 DCD/DTR issue as known open problem

Open Questions table:
- SUB 0x06 purpose RESOLVED
- Erase-all sequence RESOLVED
- ACH server RESOLVED
- Sensor Check byte: still open, added as formal question
- RV55 DCD/DTR: added as new open question

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-11 01:20:43 -04:00
committed by serversdown
parent f6a0846bab
commit 6acb419ebd
+108 -6
View File
@@ -99,6 +99,10 @@
| 2026-04-08 | §7.10 | **NEW — SUBs 0x15 and 0x01 observed in sensor-check capture.** SUB 0x15 (serial number short form, data length 0x0A, RSP 0xEA) and SUB 0x01 (device info block, data length 0x98 = 152 bytes, RSP 0xFE) seen in Blastware's "Unit Channel Test" init sequence. Note: SUB 0x01 response SUB 0xFE collides with the existing SUB 0xFE → RSP 0x01 naming convention — they are inverse commands. |
| 2026-04-08 | §12 | **CONFIRMED — Unit partially reachable during on-device sensor check.** 4-8-26/sensor-check capture shows: POLL responds normally throughout; SUB 0x0E channel reads partially served (channels 04 responded), then ~40s silent gap while sensor check ran, then channels 57 responded. On-device sensor check duration ≈ 40 s. SFM `_pollMonitorConfirm()` polls status every 5 s for up to 60 s after start_monitoring. |
| 2026-04-08 | §7.9 (NEW) | **NEW — Compliance config field inventory captured from Blastware UI.** See §7.9 for full field list (Recording Setup, Notes, Special Setups tabs). Most fields NOT yet mapped to raw byte offsets. Confirmed decoded: sample_rate, record_time, trigger_level_geo, alarm_level_geo, max_range_geo, backlight_on_time, power_saving_timeout, monitoring_lcd_cycle, project/client/operator/sensor_location/notes. Sensor Check dropdown (Before monitoring / After each event / Disabled) NOT YET LOCATED in raw config bytes. |
| 2026-04-11 | §5.1, §5.2 | **NEW — Erase-all command sequence confirmed from MITM capture.** SUB 0xA3 (begin erase, token=0xFE → ack 0x5C) + SUB 0xA2 (confirm erase, token=0xFE → ack 0x5D). Standard `build_bw_frame` format (not write-format). Required intermediate steps: 0x1C probe+data (monitor status read) + 0x06 probe+data (event storage range). All response SUBs follow the standard 0xFFSUB formula with no exceptions. |
| 2026-04-11 | §5.1 | **CONFIRMED — SUB 0x06 (CHANNEL CONFIG READ) now confirmed as event storage range.** Two-step read, data offset = 0x24 (36 bytes). Token=0xFE at params[7]. Last 8 bytes of response: first stored event key (bytes 8:4) and last stored event key (bytes 4:). Both equal `01110000` when device memory is empty. Used by Blastware to verify erase completion. |
| 2026-04-11 | §7.11 (NEW) | **NEW — §7.11 Erase-All Protocol added.** Full wire sequence, SUB 0x06 storage range payload layout, post-erase key counter reset (resets to `0x01110000`). Confirmed from 4-11-26 MITM capture of live Blastware ACH session. |
| 2026-04-11 | §14.6 | **RESOLVED — ACH Session Lifecycle is no longer "Future".** `bridges/ach_server.py` fully implements inbound ACH: POLL handshake, device info, event download. State tracked via `ach_state.json` (key-based, with `max_downloaded_key` for post-erase detection). `--clear-after-download` flag added for the standard delete-after-upload workflow. |
---
@@ -243,7 +247,7 @@ Step 4 — Device sends actual data payload:
| `15` | **SERIAL NUMBER REQUEST** | Requests device serial number. | ✅ CONFIRMED |
| `01` | **FULL CONFIG READ** | Requests complete device configuration block (~0x98 bytes). Firmware, model, serial, channel config, scaling factors. | ✅ CONFIRMED |
| `08` | **EVENT INDEX READ** | Requests the event record index (0x58 bytes). Event count and record pointers. | ✅ CONFIRMED |
| `06` | **CHANNEL CONFIG READ** | Requests channel configuration block (0x24 bytes). | ✅ CONFIRMED |
| `06` | **EVENT STORAGE RANGE READ** | Requests event storage range block (0x24 = 36 bytes). Token=0xFE at params[7]. Last 8 bytes of response: first stored event key (`[-8:-4]`) and last stored event key (`[-4:]`). Both equal `01110000` when device is empty. Used by Blastware as part of the erase-all verification step. Previously labelled "CHANNEL CONFIG READ" — function now confirmed from 4-11-26 MITM capture. | ✅ CONFIRMED 2026-04-11 |
| `1C` | **TRIGGER CONFIG READ** | Requests trigger settings block (0x2C bytes). | ✅ CONFIRMED |
| `1E` | **EVENT HEADER READ** | Gets first waveform key. Token byte at params[7] (0x00=browse, 0xFE=download-arm). Key at data[11:15]; trailing offset at data[15:19] (0 = only one event). Two uses: (1) all-zero to get key0; (2) token=0xFE after 0A, before 0C — REQUIRED to arm device for SUB 5A. | ✅ CONFIRMED 2026-04-06 |
| `0A` | **WAVEFORM HEADER READ** | Checks record type for a given waveform key. Variable DATA_LENGTH: 0x30=full bin, 0x26=partial bin. Key at params[4..7]. Required before every 1F call to establish device waveform context. | ✅ CONFIRMED 2026-03-31 |
@@ -260,6 +264,8 @@ Step 4 — Device sends actual data payload:
| `1C` | **MONITOR STATUS READ** | Two-step read, data offset 0x2C (44 bytes). `section[1] == 0x10` → monitoring; `0x00` → idle (CONFIRMED 2026-04-09, 100% accuracy on 144 frames). Payload length: 4647 bytes IDLE, 4849 bytes MONITORING. `frame.data` has checksum stripped — no trailing byte to skip. Battery/memory at end: `section[-10:-8]` = battery×100 (uint16 BE), `section[-8:-4]` = memory_total (uint32 BE), `section[-4:]` = memory_free (uint32 BE). | ✅ CONFIRMED 2026-04-09 |
| `96` | **START MONITORING** | Single write frame, no data payload. Transitions unit from idle to monitoring mode (after optional on-device sensor check ~40 s). | ✅ CONFIRMED 2026-04-08 |
| `97` | **STOP MONITORING** | Single write frame, no data payload. Stops monitoring, unit returns to idle. | ✅ CONFIRMED 2026-04-08 |
| `A3` | **ERASE ALL BEGIN** | Single frame, token=0xFE at params[7]. Initiates device memory erase. Must be followed by 0x1C probe+data + 0x06 probe+data + 0xA2 to complete. Standard `build_bw_frame` (not write-format). Response ack SUB = 0x5C. | ✅ CONFIRMED 2026-04-11 |
| `A2` | **ERASE ALL CONFIRM** | Single frame, token=0xFE at params[7]. Commits the erase initiated by 0xA3. After this ack (SUB 0x5D), device memory is cleared and the event counter resets to `0x01110000`. | ✅ CONFIRMED 2026-04-11 |
All requests use CMD byte `0x02`. All responses use CMD byte `0x10 0x02` (which, after de-stuffing, is just the DLE+CMD combination — see §3).
@@ -273,7 +279,7 @@ All requests use CMD byte `0x02`. All responses use CMD byte `0x10 0x02` (which,
| `15` | `EA` | ✅ CONFIRMED |
| `01` | `FE` | ✅ CONFIRMED |
| `08` | `F7` | ✅ CONFIRMED |
| `06` | `F9` | ✅ CONFIRMED |
| `06` | `F9` | ✅ CONFIRMED 2026-04-11 |
| `1C` | `E3` | ✅ CONFIRMED 2026-04-08 |
| `1E` | `E1` | ✅ CONFIRMED |
| `0A` | `F5` | ✅ CONFIRMED |
@@ -287,6 +293,8 @@ All requests use CMD byte `0x02`. All responses use CMD byte `0x10 0x02` (which,
| `98` | `67` | ✅ CONFIRMED 2026-04-08 |
| `96` | `69` | ✅ CONFIRMED 2026-04-08 |
| `97` | `68` | ✅ CONFIRMED 2026-04-08 |
| `A3` | `5C` | ✅ CONFIRMED 2026-04-11 |
| `A2` | `5D` | ✅ CONFIRMED 2026-04-11 |
---
@@ -1386,6 +1394,77 @@ Contains serial number, firmware bytes, and floating-point calibration fields. F
---
## 7.11 Erase-All Protocol (SUBs 0xA3 / 0xA2 / 0x06) ✅ 2026-04-11
> ✅ **Confirmed 2026-04-11** from MITM capture of a live Blastware ACH session
> (`bridges/captures/mitm/ach_mitm_20260411_001912/`).
Blastware uses a 4-step sequence to erase all stored events from device memory.
All frames use standard `build_bw_frame` format (NOT write-format).
### 7.11.1 Wire Sequence
```
BW → device: SUB 0xA3 offset=0x0000 params=00 00 00 00 00 00 00 FE 00 00
device → BW: SUB 0x5C (begin-erase ack)
BW → device: SUB 0x1C offset=0x0000 params=00 00 00 00 00 00 00 FE 00 00 (probe)
device → BW: SUB 0xE3 (probe ack)
BW → device: SUB 0x1C offset=0x002C params=(same) (data)
device → BW: SUB 0xE3 (44-byte monitor status response)
BW → device: SUB 0x06 offset=0x0000 params=00 00 00 00 00 00 00 FE 00 00 (probe)
device → BW: SUB 0xF9 (probe ack)
BW → device: SUB 0x06 offset=0x0024 params=(same) (data)
device → BW: SUB 0xF9 (36-byte storage range response)
BW → device: SUB 0xA2 offset=0x0000 params=00 00 00 00 00 00 00 FE 00 00
device → BW: SUB 0x5D (confirm-erase ack — device memory is now cleared)
```
All response SUBs follow the standard formula `0xFF request_SUB`. No exceptions.
The `token=0xFE` at `params[7]` is required for 0xA3, 0x06, and 0xA2.
### 7.11.2 SUB 0x06 Storage Range Response (36 bytes)
The 36-byte response from the data step ends with two 4-byte event keys:
| Offset (from response end) | Field | Notes |
|---|---|---|
| `[-8:-4]` | First stored event key | e.g. `0111ea60` before erase |
| `[-4:]` | Last stored event key | e.g. `0111eaa6` before erase |
After a successful erase:
- Both keys read `01110000` (device-empty sentinel)
- The device's internal event counter has reset
Example pre-erase: `... 0111ea60 0111eaa6`
Example post-erase: `... 01110000 01110000`
### 7.11.3 Post-Erase Key Counter Reset
After a successful erase the device resets its event counter. New events start
from key `0x01110000` — the same key as the very first event ever recorded on
the device. This means:
- Any system using event keys for deduplication must clear its "seen keys" state
after an erase, or risk treating fresh events as already downloaded.
- Detection heuristic: if `max(device_keys) < historical_max_key`, the counter
was reset. All device keys should be treated as new regardless of prior state.
The `ach_server.py` implementation stores `max_downloaded_key` in `ach_state.json`
and applies this heuristic on every call-home.
### 7.11.4 Implementation Notes
- `MiniMateClient.delete_all_events()` in `client.py` orchestrates the full sequence.
- `MiniMateProtocol` exposes `begin_erase_all()`, `confirm_erase_all()`, and
`read_event_storage_range()` as separate methods.
- The ACH server `--clear-after-download` flag calls `delete_all_events()` after a
successful event download and resets `ach_state.json` state for the unit.
---
## 8. Timestamp Format
Two timestamp wire formats are used:
@@ -1776,7 +1855,7 @@ The TCP port is **user-configurable** in both Blastware and the modem. There is
---
### 14.6 ACH Session Lifecycle (Call Home Mode — Future)
### 14.6 ACH Session Lifecycle (Call Home Mode) ✅ IMPLEMENTED 2026-04-11
When the unit calls home under ACH, the session lifecycle from the unit's perspective is:
@@ -1785,10 +1864,28 @@ When the unit calls home under ACH, the session lifecycle from the unit's perspe
3. Unit waits for "Wait for Connection" window for first BW frame from server
4. Server sends POLL_PROBE → unit responds with POLL_RESPONSE (same as serial)
5. Server reads serial number, full config, events as needed
6. Server disconnects (or unit disconnects on Serial Idle Time expiry)
7. Unit powers modem down, returns to monitor mode
6. (Optional) Server erases device memory: SUB 0xA3 → 0x1C → 0x06 → 0xA2
7. Server disconnects (or unit disconnects on Serial Idle Time expiry)
8. Unit detects DCD/DTR going low (modem signals line drop), returns to monitor mode automatically
Step 4 onward is **identical to the serial/call-up protocol**. The only difference from our perspective is that we are the **listener** rather than the **connector**. A future `AchServer` class will accept the incoming TCP connection and hand the socket to `TcpTransport` for processing.
Step 4 onward is **identical to the serial/call-up protocol**. The only difference
from our perspective is that we are the **listener** rather than the **connector**.
**Implementation: `bridges/ach_server.py`** — run with `python bridges/ach_server.py`.
Key flags:
- `--clear-after-download` — erase device memory after a successful event download
- `--allow-ip IP` — restrict to specific unit IPs
- `--max-events N` — cap events per session for safety
**State persistence: `ach_state.json`** — tracks `downloaded_keys` (set of event key
hex strings) and `max_downloaded_key` (high-water mark) per unit serial number.
Post-erase key reuse (`0x01110000` recycled) is detected via the high-water mark.
**Note on DCD/DTR:** The MiniMate Plus monitors the RS-232 DCD line. When the TCP
connection closes, the Sierra Wireless modem drops DCD, which the unit interprets as
"serial connection ended" and automatically resumes monitoring. No `start_monitoring()`
(SUB 0x96) command is needed from the server. ⚠️ Newer RV55 firmware may not assert DCD
by default — known issue, not yet resolved.
---
@@ -1841,6 +1938,11 @@ The `.bin` files produced by `s3_bridge` are **not raw wire bytes**. The logger
| Backlight offset — **RESOLVED: +4B in event index data**, uint8, seconds | RESOLVED | 2026-03-02 | |
| Power save offset — **RESOLVED: +53 in event index data**, uint8, minutes | RESOLVED | 2026-03-02 | |
| Monitoring LCD Cycle — **RESOLVED: +54/+55 in event index data**, uint16 BE, seconds (65500 = disabled) | RESOLVED | 2026-03-02 | |
| **SUB 0x06 purpose — RESOLVED: event storage range.** Previously labeled "CHANNEL CONFIG READ". 4-11-26 MITM capture confirms it returns first/last stored event keys in the final 8 bytes of the 36-byte response. Used by Blastware as part of the erase-all verification step. | RESOLVED | 2026-04-11 | |
| **Erase-all command sequence — RESOLVED.** SUB 0xA3 (begin) + 0x1C (monitor status) + 0x06 (storage range) + 0xA2 (confirm). Confirmed from 4-11-26 MITM capture. All frames standard `build_bw_frame`, token=0xFE. | RESOLVED | 2026-04-11 | |
| **ACH inbound server — RESOLVED.** `bridges/ach_server.py` implements full inbound ACH pipeline. `--clear-after-download` flag for delete-after-upload workflow. Post-erase key-reuse detection via `max_downloaded_key` high-water mark. | RESOLVED | 2026-04-11 | |
| **Sensor Check dropdown byte location** — byte offset in 1A compliance config payload for the "Sensor Check: Before monitoring / After each event / Disabled" setting is NOT YET LOCATED. Confirmed: unit always runs with "Before monitoring" set. Need a capture with "Disabled" to diff. | MEDIUM | 2026-04-08 | Still open |
| **RV55 DCD/DTR default** — newer Sierra Wireless RV55 firmware does not assert DCD/DTR by default, so the MiniMate Plus never detects TCP disconnect and stays idle instead of resuming monitoring. Root cause: RV55 ACEmanager `DCD Control` setting. Workaround not yet found. | MEDIUM | 2026-04-11 | Still open |
---