New non-AI src/battery module (patterned after src/weather):
Every 60 s (BATTERY_CHECK_INTERVAL_MS) scans known nodes for batteryLevel <= BATTERY_ALERT_THRESHOLD (default 20).
Qualifying nodes outside their per-node cooldown (BATTERY_ALERT_COOLDOWN_MS, default 6 h) are merged into one broadcast on the pinned send channel: ⚠️ battery low: @!<hex> (<name>) <X>%[, …] — at most one message per cycle, no spam.
Mention syntax @! + 8-hex lowercase node num; name omitted when a node has none.
Node battery now also refreshed from live NODEINFO_APP packets (was sync-only): codec.ts gains PORT_NODEINFO_APP = 4 + decodeNodeInfo(), mesh service merges into node state.
New non-AI `src/battery` module (patterned after `src/weather`):
- Every 60 s (`BATTERY_CHECK_INTERVAL_MS`) scans known nodes for `batteryLevel <= BATTERY_ALERT_THRESHOLD` (default **20**).
- Qualifying nodes outside their per-node cooldown (`BATTERY_ALERT_COOLDOWN_MS`, default **6 h**) are merged into **one** broadcast on the pinned send channel: `⚠️ battery low: @!<hex> (<name>) <X>%[, …]` — at most one message per cycle, no spam.
- Mention syntax `@!` + 8-hex lowercase node num; name omitted when a node has none.
- Node battery now also refreshed from live NODEINFO_APP packets (was sync-only): `codec.ts` gains `PORT_NODEINFO_APP = 4` + `decodeNodeInfo()`, mesh service merges into node state.
Tests: 79 passed / 0 failed (13 new: threshold boundary, cooldown window, hex formatting, merged multi-node format, in-cooldown exclusion). `npm run build` clean.
Changelog + version bump included (v0.13.0).
battery_level was only populated during the initial sync; NodeInfo
frames streamed as NODEINFO_APP (port 4) now refresh deviceMetrics in
the node database so /api/nodes and downstream consumers see current
values between syncs. decodeNodeInfo + PORT_NODEINFO_APP added to the
codec, one branch in the existing packet-handling path.
BatteryAlertModule + BatteryAlertService wired into app.module like
the weather module. Every BATTERY_CHECK_INTERVAL_MS (default 60 s) the
service scans the node state backing GET /api/nodes and broadcasts a
single-packet '⚠️ @!<8-hex> battery low: <X>% (<name>)' alert for every
node at or below BATTERY_ALERT_THRESHOLD percent (default 20, <= on
purpose) not alerted within BATTERY_ALERT_COOLDOWN_MS (default 6 h,
in-memory map — resets on restart). Sends ride the pinned send channel
via MeshService.sendText like every other bot send.
Owner follow-up: 'if multiple ppl shows at once — merge messages to one'.
check() now collects every qualifying node (at/below threshold and not
within its per-node cooldown) and sends AT MOST ONE broadcast per cycle
containing all of them, recording the alert timestamp for each after
sending; nothing is sent when none qualify. Format: '⚠️ battery low:
@!<hex> (<name>) <X>%[, @!<hex> (<name>) <Y>%]' — single-node case uses
the same one-entry template. Cooldown semantics unchanged.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
New non-AI
src/batterymodule (patterned aftersrc/weather):BATTERY_CHECK_INTERVAL_MS) scans known nodes forbatteryLevel <= BATTERY_ALERT_THRESHOLD(default 20).BATTERY_ALERT_COOLDOWN_MS, default 6 h) are merged into one broadcast on the pinned send channel:⚠️ battery low: @!<hex> (<name>) <X>%[, …]— at most one message per cycle, no spam.@!+ 8-hex lowercase node num; name omitted when a node has none.codec.tsgainsPORT_NODEINFO_APP = 4+decodeNodeInfo(), mesh service merges into node state.Tests: 79 passed / 0 failed (13 new: threshold boundary, cooldown window, hex formatting, merged multi-node format, in-cooldown exclusion).
npm run buildclean.Changelog + version bump included (v0.13.0).
BatteryAlertModule + BatteryAlertService wired into app.module like the weather module. Every BATTERY_CHECK_INTERVAL_MS (default 60 s) the service scans the node state backing GET /api/nodes and broadcasts a single-packet '⚠️ @!<8-hex> battery low: <X>% (<name>)' alert for every node at or below BATTERY_ALERT_THRESHOLD percent (default 20, <= on purpose) not alerted within BATTERY_ALERT_COOLDOWN_MS (default 6 h, in-memory map — resets on restart). Sends ride the pinned send channel via MeshService.sendText like every other bot send.Owner follow-up: 'if multiple ppl shows at once — merge messages to one'. check() now collects every qualifying node (at/below threshold and not within its per-node cooldown) and sends AT MOST ONE broadcast per cycle containing all of them, recording the alert timestamp for each after sending; nothing is sent when none qualify. Format: '⚠️ battery low: @!<hex> (<name>) <X>%[, @!<hex> (<name>) <Y>%]' — single-node case uses the same one-entry template. Cooldown semantics unchanged.