• serversdown released this 2026-06-10 14:57:45 -04:00 | 0 commits to main since this release

    [0.13.3] - 2026-06-05
    Calibration sync from SFM events. Closes the manual data-entry loop on calibration dates — Terra-View now pulls device.calibration_date from each seismograph's most recent event sidecar once a day and updates RosterUnit.last_calibrated when the device reports something fresher than what's stored. Manual edits still win when they're newer than the latest event; a fresh event arriving later supersedes the manual edit. Adds a "Sync now" button under Settings → Advanced → Calibration Defaults for on-demand runs, and a docs/ROADMAP.md to track in-flight + deferred work.

    Added
    Calibration sync service (backend/services/calibration_sync.py). Per-unit: fetches /db/events?serial={id}&limit=1 then /db/events/{event_id}/sidecar via the SFM proxy, reads device.calibration_date, and writes it to RosterUnit.last_calibrated with next_calibration_due recomputed from UserPreferences.calibration_interval_days. Every change is logged in UnitHistory with source='sfm_event' and notes="Synced from event {id}" so the unit detail history timeline reflects auto-sync activity alongside manual edits.
    Conflict rule: events-as-truth, manual wins when newer. Three outcomes per unit:
    already_in_sync — stored date already matches the event's calibration date.
    skipped_manual_newer — the latest UnitHistory change for last_calibrated happened after the event's timestamp, so the manual edit is preserved. Only a future event can supersede it.
    updated — the event is newer (or no manual edit exists), so the stored date is replaced.
    Daily background job at 03:15 local via the schedule library + a worker thread (modeled on backup_scheduler.py). Started in main.py's startup hook, stopped on shutdown. Does not run on boot — first sync after a server start fires at the next 03:15.
    POST /api/calibration/sync — runs a full sync immediately and returns a summary {checked, updated, skipped_manual_newer, already_in_sync, no_event, no_sidecar, no_cal_in_sidecar, errors, results: [...]}. Powers the Settings button.
    GET /api/calibration/sync/status — returns scheduler state + the last run's summary including per-unit {unit_id, action, old, new, event_id} rows. Useful for diagnostics: curl localhost:8001/api/calibration/sync/status | jq.
    Settings UI: "Sync from SFM events" section under the Calibration Defaults card (Advanced tab). Click "Sync now" → result line shows counts: Checked N · Updated N · Already in sync N · Manual kept N · No event N.
    docs/ROADMAP.md — first-pass roadmap pulling deferred items from CLAUDE.md's focus block, in-code TODOs (photos.py GPS migration → MonitoringLocation, device_controller.py SFM Phase 2 stubs, modem_dashboard.py ModemManager backend, dashboard.html geocoding), and the README's long-standing "Future Enhancements" wishlist. Grouped into In Flight / Near-Term / Medium-Term / Wishlist; intended as a living document.
    Fixed
    Prod startup crash: ModuleNotFoundError: No module named 'schedule'. The schedule library wasn't pinned in requirements.txt even though backend/services/backup_scheduler.py has been using it since v0.4.x — the dev image happened to have it from an earlier manual pip install, but a clean prod rebuild dropped it. Added schedule==1.2.2 so the new calibration scheduler (and the existing backup scheduler) survive a clean rebuild.

    What's Changed

    • update to 0.13.3 in #57

    Contributors

    Full Changelog: v0.12.3...v0.13.3

    Downloads