diff --git a/CHANGELOG.md b/CHANGELOG.md index 85936fa..3a9f718 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,33 @@ All notable changes to seismo-relay are documented here. --- +## v0.16.0 — 2026-05-11 + +The "BW ACH ingestion" release. When paired with **series3-watcher v1.5.0**, every Blastware ACH event (binary + `_ASCII.TXT` report) lands in SeismoDb with device-authoritative peaks, project metadata, sensor self-check, and ZC/Time-of-Peak data — without depending on the still-undecoded waveform body codec. This is the end-to-end product win discussed in v0.15.0's "out of scope" notes: sortable / filterable monthly-summary review of historical events, populated from the BW ASCII export rather than re-decoded samples. + +### Added — `/db/import/blastware_file` rich-metadata ingestion + +- **Paired BW ASCII reports.** The endpoint now accepts the `__ASCII.TXT` partner BW writes alongside each event. Pairing handles both filename conventions: ACH (`M529LK44_AB0_ASCII.TXT`) and manual-export (`M529LK44.AB0.TXT`). When both present, ACH wins. +- **`minimateplus/bw_ascii_report.py`** (new) — parser + `BwAsciiReport` dataclass for BW's per-event ASCII export. Handles every field BW writes: identity, trigger config, per-channel PPV / ZC Freq / Time of Peak / Peak Acceleration / Peak Displacement, Peak Vector Sum + time, MicL PSPL / Time of Peak / ZC Freq, sensor self-check (Test Freq / Test Ratio / Test Amplitude / Pass-Fail per channel), monitor log, PC SW version. +- **Position-based user-notes parsing.** BW's Compliance Setup → Notes tab labels (Project / Client / User Name / Seis Loc) are *operator-editable* — an operator can rename them to "Building:", "Site Address:", etc. Rather than maintain a label-spelling map, the parser uses positional matching between the `Units :` and `Geo Range :` anchors in the ASCII output. The four canonical slots (project / client / operator / sensor_location) populate by position regardless of label; the original labels BW wrote are preserved in `report.user_note_labels` for downstream UIs (terra-view) to display verbatim. +- **`bw_report` sidecar block.** New top-level block in `.sfm.json` carrying the parsed BW report (trigger config, peaks with per-channel stats, mic block, sensor_check, monitor_log, PC SW version, operator-label labels). +- **`apply_report_to_event(event, report)` helper.** Overlays the report's device-authoritative fields onto an in-memory `Event` so `SeismoDb.insert_events()` writes correct DB columns instead of the broken-codec values from `_peaks_from_samples()`. + +### Fixed — three compounding bugs that left forwarded events with garbage data + +- **Import endpoint inserted under `serial="UNKNOWN"`.** `_serial_from_event(ev)` was a stub that always returned `None`; the BW-filename-decoded serial that `WaveformStore` had already resolved was never surfaced to `db.insert_events`. Now uses `rec["serial"]` as the authoritative source. `scripts/repair_unknown_serials.py` repairs existing DB rows. +- **`/db/units` ignored events from non-ACH ingest paths.** `query_units()` only aggregated from `ach_sessions` — events that arrived via `save_imported_bw()` were never visible in the fleet overview even though they populated `events` correctly. Now unions both tables. +- **Re-imports left stale DB rows.** The `IntegrityError` handler in `insert_events()` only refreshed filename / sidecar columns when a duplicate `(serial, timestamp)` arrived. Peak values, project info, sample_rate, record_type stayed locked at whatever the first (often broken-codec) insert wrote. Now the upsert path refreshes every device-authoritative column from the new data while preserving `false_trigger` and immutable fields (`id`, `created_at`). +- **Server-side TXT pairing only knew the legacy convention.** The endpoint stripped `.TXT` and looked up `` — which works for manual exports (`.TXT`) but not BW ACH (`__ASCII.TXT`). Reports were arriving in the multipart but silently dropped. Now recognises both conventions and registers each report under all matching binary names. + +### Migration + +For existing deployments where events were forwarded by an older watcher (broken pairing) or imported during the UNKNOWN-bucketing window: + +1. `python -m scripts.repair_unknown_serials --db --apply` to re-attribute `serial="UNKNOWN"` rows. +2. Delete the watcher's `sfm_forwarded.json` state file and let it re-forward. The server's upsert path will refresh the existing DB rows with the report's authoritative values. +3. Operator review state (`false_trigger`, sidecar `review` block) is preserved across the re-import. + ## v0.15.0 — 2026-05-07 ### Added diff --git a/README.md b/README.md index 9590923..7bddb42 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# seismo-relay `v0.15.0` +# seismo-relay `v0.16.0` A ground-up replacement for **Blastware** — Instantel's aging Windows-only software for managing MiniMate Plus seismographs. @@ -14,11 +14,12 @@ over direct RS-232 or cellular modem (Sierra Wireless RV50 / RV55). > byte-perfect against Blastware captures across 2-sec, 3-sec, and 10-sec > events.** Generated `.G10` / `.AB0` files open cleanly in Blastware with > full Event Reports, frequency analysis, and waveform plots. -> **v0.15.0 (2026-05-07)** adds layered per-event storage (BW binary + -> raw 5A pickle + HDF5 + `.sfm.json` sidecar), a plot-ready -> `sfm.plot.v1` JSON shape with server-side ADC-to-physical-units -> conversion, and a BW-file importer for ingesting externally-produced -> events. See [CHANGELOG.md](CHANGELOG.md) for full version history. +> **v0.16.0 (2026-05-11)** adds BW ASCII report ingestion to +> `/db/import/blastware_file` — paired with **series3-watcher v1.5.0**, +> every Blastware ACH event lands in SeismoDb with device-authoritative +> peaks, project metadata, sensor self-check, and ZC/Time-of-Peak data, +> without depending on the still-undecoded waveform body codec. +> See [CHANGELOG.md](CHANGELOG.md) for full version history. --- diff --git a/minimateplus/event_file_io.py b/minimateplus/event_file_io.py index ae76064..a415599 100644 --- a/minimateplus/event_file_io.py +++ b/minimateplus/event_file_io.py @@ -47,7 +47,7 @@ SIDECAR_KIND = "sfm.event" # bumped without a `pip install` re-run — leading to confusing stale # version stamps in sidecars. Bump this constant and CHANGELOG.md # together at release time. -TOOL_VERSION = "0.15.0" +TOOL_VERSION = "0.16.0" try: # Best-effort: prefer the installed metadata when it's NEWER than the diff --git a/pyproject.toml b/pyproject.toml index 5286aa6..70530de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "seismo-relay" -version = "0.15.0" +version = "0.16.0" description = "Python client and REST server for MiniMate Plus seismographs" requires-python = ">=3.10" dependencies = [