19548466ad
None of v1.5.1 / v1.5.2 / v1.5.3 / v1.5.4 ever shipped — they only existed as separate CHANGELOG entries on this unmerged feature branch. SemVer ties version numbers to releases, not commits. From a field machine's perspective, the world skips straight from v1.4.4 to whatever the next built-and-pushed installer is tagged. Revert VERSION / AppVersion / module-docstring version comments to v1.5.0 across: - series3_watcher.py (VERSION = "1.5.0") - installer.iss (AppVersion=1.5.0) - series3_tray.py (docstring) - settings_dialog.py (docstring) - README.md (banner + footer) Consolidate the four split CHANGELOG sections into a single "## [Unreleased] — v1.5.0" entry covering all the work in one release. Configuration key table consolidated into one place. No commit history rewriting — the per-commit code changes still make sense as logical units for code review; only the surface- level version metadata + CHANGELOG narrative was misleading. Going forward: accumulate work-in-progress under an "[Unreleased]" heading, bump VERSION only at actual release time.
184 lines
12 KiB
Markdown
184 lines
12 KiB
Markdown
# Changelog
|
|
All notable changes to **Series 3 Watcher** will be documented in this file.
|
|
|
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
|
---
|
|
|
|
## [Unreleased] — v1.5.0
|
|
|
|
First release of the SFM event forwarder.
|
|
|
|
### Added — SFM event forwarder
|
|
- **Forward Blastware event binaries (+ paired BW ACH ASCII reports) to an SFM server.** When `SFM_FORWARD_ENABLED=true` and `SFM_URL` is set, every event binary in the BW ACH watch folder is POSTed as multipart to `/db/import/blastware_file` along with its `<stem>_<ext>_ASCII.TXT` partner report (BW ACH convention; manual-export `<binary>.TXT` is also supported as a fallback). SFM parses the report and indexes the full per-channel stats (PPV, ZC Freq, Time of Peak, Peak Acceleration / Displacement, Peak Vector Sum + time, sensor self-check Pass/Fail, monitor-log timestamps) into a searchable database — no codec decoding required.
|
|
- **Idempotent forwarding.** Forwarded files are tracked by sha256 in a JSON state file (default `<log dir>/sfm_forwarded.json`, override via `SFM_STATE_FILE`). Re-scans don't re-POST and the state survives restarts / auto-updates.
|
|
- **Quiescence + grace-period guards.** Files modified within `SFM_QUIESCENCE_SECONDS` (default 5s) are skipped to avoid forwarding mid-write. If a binary's report partner hasn't appeared after `SFM_MISSING_REPORT_GRACE_SECONDS` (default 60s), the binary is forwarded alone rather than blocking forever.
|
|
- **Per-pass rate cap.** `SFM_MAX_FORWARDS_PER_PASS` (default 500) drips first-deploy backfill instead of hammering the SFM server in one burst. At 60-second `SFM_FORWARD_INTERVAL_SECONDS` cadence that's ~30K events/hour throughput. Set to `0` for unlimited. Scan walks oldest-first so backfill advances chronologically and successive scans reliably progress.
|
|
- **`event_forwarder.py --seed-state` CLI mode.** Walks the watch folder once, sha256s every in-window event, and marks them all as already-forwarded *without* POSTing anything. Recommended pre-deploy workflow on machines with a large historical archive — flip `SFM_FORWARD_ENABLED=true` after seeding and only events that appear from then on get forwarded.
|
|
- **SFM Forward tab in the Settings dialog** with: Forward checkbox, SFM URL + Test button (GETs `/health`), Forward Interval / Quiescence / Missing-Report Grace / HTTP Timeout / Max Events Per Pass spinboxes, State File entry with Browse... Save-time guard: enabling forwarding without a URL shows a validation error.
|
|
- **Histogram-aware log clarity.** Histogram events (extensions ending in `H`) don't get auto-exported reports from BW; the log distinguishes that case (`(histogram, no report expected)`) from a waveform with unexpectedly missing report (`no report ⚠`).
|
|
- **README "First-time deployment" section** documenting the seed-state workflow + the rate cap as belt-and-suspenders for safe rollout on machines with hundreds of thousands of historical events.
|
|
- 31 new unit tests in `test_event_forwarder.py` covering filename matching, state idempotency, scan logic (quiescence / grace period / max age / already-forwarded / TXT pairing), multipart byte shape, rate cap (oldest-first, cap=0 unlimited, cap=N enforcement), seed-state mode (in-window seeding / max-age skip / end-to-end skip-after-seed / idempotent re-runs), histogram classification, and an end-to-end POST against a stdlib fake server.
|
|
|
|
### Configuration
|
|
|
|
New `[agent]` keys (all default-off — existing 1.4.x deployments don't change behaviour on auto-update):
|
|
|
|
| Key | Default | Notes |
|
|
|---|---|---|
|
|
| `SFM_FORWARD_ENABLED` | `false` | Master toggle for the forwarder |
|
|
| `SFM_URL` | empty | e.g. `http://10.0.0.44:8200` |
|
|
| `SFM_FORWARD_INTERVAL_SECONDS` | `60` | Scan-and-forward cadence |
|
|
| `SFM_QUIESCENCE_SECONDS` | `5` | Skip files modified in the last N seconds |
|
|
| `SFM_MISSING_REPORT_GRACE_SECONDS` | `60` | Forward without TXT after this delay |
|
|
| `SFM_HTTP_TIMEOUT` | `60` | Per-request HTTP timeout |
|
|
| `SFM_STATE_FILE` | `<log dir>/sfm_forwarded.json` | Override location of the forwarded-sha256 state file |
|
|
| `SFM_MAX_FORWARDS_PER_PASS` | `500` | Per-scan cap (`0` = unlimited) |
|
|
|
|
### Compatibility
|
|
|
|
- Requires SFM server v0.16+ (the `/db/import/blastware_file` endpoint that accepts paired `_ASCII.TXT` reports + the BW-report label normalisation — released alongside this watcher version on the seismo-relay side).
|
|
|
|
## [1.4.4] - 2026-03-17
|
|
|
|
### Removed
|
|
- `OK_HOURS` and `MISSING_HOURS` config keys and Settings dialog fields removed — unit status thresholds are calculated by terra-view from raw `age_minutes`, not by the watcher. These fields had no effect since v1.4.2.
|
|
|
|
## [1.4.3] - 2026-03-17
|
|
|
|
### Added
|
|
- Auto-updater now logs all activity to the watcher log file (`[updater]` prefix) — silent failures are now visible.
|
|
- Configurable update source: `UPDATE_SOURCE = gitea` (default), `url`, or `disabled`. In `url` mode the watcher fetches `version.txt` and the `.exe` from a custom base URL (e.g. terra-view) instead of the Gitea API — enables updates on isolated networks that cannot reach Gitea. `disabled` turns off automatic checks while keeping the remote push path (from terra-view) functional.
|
|
- New **Updates** tab in the Settings dialog to configure `UPDATE_SOURCE` and `UPDATE_URL`.
|
|
|
|
### Fixed
|
|
- Downloaded `.exe` is now validated before applying: absolute size floor (100 KB), relative size floor (50% of current exe), and MZ magic bytes check. A corrupt or truncated download is now rejected and logged rather than silently overwriting the live exe.
|
|
- Swap `.bat` now backs up the current exe as `<exe>.old` before overwriting, providing a manual rollback copy if needed.
|
|
- Swap `.bat` retry loop is now capped at 5 attempts — was previously infinite if the file remained locked.
|
|
- Swap `.bat` now cleans up the temp download file on both success and failure.
|
|
|
|
## [1.4.2] - 2026-03-17
|
|
|
|
### Changed
|
|
- Tray icon color now reflects watcher + API health rather than unit ages — green=API OK, amber=API disabled, red=API failing, purple=watcher error.
|
|
- Status menu text updated to show `Running — API OK | N unit(s) | scan Xm ago`.
|
|
- Units submenu removed from tray — status tracking for individual units is handled by terra-view, not the watcher.
|
|
- Unit list still logged to console and log file for debugging, but no OK/Pending/Missing judgement applied.
|
|
- `watcher_status` field added to heartbeat payload so terra-view receives accurate watcher health data.
|
|
|
|
## [1.4.1] - 2026-03-17
|
|
|
|
### Fixed
|
|
- `config.ini` now saves to `AppData\Local\Series3Watcher\` instead of `Program Files` — fixes permission denied error on first-run wizard save.
|
|
- Config path resolution in both `series3_tray.py` and `series3_watcher.py` updated to use `sys.frozen` + `LOCALAPPDATA` when running as a PyInstaller `.exe`.
|
|
- Status menu item now uses a callable so it updates every time the menu opens — was showing stale "Starting..." while tooltip correctly showed current status.
|
|
- Settings dialog now opens in its own thread — fixes unresponsive tabs and text fields while the watcher loop is running.
|
|
- Tray icon reverted to plain colored dot — custom icon graphic was unreadable at 16px tray size. `.ico` file is still used for the `.exe` file icon.
|
|
|
|
### Changed
|
|
- Terra-View URL field in settings wizard now accepts base URL only (e.g. `http://192.168.x.x:8000`) — `/api/series3/heartbeat` endpoint appended automatically.
|
|
- Test Connection button now hits `/health` endpoint instead of posting a fake heartbeat — no database side effects.
|
|
- "terra-view URL" label capitalized to "Terra-View URL".
|
|
- Default log path updated to `AppData\Local\Series3Watcher\agent_logs\series3_watcher.log`.
|
|
- Installer now creates `agent_logs\` folder on install.
|
|
- `BUILDING.md` added — step-by-step guide for building, releasing, and updating.
|
|
|
|
## [1.4.0] - 2026-03-12
|
|
|
|
### Added
|
|
- `series3_tray.py` — system tray launcher using `pystray` + `Pillow`. Color-coded icon (green=OK, amber=Pending, red=Missing, purple=Error, grey=Starting). Right-click menu shows live status, unit count, last scan age, Open Log Folder, and Exit.
|
|
- `run_watcher(state, stop_event)` in `series3_watcher.py` for background thread use by the tray. Shared `state` dict updated on every scan cycle with status, unit list, last scan time, and last error.
|
|
- Interruptible sleep in watcher loop — tray exit is immediate, no waiting out the full scan interval.
|
|
|
|
### Changed
|
|
- `main()` now calls `run_watcher()` — standalone behavior unchanged.
|
|
- `requirements.txt` updated to document tray dependencies (`pystray`, `Pillow`); watcher itself remains stdlib-only.
|
|
|
|
---
|
|
|
|
## [1.3.0] - 2026-03-12
|
|
|
|
### Changed
|
|
- Renamed program to "series3-watcher" and main script to `series3_watcher.py` — better reflects what it does (watches for activity) rather than implying active data emission.
|
|
- Default `SOURCE_TYPE` updated to `series3_watcher`.
|
|
- Default log filename updated to `series3_watcher.log`.
|
|
|
|
---
|
|
|
|
## [1.2.1] - 2026-03-03
|
|
|
|
### Changed
|
|
- Changed the name of the program to "series3-agent", this was done to align with the s4/thor agent and because it represents the program's functionality better.
|
|
- All instances of "emitter" changed to agent.
|
|
- config.ini added to .gitignore, replaced with a template example file.
|
|
- README.md updated to reflect changes.
|
|
|
|
---
|
|
|
|
## [1.2.0] - 2025-12-04
|
|
|
|
### Changed
|
|
- Removed roster CSV dependency and all Dropbox refresh/hot-reload logic; heartbeat now only enumerates `.MLG` files.
|
|
- Added `MAX_EVENT_AGE_DAYS` filter to ignore stale events and log when no recent activity exists.
|
|
- Simplified heartbeat output/logging to show detected units only; logging hardened to never crash the agent.
|
|
|
|
---
|
|
|
|
## [1.1.1] - 2025-12-02
|
|
|
|
### Added
|
|
- Example `config.ini` now ships with API heartbeat settings enabled (`API_ENABLED`, `API_URL`, `API_INTERVAL_SECONDS`, `SOURCE_ID`, `SOURCE_TYPE`).
|
|
|
|
---
|
|
|
|
## [1.1.0] - 2025-12-01
|
|
|
|
### Added
|
|
- Standardized SFM telemetry payload builder and periodic HTTP heartbeat POST via `urllib`.
|
|
- Config support for API heartbeat (`API_ENABLED`, `API_URL`, `API_INTERVAL_SECONDS`, `SOURCE_ID`, `SOURCE_TYPE`); payload includes file path/size metadata.
|
|
|
|
### Changed
|
|
- Refactored scanner to retain file paths and header sniff cache; reformatted logging/ANSI handling.
|
|
|
|
---
|
|
|
|
## [1.0.1] - 2025-11-20
|
|
|
|
### Added
|
|
- `API_URL` config key and `report_to_server` per-unit POST hook (adds `requests` dependency).
|
|
|
|
### Changed
|
|
- Example `config.ini` roster URL updated; merged into `main`.
|
|
|
|
---
|
|
|
|
## [1.0.0] - 2025-11-17
|
|
|
|
### Added
|
|
- **Automatic roster refresh** from Dropbox at a configurable interval (`ROSTER_REFRESH_MIN_SECONDS`).
|
|
- **Hot-reload** of roster file without restarting the script.
|
|
- **Failsafe reload:** if the new roster is missing or invalid, the previous good roster is retained.
|
|
- **Atomic roster downloads** (temp file in-place replace) to avoid partial/corrupted CSVs.
|
|
- **Startup config echo** printing WATCH_PATH, ROSTER_FILE, and ROSTER_URL visibility.
|
|
- **Active / Bench / Ignored** unit categories for clearer fleet status mapping.
|
|
|
|
### Fixed
|
|
- Removed stray `note=note_suffix` bug in the Unexpected Units section.
|
|
- Removed duplicate `import time`.
|
|
- Removed duplicate roster load during startup (roster now loads once).
|
|
- Cleaned indentation for Python 3.8 compatibility.
|
|
|
|
### Changed
|
|
- Reset versioning from legacy `v5.9 beta` to **v1.0.0** (clean semver baseline).
|
|
- Main script normalized as `series3_emitter.py` (later renamed to `series3_agent.py` in v1.2.1).
|
|
|
|
---
|
|
|
|
[Unreleased]: https://example.com/compare/v1.2.0...HEAD
|
|
[1.2.0]: https://example.com/releases/v1.2.0
|
|
[1.1.1]: https://example.com/releases/v1.1.1
|
|
[1.1.0]: https://example.com/releases/v1.1.0
|
|
[1.0.1]: https://example.com/releases/v1.0.1
|
|
[1.0.0]: https://example.com/releases/v1.0.0
|