Files
seismo-relay/docs/micromate_protocol_reference.md
T
serversdownandClaude Opus 5 095834183e docs(series4): open the Micromate live-protocol reference
First bench session against a Micromate over USB. The headline: the unit
answers Series III command frames unmodified.

An untouched Series III POLL (SUB 0x5B), built by build_bw_frame with no
changes, completed a full two-step probe/data cycle. Ten Series III read
commands were then tried and all ten answered, every one obeying the
response_SUB = 0xFF - request_SUB rule.

Confirmed this session:

- Transport is a plain USB CDC-ACM port (2504:0300, "MICROMATE COM PORT").
  No vendor driver, no Thor, no Windows box needed. Baud is ignored over USB
  (identical responses at 38400 and 115200).
- Device never speaks first -- 20 s idle listen produced nothing.
- Responses are Series III framing MINUS the leading DLE: bare
  [STX][payload][chk][ETX]. This alone means Blastware can never find a frame
  boundary in Micromate traffic, since its parser scans for DLE+STX.
- Response flags byte is 0xC5, not Series III's 0x10.
- Checksum is the DLE-aware variant (SUM8 excluding 0x10 bytes) -- the same
  one Series III uses for 5A and write frames, not the plain SUM8 of its
  ordinary reads. Disambiguated by the POLL data frame, which contains a 0x10.
- The probe response carries the data length at payload[9]. Four of four
  known Series III lengths match; call-home config differs (0x7E vs 0x7C).
