diff --git a/README.md b/README.md index 9603039..7f8307a 100644 --- a/README.md +++ b/README.md @@ -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 software for managing MiniMate Plus seismographs. @@ -18,26 +18,27 @@ over direct RS-232 or cellular modem (Sierra Wireless RV50 / RV55). ``` 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 │ ├── transport.py ← SerialTransport, TcpTransport, SocketTransport │ ├── 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 -│ └── 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) -│ ├── server.py ← All device + DB endpoints -│ ├── database.py ← SeismoDb — SQLite persistence layer -│ └── sfm_webapp.html ← Embedded web UI (served at /) +│ ├── server.py ← Live device endpoints + DB query endpoints + caching +│ ├── database.py ← SeismoDb — SQLite persistence (events, monitor_log, ach_sessions, sessions table) +│ └── sfm_webapp.html ← Embedded web UI with Call Home config tab │ ├── bridges/ │ ├── ach_server.py ← Inbound ACH call-home server (main production server) │ ├── ach_mitm.py ← Transparent MITM proxy for capturing BW sessions │ ├── s3-bridge/ ← RS-232 serial bridge (capture tool) │ ├── 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 │ ├── parsers/ @@ -101,21 +102,28 @@ python seismo_lab.py Each call dials the device, does its work, and closes the connection. TCP connections are retried once on `ProtocolError` to handle cold-boot timing. -**Caching** — frequently-polled endpoints are cached in-process to avoid -redundant TCP round-trips: +**In-memory caching** — frequently-polled endpoints avoid 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/events` | Count-probe fast path (~2s); full download only when new events detected | | `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/config` | Writes compliance config; invalidates cache | -| `POST` | `/device/monitor/start` | Sends SUB 0x96 | -| `POST` | `/device/monitor/stop` | Sends SUB 0x97 | +| `POST` | `/device/config` | Writes compliance config; invalidates info + events cache | +| `POST` | `/device/config/project` | Patches project/client/operator/sensor_location strings | +| `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): ``` @@ -152,21 +160,33 @@ client = MiniMateClient(transport=TcpTransport("1.2.3.4", 12345), timeout=30.0) with client: # Read - info = client.connect() # DeviceInfo — serial, firmware, compliance config - count = client.count_events() # Number of stored events - keys = client.list_event_keys() # Fast browse walk — event keys only, no download - events = client.get_events() # Full download: headers + peaks + metadata - monitor = client.get_monitor_status() # Battery, memory, is_monitoring flag - log = client.get_monitor_log_entries() # Monitoring intervals (partial 0x2C records) + info = client.connect() # DeviceInfo — serial, firmware, compliance config + count = client.count_events() # Number of stored events + keys = client.list_event_keys() # Fast browse walk — event keys only, no download + events = client.get_events() # Full download: headers + peaks + metadata + monitor = client.get_monitor_status() # Battery, memory, is_monitoring flag + 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 client.apply_config( 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, + geo_range="Normal", # Normal (10.000 in/s) / Sensitive (1.25 in/s) project="Bridge Inspection 2026", client_name="City of Portland", 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 client.start_monitoring() # SUB 0x96 @@ -182,18 +202,20 @@ existed at record time — not backfilled from the current compliance config. ## Database -`ach_server.py` writes to `bridges/captures/seismo_relay.db` (SQLite, WAL mode). -Three tables, all unit-keyed by serial number: +`ach_server.py` writes to `bridges/captures/seismo_relay.db` (SQLite, WAL mode) using the +`SeismoDb` persistence layer. Four tables, all unit-keyed by serial number: | Table | Key | Contents | |-------|-----|----------| -| `ach_sessions` | UUID | Per-call-home audit record: serial, peer IP, events_downloaded, duration | -| `events` | UUID, UNIQUE(serial, waveform_key) | Triggered events: timestamp, PPV per channel, project/client/operator strings, false_trigger flag | -| `monitor_log` | UUID, UNIQUE(serial, waveform_key) | Monitoring intervals: start/stop time, duration, geo threshold | +| `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, 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: 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 -never produce duplicate rows. Post-erase key reuse is handled automatically -via the high-water mark in `ach_state.json`. +Deduplication is by `(serial, waveform_key)` — repeat call-homes or re-runs never +produce duplicate rows. Post-erase key reuse is handled automatically via the +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 ```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 - [ ] 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 - [ ] 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)