refactor: Rename emitter to agent, update related files and logging paths
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -24,8 +24,8 @@ dist/
|
|||||||
# -------------------------
|
# -------------------------
|
||||||
# Logs + runtime artifacts
|
# Logs + runtime artifacts
|
||||||
# -------------------------
|
# -------------------------
|
||||||
emitter_logs/*
|
agent_logs/*
|
||||||
!emitter_logs/.gitkeep # keep the folder but ignore its contents
|
!agent_logs/.gitkeep # keep the folder but ignore its contents
|
||||||
|
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
|||||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,12 +1,18 @@
|
|||||||
# Changelog
|
# 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/),
|
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).
|
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
|
### Changed
|
||||||
- Removed roster CSV dependency and all Dropbox refresh/hot-reload logic; heartbeat now only enumerates `.MLG` files.
|
- 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.
|
- 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
|
### Changed
|
||||||
- Reset versioning from legacy `v5.9 beta` to **v1.0.0** (clean semver baseline).
|
- 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.
|
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
|
## 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:
|
The script will:
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ The script will:
|
|||||||
2. Sniff each file header for the unit ID.
|
2. Sniff each file header for the unit ID.
|
||||||
3. Print a status line for each detected unit (OK / Pending / Missing).
|
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`.
|
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
|
||||||
|
|
||||||
Logs are stored under `emitter_logs/`.
|
Logs are stored under `agent_logs/`.
|
||||||
Git ignores all log files but keeps the folder itself.
|
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)**.
|
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.
|
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
|
**Target**: Windows 7 + Python 3.8.10
|
||||||
**Baseline**: v5_4 (no logic changes)
|
**Baseline**: v5_4 (no logic changes)
|
||||||
|
|
||||||
## Files
|
## 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)
|
- config.ini — your config (already included)
|
||||||
- series3_roster.csv — your roster (already included, this auto updates from a URL to a dropbox file)
|
- series3_roster.csv — your roster (already included, this auto updates from a URL to a dropbox file)
|
||||||
- requirements.txt — none beyond stdlib
|
- requirements.txt — none beyond stdlib
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
3) Open CMD:
|
3) Open CMD:
|
||||||
```cmd
|
```cmd
|
||||||
cd C:\SeismoEmitter
|
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`.)
|
(If the console shows escape codes on Win7, set `COLORIZE = False` in `config.ini`.)
|
||||||
|
|
||||||
@@ -23,4 +23,4 @@
|
|||||||
- Heartbeat prints Local/UTC timestamps
|
- Heartbeat prints Local/UTC timestamps
|
||||||
- One line per active roster unit with OK/Pending/Missing, Age, Last, File
|
- One line per active roster unit with OK/Pending/Missing, Age, Last, File
|
||||||
- Unexpected units block shows .MLG not in roster
|
- 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 Heartbeat Settings ---
|
||||||
API_ENABLED = true
|
API_ENABLED = true
|
||||||
@@ -19,7 +19,7 @@ MISSING_HOURS = 24
|
|||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
ENABLE_LOGGING = True
|
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
|
LOG_RETENTION_DAYS = 30
|
||||||
|
|
||||||
# Console colors - (Doesn't work on windows 7)
|
# 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:
|
Environment:
|
||||||
- Python 3.8 (Windows 7 compatible)
|
- Python 3.8 (Windows 7 compatible)
|
||||||
@@ -31,16 +31,16 @@ from socket import gethostname
|
|||||||
|
|
||||||
# ---------------- Config ----------------
|
# ---------------- Config ----------------
|
||||||
def load_config(path: str) -> Dict[str, Any]:
|
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 = configparser.ConfigParser(inline_comment_prefixes=(";", "#"))
|
||||||
cp.optionxform = str # preserve key case
|
cp.optionxform = str # preserve key case
|
||||||
with open(path, "r", encoding="utf-8") as f:
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
txt = f.read()
|
txt = f.read()
|
||||||
# Ensure we have a section header
|
# Ensure we have a section header
|
||||||
if not re.search(r"^\s*\[", txt, flags=re.M):
|
if not re.search(r"^\s*\[", txt, flags=re.M):
|
||||||
txt = "[emitter]\n" + txt
|
txt = "[agent]\n" + txt
|
||||||
cp.read_string(txt)
|
cp.read_string(txt)
|
||||||
sec = cp["emitter"]
|
sec = cp["agent"]
|
||||||
|
|
||||||
def get_str(k: str, dflt: str) -> str:
|
def get_str(k: str, dflt: str) -> str:
|
||||||
return sec.get(k, dflt).strip()
|
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)),
|
"OK_HOURS": float(get_int("OK_HOURS", 12)),
|
||||||
"MISSING_HOURS": float(get_int("MISSING_HOURS", 24)),
|
"MISSING_HOURS": float(get_int("MISSING_HOURS", 24)),
|
||||||
"ENABLE_LOGGING": get_bool("ENABLE_LOGGING", True),
|
"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),
|
"LOG_RETENTION_DAYS": get_int("LOG_RETENTION_DAYS", 30),
|
||||||
"COLORIZE": get_bool("COLORIZE", False), # Win7 default off
|
"COLORIZE": get_bool("COLORIZE", False), # Win7 default off
|
||||||
"MLG_HEADER_BYTES": max(256, min(get_int("MLG_HEADER_BYTES", 2048), 65536)),
|
"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_URL": get_str("API_URL", ""),
|
||||||
"API_INTERVAL_SECONDS": get_int("API_INTERVAL_SECONDS", 300),
|
"API_INTERVAL_SECONDS": get_int("API_INTERVAL_SECONDS", 300),
|
||||||
"SOURCE_ID": get_str("SOURCE_ID", gethostname()),
|
"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:
|
with open(path, "a", encoding="utf-8") as f:
|
||||||
f.write("{} {}\n".format(datetime.now(timezone.utc).isoformat(), msg))
|
f.write("{} {}\n".format(datetime.now(timezone.utc).isoformat(), msg))
|
||||||
except Exception:
|
except Exception:
|
||||||
# Logging must never crash the emitter
|
# Logging must never crash the agent
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ def build_sfm_payload(units_dict: Dict[str, Dict[str, Any]], cfg: Dict[str, Any]
|
|||||||
|
|
||||||
payload = {
|
payload = {
|
||||||
"source_id": cfg.get("SOURCE_ID", gethostname()),
|
"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,
|
"timestamp": now_iso,
|
||||||
"units": [],
|
"units": [],
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user