7.2 KiB
Thor Watcher
Version: 0.3.1
Micromate (Series 4) watcher agent for Terra-View fleet management. Runs as a Windows system tray application, scans THORDATA for Micromate unit activity, sends heartbeat data to Terra-View, and (optionally) forwards .IDFH/.IDFW event files to a seismo-relay SFM server.
Overview
Thor Watcher monitors C:\THORDATA\<Project>\<UM####>\*.MLG files, determines each unit's last activity from the MLG filename timestamp, and periodically posts a heartbeat payload to the Terra-View backend. It runs silently in the system tray and auto-starts on login.
Installation
- Run
thor-watcher-setup.exe - On first launch the setup wizard will appear — enter your THORDATA path and Terra-View URL
- The app starts in the system tray and launches automatically on login
Building from Source
Requires Python 3.10+ and pip on PATH.
build.bat
Produces:
dist\thor-watcher-0.3.1.exe— upload to Gitea releasedist\thor-watcher.exe— use with Inno Setup
Then run Inno Setup Compiler on installer.iss to produce thor-watcher-setup.exe.
Configuration
Config is stored at:
%LOCALAPPDATA%\ThorWatcher\config.json
Managed through the Settings dialog (right-click tray icon → Settings). A config.example.json is included as reference.
Config Keys
| Key | Type | Default | Description |
|---|---|---|---|
thordata_path |
string | C:\THORDATA |
Root THORDATA directory |
scan_interval |
integer | 60 |
Seconds between scans |
api_url |
string | "" |
Terra-View heartbeat URL (e.g. http://10.0.0.40:8000/api/series4/heartbeat) |
api_timeout |
integer | 5 |
HTTP request timeout in seconds |
api_interval |
integer | 300 |
Seconds between API heartbeat POSTs |
source_id |
string | hostname | Identifier for this machine in Terra-View |
source_type |
string | series4_watcher |
Agent type (do not change) |
local_timezone |
string | America/New_York |
Timezone of the field machine — used to convert MLG timestamps to UTC |
enable_logging |
boolean | true |
Write log file |
log_file |
string | %LOCALAPPDATA%\ThorWatcher\agent_logs\thor_watcher.log |
Log file path |
log_retention_days |
integer | 30 |
Days before log is auto-cleared |
update_source |
string | gitea |
Auto-update source: gitea, url, or disabled |
update_url |
string | "" |
Base URL for url mode (e.g. Terra-View server) |
sfm_forward_enabled |
boolean | false |
Forward .IDFH/.IDFW event files to a seismo-relay SFM server |
sfm_url |
string | "" |
Base URL of the seismo-relay SFM server (e.g. http://10.0.0.44:8200) |
sfm_forward_interval |
integer | 60 |
Seconds between forwarder passes |
sfm_quiescence_seconds |
integer | 5 |
Skip files modified within the last N seconds (avoid in-flight files) |
sfm_missing_report_grace_seconds |
integer | 60 |
Forward a binary without its .txt sidecar if it hasn't appeared after N seconds |
sfm_http_timeout |
integer | 60 |
HTTP timeout per forward POST |
sfm_state_file |
string | "" |
Path to the sha256-keyed state file. Blank → <log_dir>\thor_forwarded.json |
sfm_max_forwards_per_pass |
integer | 500 |
Cap per pass to drip-feed large backfills |
sfm_max_event_age_days |
integer | 365 |
Skip event files older than this many days |
Event Forwarding
When sfm_forward_enabled is true and sfm_url is set, Thor Watcher walks the THORDATA tree each sfm_forward_interval seconds, finds .IDFH (histogram) and .IDFW (waveform) event binaries plus their TXT/<basename>.txt ASCII sidecars, and POSTs them to seismo-relay's /db/import/idf_file endpoint.
- Idempotent. Every forwarded file is recorded by sha256 in
thor_forwarded.json. Re-scans never re-POST. - Default off. Operators must explicitly enable from the Settings → SFM Forward tab.
- Re-pair logic. If a binary is forwarded before its TXT sidecar appears (after the grace period), it's flagged
had_report=falseand re-forwarded once the TXT arrives so the SFM database row can be refreshed with device-authoritative PPV/ZCFreq/peak values. - TXT export must be enabled in Thor. Thor's TXT sidecars are not produced automatically — operators should enable TXT export so the relay can extract rich metadata. Forwards without a TXT are still useful (binary gets indexed; rich fields stay NULL).
- Backfill seeding. To skip a large historical archive on first deploy, run
python event_forwarder.py --seed-state --thordata C:\THORDATA --state <state file>before flipping the switch.
Tray Icon Colors
| Color | Meaning |
|---|---|
| Green | Running, API reporting OK (and SFM forwarder healthy when enabled) |
| Amber | Running, API disabled OR SFM forwarder failing while API is healthy |
| Red | Running, API failing |
| Purple | Error — check logs |
| Grey | Starting up |
Auto-Updater
Thor Watcher checks for updates every ~5 minutes. When a new release is found it downloads and validates the exe, then relaunches via a swap bat — no manual intervention needed.
Update sources:
gitea— checks the Gitea release page (default)url— fetchesversion.txtandthor-watcher.exefrom a custom server (e.g. Terra-View)disabled— no automatic checks; remote push from Terra-View still works
Download validation: 100 KB minimum size, 50% relative size floor vs current exe, MZ magic bytes check.
Remote update push from Terra-View Watcher Manager works regardless of update_source setting.
Heartbeat Payload
Posted to api_url on each API interval:
{
"source_id": "THOR-PC",
"source_type": "series4_watcher",
"version": "0.3.1",
"generated_at": "2026-03-20T14:30:00Z",
"log_tail": ["...last 25 log lines..."],
"units": [
{
"unit_id": "UM11719",
"last_call": "2026-03-20T13:18:00Z",
"age_minutes": 72,
"mlg_path": "C:\\THORDATA\\Project A\\UM11719\\UM11719_20260320131800.MLG",
"project_hint": "Project A"
}
]
}
THORDATA Directory Structure
C:\THORDATA\
├── Project A\
│ ├── UM11719\
│ │ ├── UM11719_20260320131800.MLG
│ │ └── UM11719_20260319095430.MLG
│ └── UM12345\
│ └── UM12345_20260318091530.MLG
└── Project B\
└── UM98765\
└── UM98765_20260301082215.MLG
Troubleshooting
Tray icon is amber: API URL is not configured or disabled — open Settings and enter Terra-View URL.
Tray icon is red: API is failing — check Terra-View is reachable, URL is correct, and the network is up.
Units showing wrong time in Terra-View: Check local_timezone in Settings matches the field machine's timezone.
No units found: Verify thordata_path is correct and MLG files exist following the UM####_YYYYMMDDHHMMSS.MLG naming convention.
Auto-updater not working: Check the log file for [updater] lines. On first deploy, verify the Gitea release has a thor-watcher-X.X.X.exe asset (not a setup exe).
Version History
See CHANGELOG.md for detailed version history.
Proprietary — Terra-Mechanics Inc. Internal use only.