Skip to content

v2.0.38 — Schedule rules self-enforce against manual toggles + SOAP drift

Choose a tag to compare

@github-actions github-actions released this 08 Jun 14:15
· 2 commits to main since this release

Fix: scheduled OFF rules now self-enforce instead of giving up after one shot

Symptom (user-reported, two nights in a row): A scheduled rule has Family Room Lamp + Kitchen Island Light as targets, set to turn off at the same time each evening. Family Room Lamp went OFF correctly; Kitchen Island Light stayed ON overnight.

Root cause in packages/homebridge-plugin/lib/scheduler.js: a Schedule rule fired a single setBinaryState per target device, confirmed once after 3 s, retried once if the confirm came back wrong, then walked away forever. Three real-world failure paths produced the symptom:

  1. Silent manual re-toggle. Someone pressed the physical Wemo button, tapped it in Apple Home, or hit it from the Wemo app between the rule firing and morning. No enforcement layer = device stayed in the wrong state.
  2. Past-retry failure. The single retry happens 5 s after the confirm fails. If that retry also threw (network blip, switch radio asleep, SOAP timeout), the catch block swallowed the error and the device was stuck.
  3. Confirm-read race. Wemo's GetBinaryState occasionally reports stale state for a second or two after SetBinaryState. The current code accepted the confirm as authoritative and never re-checked.

Fix — continuous state enforcement via the existing 10-second health poll

Schedule rules only. Countdown / Away / Trigger / AlwaysOn rules are intentionally exempt — they have their own state semantics.

  • _intendedState: Map<host:port, {on, ruleId, ruleName, since}> populated by _fire() immediately for any Schedule entry. The map records the intended state up-front, so even if the SOAP call throws the scheduler still knows the correct target.

  • _pollDeviceHealth() (which already polls every 10 s) now consults _intendedState after each getBinaryState. If the actual state differs from the intended state and the device is not under an AlwaysOn rule, it issues a corrective setBinaryState and emits a log line:

    [enforce] Kitchen Island Light was ON — turned OFF (rule "Main Floor Sunset") ✓
    
  • _seedIntendedState() runs at scheduler start, walking today's past-fired Schedule entries in chronological order and seeding _intendedState with the most recent one per device. Catches drift that accumulated while Homebridge was stopped — restart Homebridge at 11 PM after a 9:30 PM OFF rule and the very first health poll corrects any device left in the wrong state.

In practice

After a 9:30 PM OFF rule fires, if someone turns one of the devices back on (physical button, Apple Home, Wemo app, voice command via Siri), the scheduler notices within 10 s and turns it off again. The "off" stays off until the next Schedule entry for that device flips the intended state (e.g. a 6 AM ON rule the next morning).

Devices with no Schedule entry today are unaffected — manual toggles work normally there. If you want a device to stay ON after a Schedule OFF rule fired, disable or edit the rule — don't fight the system from another UI. The behaviour matches the explicit user request: "it should always turn the device off."

Affected packages

All monorepo packages bumped to 2.0.38 in unified versioning. Functional change is confined to homebridge-dibby-wemo@2.0.38. The desktop apps, Synology Docker, Synology .spk, HA integration, and Node-RED package get the version bump only — they carry forward v2.0.37's location-search fix, v2.0.36's DwmStore atomic-write protection, and v2.0.35's Synology container root-fallback.

Upgrade

  • Homebridge: npm install -g homebridge-dibby-wemo@2.0.38 → restart Homebridge. Watch the log: when a Schedule rule fires you'll see "Main Floor Sunset" → OFF (192.168.18.69) ✓ as before; if anything drifts later you'll see a follow-up [enforce] Kitchen Island was ON — turned OFF (rule "Main Floor Sunset") ✓ from the next 10-second poll.
  • Synology Container Manager / Docker: Stop → Build → Start (:latest now points at 2.0.38; no functional change).
  • Synology .spk: download the new .spk for your arch → Package Center → Manual Install (no functional change).
  • Node-RED: npm install -g node-red-contrib-dibby-wemo@2.0.38 (no functional change).
  • HACS: ⋮ → Reload data → Dibby Wemo → ⋮ → Redownload → 2.0.38 → restart HA (no functional change).
  • Desktop installers for Windows / macOS / Linux ship a version bump and the latest icon set; no functional change vs 2.0.37.

What's NOT in this release (intentional scope limit)

The same one-shot scheduler pattern exists in:

  • apps/desktop/src/main/scheduler.js (desktop GUI)
  • apps/desktop/src/main/scheduler-standalone.js (Windows service / Synology Docker / Linux daemon)
  • custom_components/dibby_wemo/scheduler.py (Home Assistant integration)

These are technically separate code paths but share the same Schedule-rule semantics. v2.0.38 ships the fix to the Homebridge plugin only to match the reported symptom and limit blast radius. If the same symptom shows up on another surface, the fix pattern ports directly in a follow-up release.