- Series III monitor-status field offsets apply unchanged: battery 3.81 V
  (Thor's own reports say 3.8), memory 15,000,000 total and free, date
  23 Sep 2026.
- SUB 0x2C carries the string "RADIO RING" -- the same string seen in the
  RV50 ALEOS debug during the BE12599 incident. That block holds the modem
  dial/answer strings and is the most relevant command to the call-home goal.

Read commands only. Nothing that writes, erases, or changes monitoring state
has been sent to a unit; those are listed as unsafe-until-agreed.

Caveat recorded in the doc: one unit, over USB, with zero events stored, so
the event-walk commands (0x08, 0x1E, 0x0A, 0x06) could only be probed, not
exercised.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ru8Lg9HkkYvX9VWWo65SmL
2026-09-23 15:59:17 -04:00

8.8 KiB
Raw Blame History

Micromate Protocol Reference — Thor / Micromate Series IV, live wire protocol

Sibling to instantel_protocol_reference.md (Series III, "the Rosetta Stone") and idf_protocol_reference.md (Series IV file format). This document covers the Series IV live device protocol — what the unit says over the wire, as opposed to what it writes into a .IDFW.

Status (2026-09-23): opening session. Everything below was established in a single bench session against one unit. Treat it as a strong start, not a settled spec — in particular, everything here comes from one unit, over USB, with no events stored.


The headline

The Micromate answers Series III command frames.

An unmodified Series III POLL (SUB 0x5B), built by minimateplus.framing.build_bw_frame with no changes at all, produced a complete two-step probe/data cycle from a Micromate. Ten Series III read commands were then tried and all ten answered, every one obeying the Series III response-SUB rule.

This is not a new protocol. It is close enough to Series III that large parts of minimateplus/protocol.py may apply more or less directly, and the work ahead is mapping divergence rather than mapping from scratch.


How this was obtained

No Thor, no modem, no Windows machine. The Micromate exposes its protocol on a USB CDC-ACM virtual serial port:

ID 2504:0300 Instantel Inc. MICROMATE COM PORT
driver: cdc_acm          ATTRS{serial}=="V1.00"
→ /dev/ttyACM0

Plain CDC ACM, so no vendor driver and no proprietary USB layer — any host that can open a serial port can talk to the unit.

Baud is irrelevant over USB. Identical byte-for-byte responses at 38400 and 115200; CDC-ACM ignores the line rate. TMI provisions Micromate modem links at 115200 (Series III uses 38400) — that matters for the cellular path, not for USB.

The device never speaks first. 20 s of passive listening on an idle open port produced zero bytes. It is strictly request/response.


Physical + framing layer

Requests — Series III format, unmodified

Every frame in this session was produced by build_bw_frame(sub, offset) with no Series IV changes, and the device accepted all of them:

[ACK 0x41] [STX 0x02] [10 10] [flags 00] [SUB] [00] [00] [offset] [params×10] [chk] [ETX 0x03]

⚠ Only the doubled BW_CMD (10 10) form has been exercised. Whether other literal 0x10 bytes inside params require stuffing is untested — none of the probes sent carried one.

Responses — Series III minus the DLE prefix

Series III:   [DLE 0x10] [STX 0x02] … [chk] [ETX 0x03]
Micromate:              [STX 0x02] … [chk] [ETX 0x03]      ← no leading DLE

This single byte matters operationally: Blastware's parser locates frames by scanning for DLE+STX, so it will never find a frame boundary in Micromate traffic no matter what else is correct. That is a structural reason a Micromate cannot call into a Blastware ACH server, independent of any baud mismatch.

Response payload header

[0] CMD    0x00          same as Series III
[1] flags  0xC5          ← Series III uses 0x10.  Constant across all 10 SUBs.
[2] SUB    0xFF − request_SUB
[3] PAGE_HI
[4] PAGE_LO
[5+] data

Checksum — the DLE-aware variant

chk = sum(b for b in payload if b != 0x10) & 0xFF

Confirmed on every frame captured. The POLL probe response contains no 0x10 and so cannot distinguish plain SUM8 from the DLE-aware form; the POLL data response contains a 0x10 at payload offset 42, and only the DLE-aware rule matches there. This is the same checksum Series III uses for its 5A bulk-stream and write frames — not the plain SUM8 of ordinary Series III reads.

The probe response carries the data length

Series III hardcodes DATA_LENGTHS per SUB. On the Micromate the probe response tells you, at payload[9]:

SUB command payload[9] Series III constant
0x15 serial number 0x0A 0x0A ✓
0x01 device info 0x98 0x98 ✓
0x1C monitor status 0x2C 0x2C ✓
0x06 storage range 0x24 0x24 ✓
0x2C call-home config 0x7E 0x7C ✗ differs by 2
0x08 event index 0x5A —
0x1E event header 0x08 —
0x1A compliance config 0x2C —
0x0A waveform header 0x00 — (no event context)
0xFE full config 0x00 — (see note)

Four of four known Series III lengths match exactly. Read the length from the probe rather than hardcoding it — it is free, and it already caught the call-home divergence.


Confirmed commands (read-only)

All ten below answered with a correct 0xFF − SUB response. Nothing that writes, erases, or changes monitoring state has been sent to a unit.

SUB RSP Command Data proven
0x5B 0xA4 POLL / handshake yes — ID block
0x15 0xEA Serial number yes — UM12947
0x01 0xFE Device info yes — 152 B
0x2C 0xD3 Call-home config yes — 126 B
0x1C 0xE3 Monitor status yes — 44 B
0x06 0xF9 Event storage range yes — 36 B
0x08 0xF7 Event index probe only
0x1E 0xE1 Event header / first key probe only
0x0A 0xF5 Waveform header probe only
0x1A 0xE5 Compliance config probe only

Decoded so far

SUB 0x15 — serial. ASCII, null-terminated: UM12947.

SUB 0x5B / 0x01 — identification strings. Instantel\0 and MM/ISEE/S/IO (MicroMate / ISEE standard). 0x01 also carries eight consecutive 3f 80 00 00 float32 values (= 1.0f) — almost certainly per-channel calibration/scale factors, by analogy with Series III's geo_hardware_constant. Unverified.

SUB 0x1C — monitor status. Series III field offsets apply unchanged:

field offset read
battery × 100 payload[-10:-8] uint16 BE 0x017D → 3.81 V
memory total payload[-8:-4] uint32 BE 15,000,000
memory free payload[-4:] uint32 BE 15,000,000 (empty)
date payload[18:22] day 23, month 9, year 0x07EA = 2026

The battery reading independently corroborates: Thor's own event reports for these units print BatteryLevel : 3.8 volts.

SUB 0x2C — call-home config. Contains the ASCII string RADIO RING. Worth flagging: that is the exact string seen in the RV50 ALEOS_SERIAL debug during the BE12599 incident — 'ATQ1^MATE0^MATS0=2^M^MRADIO RING^M'. So this block holds the modem dial / answer strings, and it is the most directly relevant command to the call-home-receiver goal. Field layout not yet mapped; Series III's map (raw[5] enabled, raw[6:46] dial string) is a starting hypothesis only, and the length already differs (0x7E vs 0x7C).

SUB 0x06 — storage range. All zeros on this unit, consistent with memory free == memory total. Series III reads first/last event keys from the final 8 bytes; untestable until the unit holds events.


Divergences from Series III (running list)

  1. No DLE prefix on responses — bare STX.
  2. Response flags byte is 0xC5, not 0x10.
  3. Call-home config is 126 bytes, not 124.
  4. Data lengths are discoverable from the probe response at payload[9].
  5. Modem serial rate is 115200, not 38400 (per TMI provisioning practice; not independently verified here).

⚠ Untested and unsafe-until-agreed

Nothing below has been sent to a unit, and nothing should be without an explicit decision:

  • Writes (0x68–0x83), call-home write (0x7E/0x7F)
  • Erase (0xA3 / 0xA2)
  • Start / stop monitoring (0x96 / 0x97)
  • 0x1F (advance event pointer) — non-destructive on Series III but it does move device state, so it is parked with the rest

Also unknown:

  • Whether 0x10 bytes inside request params need stuffing
  • Whether the bulk waveform stream (5A on Series III) exists here, and whether it is the transport for .IDFW bodies we already decode
  • 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.

Session provenance

Unit UM12947, on the bench via USB, zero events stored (memory free == total). Read commands only. Every response in this document was checksum- validated.

An empty unit is a real limitation: 0x08, 0x1E, 0x0A and 0x06 all have event-dependent payloads that could not be exercised. Recording a couple of events on the bench unit would unlock the entire event-walk half of the protocol.