Merge: dev to main, refactor rename #1
4
.gitignore
vendored
4
.gitignore
vendored
@@ -24,8 +24,8 @@ dist/
|
||||
# -------------------------
|
||||
# Logs + runtime artifacts
|
||||
# -------------------------
|
||||
emitter_logs/*
|
||||
!emitter_logs/.gitkeep # keep the folder but ignore its contents
|
||||
agent_logs/*
|
||||
!agent_logs/.gitkeep # keep the folder but ignore its contents
|
||||
|
||||
*.log
|
||||
|
||||
|
||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,12 +1,18 @@
|
||||
# Changelog
|
||||
All notable changes to **Series3 Emitter** will be documented in this file.
|
||||
All notable changes to **Series3 Agent** 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]
|
||||
## [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.
|
||||
|
||||
---
|
||||
|
||||
@@ -15,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### 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 emitter.
|
||||
- Simplified heartbeat output/logging to show detected units only; logging hardened to never crash the agent.
|
||||
|
||||
---
|
||||
|
||||
@@ -65,7 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Changed
|
||||
- Reset versioning from legacy `v5.9 beta` to **v1.0.0** (clean semver baseline).
|
||||
- Main script normalized as `series3_emitter.py`.
|
||||
- Main script normalized as `series3_emitter.py` (later renamed to `series3_agent.py` in v1.2.1).
|
||||
|
||||
---
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -1,4 +1,4 @@
|
||||
# Series3-Emitter v1.2
|
||||
# Series3 Ingest Agent v1.2
|
||||
|
||||
A lightweight Python script that monitors Instantel **Series 3 (Minimate)** call-in activity on a Blastware server.
|
||||
|
||||
@@ -28,9 +28,9 @@ Install dependencies with:
|
||||
|
||||
## Usage
|
||||
|
||||
Run the emitter from the folder containing the script:
|
||||
Run the agent from the folder containing the script:
|
||||
|
||||
`python series3_emitter.py`
|
||||
`python series3_agent.py`
|
||||
|
||||
The script will:
|
||||
|
||||
@@ -38,7 +38,7 @@ The script will:
|
||||
2. Sniff each file header for the unit ID.
|
||||
3. Print a status line for each detected unit (OK / Pending / Missing).
|
||||
4. Optionally POST a heartbeat payload on an interval when `API_ENABLED=true`.
|
||||
5. Write logs into the `emitter_logs/` folder and auto-clean old logs.
|
||||
5. Write logs into the `agent_logs/` folder and auto-clean old logs.
|
||||
|
||||
---
|
||||
|
||||
@@ -65,7 +65,7 @@ Key fields:
|
||||
|
||||
## Logs
|
||||
|
||||
Logs are stored under `emitter_logs/`.
|
||||
Logs are stored under `agent_logs/`.
|
||||
Git ignores all log files but keeps the folder itself.
|
||||
|
||||
---
|
||||
@@ -74,7 +74,7 @@ Git ignores all log files but keeps the folder itself.
|
||||
|
||||
This repo follows **Semantic Versioning (SemVer)**.
|
||||
|
||||
Current release: **v1.2.0** — rosterless scanning with API heartbeat option.
|
||||
Current release: **v1.2.1** — renamed to series3 ingest agent.
|
||||
See `CHANGELOG.md` for details.
|
||||
|
||||
---
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Series 3 Emitter — v1_0(py38-safe) for DL2
|
||||
# Series 3 Ingest Agent — v1_0(py38-safe) for DL2
|
||||
|
||||
**Target**: Windows 7 + Python 3.8.10
|
||||
**Baseline**: v5_4 (no logic changes)
|
||||
|
||||
## Files
|
||||
- series3_emitter_v1_0_py38.py — main script (py38-safe)
|
||||
- series3_agent_v1_0_py38.py — main script (py38-safe)
|
||||
- config.ini — your config (already included)
|
||||
- series3_roster.csv — your roster (already included, this auto updates from a URL to a dropbox file)
|
||||
- requirements.txt — none beyond stdlib
|
||||
@@ -15,7 +15,7 @@
|
||||
3) Open CMD:
|
||||
```cmd
|
||||
cd C:\SeismoEmitter
|
||||
python series3_emitter_v1_0_py38.py
|
||||
python series3_agent_v1_0_py38.py
|
||||
```
|
||||
(If the console shows escape codes on Win7, set `COLORIZE = False` in `config.ini`.)
|
||||
|
||||
@@ -23,4 +23,4 @@
|
||||
- Heartbeat prints Local/UTC timestamps
|
||||
- One line per active roster unit with OK/Pending/Missing, Age, Last, File
|
||||
- Unexpected units block shows .MLG not in roster
|
||||
- emitter.log rotates per LOG_RETENTION_DAYS
|
||||
- agent.log rotates per LOG_RETENTION_DAYS
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[emitter]
|
||||
[agent]
|
||||
|
||||
# --- API Heartbeat Settings ---
|
||||
API_ENABLED = true
|
||||
@@ -19,7 +19,7 @@ MISSING_HOURS = 24
|
||||
|
||||
# Logging
|
||||
ENABLE_LOGGING = True
|
||||
LOG_FILE = C:\SeismoEmitter\emitter_logs\series3_emitter.log
|
||||
LOG_FILE = C:\SeismoEmitter\agent_logs\series3_agent.log
|
||||
LOG_RETENTION_DAYS = 30
|
||||
|
||||
# Console colors - (Doesn't work on windows 7)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""
|
||||
Series 3 Emitter — v1.2.0
|
||||
Series 3 Ingest Agent — v1.2.1
|
||||
|
||||
Environment:
|
||||
- Python 3.8 (Windows 7 compatible)
|
||||
@@ -31,16 +31,16 @@ from socket import gethostname
|
||||
|
||||
# ---------------- Config ----------------
|
||||
def load_config(path: str) -> Dict[str, Any]:
|
||||
"""Load INI with tolerant inline comments and a required [emitter] section."""
|
||||
"""Load INI with tolerant inline comments and a required [agent] section."""
|
||||
cp = configparser.ConfigParser(inline_comment_prefixes=(";", "#"))
|
||||
cp.optionxform = str # preserve key case
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
txt = f.read()
|
||||
# Ensure we have a section header
|
||||
if not re.search(r"^\s*\[", txt, flags=re.M):
|
||||
txt = "[emitter]\n" + txt
|
||||
txt = "[agent]\n" + txt
|
||||
cp.read_string(txt)
|
||||
sec = cp["emitter"]
|
||||
sec = cp["agent"]
|
||||
|
||||
def get_str(k: str, dflt: str) -> str:
|
||||
return sec.get(k, dflt).strip()
|
||||
@@ -63,7 +63,7 @@ def load_config(path: str) -> Dict[str, Any]:
|
||||
"OK_HOURS": float(get_int("OK_HOURS", 12)),
|
||||
"MISSING_HOURS": float(get_int("MISSING_HOURS", 24)),
|
||||
"ENABLE_LOGGING": get_bool("ENABLE_LOGGING", True),
|
||||
"LOG_FILE": get_str("LOG_FILE", r"C:\SeismoEmitter\emitter_logs\series3_emitter.log"),
|
||||
"LOG_FILE": get_str("LOG_FILE", r"C:\SeismoEmitter\agent_logs\series3_agent.log"),
|
||||
"LOG_RETENTION_DAYS": get_int("LOG_RETENTION_DAYS", 30),
|
||||
"COLORIZE": get_bool("COLORIZE", False), # Win7 default off
|
||||
"MLG_HEADER_BYTES": max(256, min(get_int("MLG_HEADER_BYTES", 2048), 65536)),
|
||||
@@ -75,7 +75,7 @@ def load_config(path: str) -> Dict[str, Any]:
|
||||
"API_URL": get_str("API_URL", ""),
|
||||
"API_INTERVAL_SECONDS": get_int("API_INTERVAL_SECONDS", 300),
|
||||
"SOURCE_ID": get_str("SOURCE_ID", gethostname()),
|
||||
"SOURCE_TYPE": get_str("SOURCE_TYPE", "series3_emitter"),
|
||||
"SOURCE_TYPE": get_str("SOURCE_TYPE", "series3_ingest_agent"),
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ def log_message(path: str, enabled: bool, msg: str) -> None:
|
||||
with open(path, "a", encoding="utf-8") as f:
|
||||
f.write("{} {}\n".format(datetime.now(timezone.utc).isoformat(), msg))
|
||||
except Exception:
|
||||
# Logging must never crash the emitter
|
||||
# Logging must never crash the agent
|
||||
pass
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@ def build_sfm_payload(units_dict: Dict[str, Dict[str, Any]], cfg: Dict[str, Any]
|
||||
|
||||
payload = {
|
||||
"source_id": cfg.get("SOURCE_ID", gethostname()),
|
||||
"source_type": cfg.get("SOURCE_TYPE", "series3_emitter"),
|
||||
"source_type": cfg.get("SOURCE_TYPE", "series3_ingest_agent"),
|
||||
"timestamp": now_iso,
|
||||
"units": [],
|
||||
}
|
||||
Reference in New Issue
Block a user