v0.12.6 #10
@@ -1,4 +1,4 @@
|
|||||||
# seismo-relay `v0.12.1`
|
# seismo-relay `v0.12.5`
|
||||||
|
|
||||||
A ground-up replacement for **Blastware** — Instantel's aging Windows-only
|
A ground-up replacement for **Blastware** — Instantel's aging Windows-only
|
||||||
software for managing MiniMate Plus seismographs.
|
software for managing MiniMate Plus seismographs.
|
||||||
@@ -18,26 +18,27 @@ over direct RS-232 or cellular modem (Sierra Wireless RV50 / RV55).
|
|||||||
|
|
||||||
```
|
```
|
||||||
seismo-relay/
|
seismo-relay/
|
||||||
├── seismo_lab.py ← Main GUI (Bridge + Analyzer + Console tabs)
|
├── seismo_lab.py ← Main GUI (Bridge + Analyzer + Download + Console tabs)
|
||||||
│
|
│
|
||||||
├── minimateplus/ ← MiniMate Plus client library
|
├── minimateplus/ ← MiniMate Plus client library
|
||||||
│ ├── transport.py ← SerialTransport, TcpTransport, SocketTransport
|
│ ├── transport.py ← SerialTransport, TcpTransport, SocketTransport
|
||||||
│ ├── protocol.py ← DLE frame layer, SUB command dispatch
|
│ ├── protocol.py ← DLE frame layer, SUB command dispatch
|
||||||
│ ├── client.py ← High-level client (connect, get_events, push_config, …)
|
│ ├── client.py ← High-level client (connect, get_events, delete_all_events, push_config, get_call_home_config, …)
|
||||||
│ ├── framing.py ← Frame builders, DLE codec, S3FrameParser
|
│ ├── framing.py ← Frame builders, DLE codec, S3FrameParser
|
||||||
│ └── models.py ← DeviceInfo, Event, ComplianceConfig, MonitorLogEntry, …
|
│ ├── models.py ← DeviceInfo, Event, ComplianceConfig, MonitorLogEntry, CallHomeConfig, …
|
||||||
|
│ └── blastware_file.py ← Write events to Blastware-compatible .AB0 files
|
||||||
│
|
│
|
||||||
├── sfm/ ← SFM REST API server (FastAPI, port 8200)
|
├── sfm/ ← SFM REST API server (FastAPI, port 8200)
|
||||||
│ ├── server.py ← All device + DB endpoints
|
│ ├── server.py ← Live device endpoints + DB query endpoints + caching
|
||||||
│ ├── database.py ← SeismoDb — SQLite persistence layer
|
│ ├── database.py ← SeismoDb — SQLite persistence (events, monitor_log, ach_sessions, sessions table)
|
||||||
│ └── sfm_webapp.html ← Embedded web UI (served at /)
|
│ └── sfm_webapp.html ← Embedded web UI with Call Home config tab
|
||||||
│
|
│
|
||||||
├── bridges/
|
├── bridges/
|
||||||
│ ├── ach_server.py ← Inbound ACH call-home server (main production server)
|
│ ├── ach_server.py ← Inbound ACH call-home server (main production server)
|
||||||
│ ├── ach_mitm.py ← Transparent MITM proxy for capturing BW sessions
|
│ ├── ach_mitm.py ← Transparent MITM proxy for capturing BW sessions
|
||||||
│ ├── s3-bridge/ ← RS-232 serial bridge (capture tool)
|
│ ├── s3-bridge/ ← RS-232 serial bridge (capture tool)
|
||||||
│ ├── tcp_serial_bridge.py ← Local TCP↔serial bridge (bench testing)
|
│ ├── tcp_serial_bridge.py ← Local TCP↔serial bridge (bench testing)
|
||||||
│ ├── gui_bridge.py ← Standalone bridge GUI
|
│ ├── gui_bridge.py ← Standalone bridge GUI with raw capture checkboxes
|
||||||
│ └── raw_capture.py ← Simple raw capture tool
|
│ └── raw_capture.py ← Simple raw capture tool
|
||||||
│
|
│
|
||||||
├── parsers/
|
├── parsers/
|
||||||
@@ -101,21 +102,28 @@ python seismo_lab.py
|
|||||||
Each call dials the device, does its work, and closes the connection. TCP
|
Each call dials the device, does its work, and closes the connection. TCP
|
||||||
connections are retried once on `ProtocolError` to handle cold-boot timing.
|
connections are retried once on `ProtocolError` to handle cold-boot timing.
|
||||||
|
|
||||||
**Caching** — frequently-polled endpoints are cached in-process to avoid
|
**In-memory caching** — frequently-polled endpoints avoid redundant TCP round-trips
|
||||||
redundant TCP round-trips:
|
via a thread-safe `_LiveCache` (plain Python dict + `threading.Lock`):
|
||||||
|
|
||||||
| Method | URL | Cache |
|
| Method | URL | Cache Strategy |
|
||||||
|--------|-----|-------|
|
|--------|-----|---|
|
||||||
| `GET` | `/device/info` | Indefinite; invalidated by `POST /device/config` |
|
| `GET` | `/device/info` | Indefinite; invalidated by `POST /device/config` |
|
||||||
| `GET` | `/device/events` | Count-probe fast path (~2s); full download only when new events detected |
|
| `GET` | `/device/events` | Count-probe fast path (~2s); full download only when new events detected |
|
||||||
| `GET` | `/device/event/{idx}/waveform` | Permanent per event index |
|
| `GET` | `/device/event/{idx}/waveform` | Permanent per event index |
|
||||||
| `GET` | `/device/monitor/status` | 30-second TTL |
|
| `GET` | `/device/monitor/status` | 30-second TTL; invalidated by monitor start/stop |
|
||||||
|
| `GET` | `/device/call_home` | Fresh read from device (not cached) |
|
||||||
| `POST` | `/device/connect` | — |
|
| `POST` | `/device/connect` | — |
|
||||||
| `POST` | `/device/config` | Writes compliance config; invalidates cache |
|
| `POST` | `/device/config` | Writes compliance config; invalidates info + events cache |
|
||||||
| `POST` | `/device/monitor/start` | Sends SUB 0x96 |
|
| `POST` | `/device/config/project` | Patches project/client/operator/sensor_location strings |
|
||||||
| `POST` | `/device/monitor/stop` | Sends SUB 0x97 |
|
| `POST` | `/device/monitor/start` | Sends SUB 0x96; immediately evicts status cache |
|
||||||
|
| `POST` | `/device/monitor/stop` | Sends SUB 0x97; immediately evicts status cache |
|
||||||
|
| `POST` | `/device/call_home` | Reads, patches specified fields, writes back to device |
|
||||||
|
|
||||||
All cached endpoints accept `?force=true` to bypass the cache.
|
**Cache bypass** — All cached endpoints accept `?force=true` to skip the cache and
|
||||||
|
force a fresh read from the device.
|
||||||
|
|
||||||
|
**Cache stats** — `GET /cache/stats` returns hit/miss counts and TTL info; `DELETE /cache/device`
|
||||||
|
clears the device cache immediately.
|
||||||
|
|
||||||
Transport query params (supply one set):
|
Transport query params (supply one set):
|
||||||
```
|
```
|
||||||
@@ -152,21 +160,33 @@ client = MiniMateClient(transport=TcpTransport("1.2.3.4", 12345), timeout=30.0)
|
|||||||
|
|
||||||
with client:
|
with client:
|
||||||
# Read
|
# Read
|
||||||
info = client.connect() # DeviceInfo — serial, firmware, compliance config
|
info = client.connect() # DeviceInfo — serial, firmware, compliance config
|
||||||
count = client.count_events() # Number of stored events
|
count = client.count_events() # Number of stored events
|
||||||
keys = client.list_event_keys() # Fast browse walk — event keys only, no download
|
keys = client.list_event_keys() # Fast browse walk — event keys only, no download
|
||||||
events = client.get_events() # Full download: headers + peaks + metadata
|
events = client.get_events() # Full download: headers + peaks + metadata
|
||||||
monitor = client.get_monitor_status() # Battery, memory, is_monitoring flag
|
monitor = client.get_monitor_status() # Battery, memory, is_monitoring flag
|
||||||
log = client.get_monitor_log_entries() # Monitoring intervals (partial 0x2C records)
|
log = client.get_monitor_log_entries() # Monitoring intervals (partial 0x2C records)
|
||||||
|
ach_cfg = client.get_call_home_config() # Auto Call Home settings (SUB 0x2C)
|
||||||
|
|
||||||
# Write
|
# Write
|
||||||
client.apply_config(
|
client.apply_config(
|
||||||
sample_rate=1024,
|
sample_rate=1024,
|
||||||
|
recording_mode="Continuous", # Single Shot / Continuous / Histogram / Histogram+Continuous
|
||||||
|
histogram_interval_sec=15, # 2, 5, 15, 60, 300, 900
|
||||||
trigger_level_geo=0.5,
|
trigger_level_geo=0.5,
|
||||||
|
geo_range="Normal", # Normal (10.000 in/s) / Sensitive (1.25 in/s)
|
||||||
project="Bridge Inspection 2026",
|
project="Bridge Inspection 2026",
|
||||||
client_name="City of Portland",
|
client_name="City of Portland",
|
||||||
operator="B. Harrison",
|
operator="B. Harrison",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
client.set_call_home_config(
|
||||||
|
auto_call_home_enabled=True,
|
||||||
|
after_event_recorded=True,
|
||||||
|
at_specified_times=True,
|
||||||
|
time1_hour=18, time1_min=30, # 6:30 PM
|
||||||
|
time2_hour=6, time2_min=0, # 6:00 AM
|
||||||
|
)
|
||||||
|
|
||||||
# Control
|
# Control
|
||||||
client.start_monitoring() # SUB 0x96
|
client.start_monitoring() # SUB 0x96
|
||||||
@@ -182,18 +202,20 @@ existed at record time — not backfilled from the current compliance config.
|
|||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
`ach_server.py` writes to `bridges/captures/seismo_relay.db` (SQLite, WAL mode).
|
`ach_server.py` writes to `bridges/captures/seismo_relay.db` (SQLite, WAL mode) using the
|
||||||
Three tables, all unit-keyed by serial number:
|
`SeismoDb` persistence layer. Four tables, all unit-keyed by serial number:
|
||||||
|
|
||||||
| Table | Key | Contents |
|
| Table | Key | Contents |
|
||||||
|-------|-----|----------|
|
|-------|-----|----------|
|
||||||
| `ach_sessions` | UUID | Per-call-home audit record: serial, peer IP, events_downloaded, duration |
|
| `ach_sessions` | UUID | Per-call-home audit record: serial, timestamp, peer IP, events_downloaded, monitor_entries, duration_seconds |
|
||||||
| `events` | UUID, UNIQUE(serial, waveform_key) | Triggered events: timestamp, PPV per channel, project/client/operator strings, false_trigger flag |
|
| `events` | UUID, UNIQUE(serial, waveform_key) | Triggered events: timestamp, Tran/Vert/Long/VectorSum/Mic PPV, project/client/operator/sensor_location strings, sample_rate, record_type, false_trigger flag |
|
||||||
| `monitor_log` | UUID, UNIQUE(serial, waveform_key) | Monitoring intervals: start/stop time, duration, geo threshold |
|
| `monitor_log` | UUID, UNIQUE(serial, waveform_key) | Monitoring intervals: serial, waveform_key, start_time, stop_time, duration_seconds, geo_threshold_ips |
|
||||||
|
| `events.false_trigger` | Boolean flag | PATCH endpoint to mark/unmark false triggers for review |
|
||||||
|
|
||||||
Deduplication is by `(serial, waveform_key)` — repeat call-homes or re-runs
|
Deduplication is by `(serial, waveform_key)` — repeat call-homes or re-runs never
|
||||||
never produce duplicate rows. Post-erase key reuse is handled automatically
|
produce duplicate rows. Post-erase key reuse is handled automatically via the
|
||||||
via the high-water mark in `ach_state.json`.
|
high-water mark in `ach_state.json`. Key-based state tracking allows correct
|
||||||
|
handling of device erasures (external or post-download).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -231,6 +253,27 @@ Full protocol documentation: [`docs/instantel_protocol_reference.md`](docs/insta
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Compliance Config Features (v0.12.2–v0.12.3)
|
||||||
|
|
||||||
|
The REST API and web UI expose full control over device compliance settings:
|
||||||
|
|
||||||
|
- **Recording Mode** (Single Shot / Continuous / Histogram / Histogram+Continuous)
|
||||||
|
- **Sample Rate** (1024 / 2048 / 4096 sps)
|
||||||
|
- **Record Time** (float, seconds)
|
||||||
|
- **Histogram Interval** (2s, 5s, 15s, 1m, 5m, 15m) — when recording mode includes histogram
|
||||||
|
- **Geo Trigger Levels** (float, in/s per channel)
|
||||||
|
- **Geo Maximum Range** (Normal 10.000 in/s / Sensitive 1.250 in/s per channel)
|
||||||
|
- **Project / Client / Operator / Sensor Location** (ASCII strings)
|
||||||
|
|
||||||
|
Auto Call Home config:
|
||||||
|
- **Auto Call Home Enable** (bool)
|
||||||
|
- **Dial String** (read-only; 40-byte ASCII)
|
||||||
|
- **Trigger on Event** (bool)
|
||||||
|
- **Scheduled Call-Ins** (two time slots with HH:MM each)
|
||||||
|
- **Retry Settings** (count, delay, connection timeout, warm-up time)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -252,17 +295,55 @@ Use **com0com** or **VSPD** to create the virtual COM pair on Windows.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Roadmap
|
## Key Features (v0.10–v0.12)
|
||||||
|
|
||||||
|
**Device support (v0.12.5):**
|
||||||
|
- [x] Full read/write/erase pipelines
|
||||||
|
- [x] Compliance config (recording mode, sample rate, histogram interval, geo sensitivity, project strings)
|
||||||
|
- [x] Auto Call Home config (read/write ACH settings, dial string, time slots, retries)
|
||||||
|
- [x] Monitor control (start/stop, status polling, battery/memory)
|
||||||
|
- [x] Monitor log entries (continuous monitoring intervals without full waveform download)
|
||||||
|
|
||||||
|
**Data persistence (v0.11):**
|
||||||
|
- [x] SQLite database (`seismo_relay.db`) with 4 tables: ach_sessions, events, monitor_log, plus false_trigger flag
|
||||||
|
- [x] Deduplication by waveform key (handles re-runs and repeat call-homes)
|
||||||
|
- [x] Post-erase key-reuse detection (tracks high-water mark)
|
||||||
|
- [x] Session state (`ach_state.json`) with downloaded keys and max key
|
||||||
|
|
||||||
|
**REST API (v0.12.1):**
|
||||||
|
- [x] Live device endpoints with in-memory caching (`_LiveCache`)
|
||||||
|
- [x] Cache statistics (`/cache/stats`) and manual invalidation (`/cache/device`)
|
||||||
|
- [x] DB query endpoints (units, events, monitor_log, sessions, false_trigger PATCH)
|
||||||
|
- [x] Call Home config read/write endpoints
|
||||||
|
- [x] Blastware file download endpoint (`/device/event/{index}/blastware_file`)
|
||||||
|
|
||||||
|
**File output (v0.7+):**
|
||||||
|
- [x] Blastware-compatible `.AB0` file generation (waveform + metadata)
|
||||||
|
- [x] Multi-channel waveform decode from SUB 5A bulk stream
|
||||||
|
- [x] Second-resolution timestamp encoding in Blastware filename
|
||||||
|
|
||||||
|
**Capture tools (v0.12.5):**
|
||||||
|
- [x] Serial-to-TCP bridge with raw BW/S3 capture (s3_bridge.py, defaults to auto-capture)
|
||||||
|
- [x] GUI bridge with raw capture checkboxes (gui_bridge.py)
|
||||||
|
- [x] ACH inbound server with bidirectional capture (ach_server.py saves raw_tx + raw_rx)
|
||||||
|
- [x] Transparent TCP MITM proxy for live BW session capture (ach_mitm.py)
|
||||||
|
|
||||||
|
**Analysis tools:**
|
||||||
|
- [x] s3_analyzer.py — session parser, frame differ, Claude export
|
||||||
|
- [x] gui_analyzer.py — standalone analyzer GUI
|
||||||
|
- [x] frame_db.py — SQLite frame database for capture analysis
|
||||||
|
|
||||||
|
**seismo_lab.py GUI (v0.12.5):**
|
||||||
|
- [x] Bridge tab — Serial/TCP mode selector with raw capture options
|
||||||
|
- [x] Analyzer tab — BW/S3 capture playback and differencing
|
||||||
|
- [x] Download tab — Live wire-byte capture during event download (new v0.12.5)
|
||||||
|
- [x] Console tab — Logging and diagnostics
|
||||||
|
|
||||||
|
## Roadmap (Future)
|
||||||
|
|
||||||
- [x] Full read pipeline — device info, compliance config, event download with true event-time metadata
|
|
||||||
- [x] Write commands — push compliance config, trigger thresholds, project strings to device
|
|
||||||
- [x] Erase all events — confirmed erase sequence from live MITM capture
|
|
||||||
- [x] Monitor control — start/stop monitoring, read battery/memory/status
|
|
||||||
- [x] Monitor log entries — decode partial 0x2C records (continuous monitoring intervals)
|
|
||||||
- [x] ACH inbound server — accept call-home connections, download events, dedup by key
|
|
||||||
- [x] SQLite persistence — events, monitor log, and session history in `seismo_relay.db`
|
|
||||||
- [x] SFM REST API — device control + DB query endpoints, live device cache
|
|
||||||
- [ ] Terra-view integration — seismo-relay router, unit detail page, VISON-style event listing
|
- [ ] Terra-view integration — seismo-relay router, unit detail page, VISON-style event listing
|
||||||
- [ ] Vibration summary reports — highest legit PPV per project → Word doc (false trigger filtering first)
|
- [ ] Vibration summary reports — highest legit PPV per project → Word doc (false trigger filtering first)
|
||||||
- [ ] Compliance config encoder — build raw write payloads from a `ComplianceConfig` object
|
- [ ] Compliance config encoder — build raw write payloads from a `ComplianceConfig` object
|
||||||
- [ ] Modem manager — push RV50/RV55 configs via Sierra Wireless API
|
- [ ] Modem manager — push RV50/RV55 configs via Sierra Wireless API
|
||||||
|
- [ ] Histogram mode recording support (5A stream analysis for mode 0x03)
|
||||||
|
- [ ] Call Home dial_string write support (requires DLE escaping for embedded control characters)
|
||||||
|
|||||||
Reference in New Issue
Block a user