# seismo-relay `v0.5.0` A ground-up replacement for **Blastware** — Instantel's aging Windows-only software for managing MiniMate Plus seismographs. Built in Python. Runs on Windows. Connects to instruments over direct RS-232 or cellular modem (Sierra Wireless RV50 / RV55). > **Status:** Active development. Core read pipeline working (device info, > config, event index). Event download and write commands in progress. > See [CHANGELOG.md](CHANGELOG.md) for version history. --- ## What's in here ``` seismo-relay/ ├── seismo_lab.py ← Main GUI (Bridge + Analyzer + Console tabs) │ ├── minimateplus/ ← MiniMate Plus client library │ ├── transport.py ← SerialTransport and TcpTransport │ ├── protocol.py ← DLE frame layer (read/write/parse) │ ├── client.py ← High-level client (connect, get_config, etc.) │ ├── framing.py ← Frame builder/parser primitives │ └── models.py ← DeviceInfo, EventRecord, etc. │ ├── sfm/ ← SFM REST API server (FastAPI) │ └── server.py ← /device/info, /device/events, /device/event │ ├── bridges/ │ ├── s3-bridge/ │ │ └── s3_bridge.py ← RS-232 serial bridge (capture tool) │ ├── tcp_serial_bridge.py ← Local TCP↔serial bridge (bench testing) │ ├── gui_bridge.py ← Standalone bridge GUI (legacy) │ └── raw_capture.py ← Simple raw capture tool │ ├── parsers/ │ ├── s3_parser.py ← DLE frame extractor │ ├── s3_analyzer.py ← Session parser, differ, Claude export │ ├── gui_analyzer.py ← Standalone analyzer GUI (legacy) │ └── frame_db.py ← SQLite frame database │ └── docs/ └── instantel_protocol_reference.md ← Reverse-engineered protocol spec ``` --- ## Quick start ### Seismo Lab (main GUI) The all-in-one tool. Three tabs: **Bridge**, **Analyzer**, **Console**. ``` python seismo_lab.py ``` ### SFM REST server Exposes MiniMate Plus commands as a REST API for integration with other systems. ``` cd sfm uvicorn server:app --reload ``` **Endpoints:** | Method | URL | Description | |--------|-----|-------------| | `GET` | `/device/info?port=COM5` | Device info via serial | | `GET` | `/device/info?host=1.2.3.4&tcp_port=9034` | Device info via cellular modem | | `GET` | `/device/events?port=COM5` | Event index | | `GET` | `/device/event?port=COM5&index=0` | Single event record | --- ## Seismo Lab tabs ### Bridge tab Captures live RS-232 traffic between Blastware and the seismograph. Sits in the middle as a transparent pass-through while logging everything to disk. ``` Blastware → COM4 (virtual) ↔ s3_bridge ↔ COM5 (physical) → MiniMate Plus ``` Set your COM ports and log directory, then hit **Start Bridge**. Use **Add Mark** to annotate the capture at specific moments (e.g. "changed trigger level"). When the bridge starts, the Analyzer tab automatically wires up to the live files and starts updating in real time. ### Analyzer tab Parses raw captures into DLE-framed protocol sessions, diffs consecutive sessions to show exactly which bytes changed, and lets you query across all historical captures via the built-in SQLite database. - **Inventory** — all frames in a session, click to drill in - **Hex Dump** — full payload hex dump with changed-byte annotations - **Diff** — byte-level before/after diff between sessions - **Full Report** — plain text session report - **Query DB** — search across all captures by SUB, direction, or byte value Use **Export for Claude** to generate a self-contained `.md` report for AI-assisted field mapping. ### Console tab Direct connection to a MiniMate Plus — no bridge, no Blastware. Useful for diagnosing field units over cellular without a full capture session. **Connection:** choose Serial (COM port + baud) or TCP (IP + port for cellular modem). **Commands:** | Button | What it does | |--------|-------------| | POLL | Startup handshake — confirms unit is alive and identifies model | | Serial # | Reads unit serial number | | Full Config | Reads full 166-byte config block (firmware version, channel scales, etc.) | | Event Index | Reads stored event list | Output is colour-coded: TX in blue, raw RX bytes in teal, decoded fields in green, errors in red. **Save Log** writes a timestamped `.log` file to `bridges/captures/`. **Send to Analyzer** injects the captured bytes into the Analyzer tab for deeper inspection. --- ## Connecting over cellular (RV50 / RV55 modems) Field units connect via Sierra Wireless RV50 or RV55 cellular modems. Use TCP mode in the Console or SFM: ``` # Console tab Transport: TCP Host: Port: 9034 ← Device Port in ACEmanager (call-up mode) ``` ```python # In code from minimateplus.transport import TcpTransport from minimateplus.client import MiniMateClient client = MiniMateClient(transport=TcpTransport("1.2.3.4", 9034)) info = client.connect() ``` ### Required ACEmanager settings (Serial tab) These must match exactly — a single wrong setting causes the unit to beep on connect but never respond: | Setting | Value | Why | |---------|-------|-----| | Configure Serial Port | `38400,8N1` | Must match MiniMate baud rate | | Flow Control | `None` | Hardware flow control blocks unit TX if pins unconnected | | **Quiet Mode** | **Enable** | **Critical.** Disabled → modem injects `RING`/`CONNECT` onto serial line, corrupting the S3 handshake | | Data Forwarding Timeout | `1` (= 0.1 s) | Lower latency; `5` works but is sluggish | | TCP Connect Response Delay | `0` | Non-zero silently drops the first POLL frame | | TCP Idle Timeout | `2` (minutes) | Prevents premature disconnect | | DB9 Serial Echo | `Disable` | Echo corrupts the data stream | --- ## minimateplus library ```python from minimateplus import MiniMateClient from minimateplus.transport import SerialTransport, TcpTransport # Serial client = MiniMateClient(port="COM5") # TCP (cellular modem) client = MiniMateClient(transport=TcpTransport("1.2.3.4", 9034), timeout=30.0) with client: info = client.connect() # DeviceInfo — model, serial, firmware serial = client.get_serial() # Serial number string config = client.get_config() # Full config block (bytes) events = client.get_events() # Event index ``` --- ## Protocol quick-reference | Term | Value | Meaning | |------|-------|---------| | DLE | `0x10` | Data Link Escape | | STX | `0x02` | Start of frame | | ETX | `0x03` | End of frame | | ACK | `0x41` (`'A'`) | Frame-start marker sent before every frame | | DLE stuffing | `10 10` on wire | Literal `0x10` in payload | **S3-side frame** (seismograph → Blastware): `ACK DLE+STX [payload] CHK DLE+ETX` **De-stuffed payload header:** ``` [0] CMD 0x10 = BW request, 0x00 = S3 response [1] ? unknown (0x00 BW / 0x10 S3) [2] SUB Command/response identifier ← the key field [3] PAGE_HI Page address high byte [4] PAGE_LO Page address low byte [5+] DATA Payload content ``` **Response SUB rule:** `response_SUB = 0xFF - request_SUB` Example: request SUB `0x08` (Event Index) → response SUB `0xF7` Full protocol documentation: [`docs/instantel_protocol_reference.md`](docs/instantel_protocol_reference.md) --- ## Requirements ``` pip install pyserial fastapi uvicorn ``` Python 3.10+. Tkinter is included with the standard Python installer on Windows (make sure "tcl/tk and IDLE" is checked during install). --- ## Virtual COM ports (bridge capture) The bridge needs two COM ports on the same PC — one that Blastware connects to, and one wired to the seismograph. Use a virtual COM port pair (**com0com** or **VSPD**) to give Blastware a port to talk to. ``` Blastware → COM4 (virtual) ↔ s3_bridge.py ↔ COM5 (physical) → MiniMate Plus ``` --- ## Roadmap - [ ] Event download — pull waveform records from the unit (SUBs `1E` → `0A` → `0C` → `5A`) - [ ] Write commands — push config changes to the unit (compliance setup, channel config, trigger settings) - [ ] ACH inbound server — accept call-home connections from field units - [ ] Modem manager — push standard configs to RV50/RV55 fleet via Sierra Wireless API - [ ] Full Blastware parity — complete read/write/download cycle without Blastware