mirror of
https://github.com/zvx-echo6/meshai.git
synced 2026-06-11 01:14:45 +02:00
feat: fire halt broadcast + tombstone all-clear (wildfire_halted / wildfire_closed)
Enable _maybe_emit_halt in firms_handler (remove return None stub) so fires with no FIRMS hotspot activity beyond halt_minimum_seconds emit a routine wildfire_halted broadcast. Add tombstone all-clear in wfigs_handler: when a fire is tombstoned and has last_broadcast_at set (i.e. previously made it to mesh), broadcast a wildfire_closed message with acres, containment, and location. Fires that were never broadcast are silently consumed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3ff819eed9
commit
f4930a388f
2 changed files with 34 additions and 1 deletions
|
|
@ -774,7 +774,6 @@ def _maybe_emit_halt(conn, *, data, now):
|
||||||
eligible because we filter on `halt_broadcast_at IS NULL OR
|
eligible because we filter on `halt_broadcast_at IS NULL OR
|
||||||
halt_broadcast_at < last_pass_at`.
|
halt_broadcast_at < last_pass_at`.
|
||||||
"""
|
"""
|
||||||
return None
|
|
||||||
minimum_s = int(adapter_config.fires.halt_minimum_seconds)
|
minimum_s = int(adapter_config.fires.halt_minimum_seconds)
|
||||||
cutoff = float(now) - float(minimum_s)
|
cutoff = float(now) - float(minimum_s)
|
||||||
row = conn.execute(
|
row = conn.execute(
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,40 @@ def handle_wfigs(normalized: dict, envelope: dict, subject: str,
|
||||||
)
|
)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("wfigs: tombstoned_at stamp failed irwin=%s", irwin_id)
|
logger.exception("wfigs: tombstoned_at stamp failed irwin=%s", irwin_id)
|
||||||
|
|
||||||
|
# All-clear broadcast: only fires that previously made it to mesh
|
||||||
|
# get a closure message. Silent for fires that were never broadcast.
|
||||||
|
if kind == "wfigs_tombstone" and irwin_id:
|
||||||
|
fire_row = conn.execute(
|
||||||
|
"SELECT incident_name, current_acres, current_contained_pct, "
|
||||||
|
"last_broadcast_at, county, state, lat, lon "
|
||||||
|
"FROM fires WHERE irwin_id = ?", (irwin_id,)
|
||||||
|
).fetchone()
|
||||||
|
if fire_row is not None and fire_row["last_broadcast_at"] is not None:
|
||||||
|
name = fire_row["incident_name"] or "(unnamed fire)"
|
||||||
|
# Build line 2 parts
|
||||||
|
parts = []
|
||||||
|
if fire_row["current_acres"] is not None:
|
||||||
|
parts.append(f"{int(fire_row['current_acres']):,} ac")
|
||||||
|
if fire_row["current_contained_pct"] is not None:
|
||||||
|
parts.append(f"{int(fire_row['current_contained_pct'])}% contained")
|
||||||
|
# Location via _location_anchor with a minimal normalized dict
|
||||||
|
loc_dict = {
|
||||||
|
"lat": fire_row["lat"], "lon": fire_row["lon"],
|
||||||
|
"county": fire_row["county"], "state": fire_row["state"],
|
||||||
|
}
|
||||||
|
anchor = _location_anchor(loc_dict)
|
||||||
|
if anchor and anchor != "(location unknown)":
|
||||||
|
parts.append(anchor)
|
||||||
|
lines = [f"✅ {name} — contained & closed"]
|
||||||
|
if parts:
|
||||||
|
lines.append(" | ".join(parts))
|
||||||
|
wire = "\n".join(lines)
|
||||||
|
if isinstance(data, dict):
|
||||||
|
data["category"] = "wildfire_closed"
|
||||||
|
data["_severity_override"] = "routine"
|
||||||
|
return wire
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# ---- active incident ----
|
# ---- active incident ----
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue