Skip to content

feat(notifications): alerts you can trust - #451

Merged
joszz merged 1 commit into
mainfrom
feat/alert-reliability
Oct 11, 2026
Merged

joszz merged 1 commit into
mainfrom
feat/alert-reliability

Conversation

@joszz

@joszz joszz commented Oct 11, 2026

Copy link
Copy Markdown
Owner

Pull Request

Summary

Alerts you can trust: three notification bugs fixed, and four alerts added for data GarageStack already stored but never watched.

Fixes

  • Switching a type off now stops its push. Before, it only hid the type in the panel: the Worker pushed every alert to every subscription and the service worker showed them all. Each subscription now carries the types its device switched off (PushSubscription.ExcludedCategories, migration AddPushSubscriptionExcludedCategories), and PushSenderService leaves that device out. The in-app panel still records every alert.
  • A push switch per device. A fresh device only subscribed when the number of unticked types changed, so turning push on meant unticking and re-ticking a type. Settings now has "Push notifications on this device". The checklist no longer subscribes or unsubscribes; it only tells the server which types to leave out, so ticking a box never brings up a permission prompt. The settings section is renamed Notifications, and the permission notices sit under the switch.
  • No more hourly repeats on a sleeping car. Tyre and low EV alerts went out every hour while the latest data still showed the problem. Level alerts now go out once per report, judged by the gateway's poll stamps (LastVehicleStateAt / LastChargeStateAt), so a message the broker replays on reconnect cannot re-arm them. This is the same rule the parked alerts already used.

New alerts

Alert When Setting
Low 12V battery Below the level on several polls in a row while parked AUX_BATTERY_LOW_VOLT (12.0)
Low fuel Below the level; hybrids and plug-in hybrids only LOW_FUEL_PERCENT (15)
No data from the car Nothing reported for this long; the gateway polls a sleeping car once a day STALE_DATA_HOURS (48)
MG sign-in failed The gateway's account/lastLoginError, once per outage (until the next account/lastLogin)

LOW_EV_PERCENT (20) replaces the hardcoded low EV level, and 0 switches any of these off. The defaults match the dashboard's warning colours.

Account topics (saic/{user}/account/...) used to be dropped before any handler saw them. MqttTopicParser.TryParseAccount and the new AccountStatusHandler read them. The account is an email address, so it never reaches the log. Retained failures are ignored on resubscribe, and the gateway retries every 15 minutes, so the alert is held back while one has gone out since the last good sign-in.

Type of Change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Documentation
  • Dependency update
  • Other

Related Issues

None.

Checklist

  • Tests added or updated (935 backend, 871 frontend, all passing)
  • Linting passes (pnpm lint / dotnet build, dotnet format --verify-no-changes, vue-tsc)
  • No secrets or personal data committed
  • Responsive on mobile (settings panel checked at 1440, 390 and 320 px, English and Dutch)
  • i18n keys added for any new UI strings (en, nl; Worker resx en, nl)
  • If unraid/garagestack.xml changed: copied to joszz/unraid-community-apps after merge (four new Config entries)

Verification

  • Migration on Postgres 18: up, down and up again with an existing subscription, which comes out as {} (wants every type).
  • End to end: real Api and Worker, mosquitto, and a local fake push service standing in for two devices. Device B had low fuel and no data switched off.
    • Three sign-in failures sent one push to each device.
    • The first check sent device A low fuel, low 12V and no data, and device B only low 12V.
    • After a Worker restart (in-memory cooldowns gone, retained sign-in error replayed), nothing repeated, and a new soft tyre still reached both devices.

🤖 Generated with Claude Code

Switching a notification type off only hid it in the panel: the server
pushed every alert to every device and the service worker showed them
all. Each subscription now carries the types its device switched off
(new ExcludedCategories column), and the Worker leaves that device out
of the push. The panel still records every alert for everyone.

Settings gains a "Push notifications on this device" switch. Before, a
fresh device only subscribed when the number of unticked types changed,
so turning push on meant unticking and re-ticking a type. The checklist
no longer subscribes or unsubscribes; it only tells the server which
types to leave out, so ticking a box never brings up a permission
prompt. The settings section is now called Notifications.

Tyre and low EV alerts went out every hour while the latest data still
showed the problem, so a car asleep overnight with a soft tyre pushed
all night. Level alerts now go out once per report, judged by the
gateway's own poll stamps, so a replayed message cannot re-arm them.

New alerts, all switchable per device:
- Low 12V battery: below AUX_BATTERY_LOW_VOLT (12.0 V) on several polls
  in a row while parked.
- Low fuel: below LOW_FUEL_PERCENT (15 %), hybrids and plug-in hybrids.
- No data from the car: nothing reported for STALE_DATA_HOURS (48).
- MG sign-in failed: the gateway's account/lastLoginError, once per
  outage (until the next account/lastLogin). Account topics were dropped
  before any handler saw them; MqttTopicParser now parses them.

LOW_EV_PERCENT (20) replaces the hardcoded low EV level. Zero switches
any of these alerts off. The variables are in compose, .env.example,
CONFIGURATION.md, the README and the Unraid template.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@joszz
joszz merged commit 668f2d2 into main Oct 11, 2026
23 checks passed
@joszz
joszz deleted the feat/alert-reliability branch October 11, 2026 20:55
joszz added a commit to joszz/unraid-community-apps that referenced this pull request Oct 11, 2026
Adds the alert level variables from joszz/GarageStack#451:
AUX_BATTERY_LOW_VOLT, LOW_FUEL_PERCENT, LOW_EV_PERCENT, STALE_DATA_HOURS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant