Description
When a physical switch is pressed twice in quick succession, or two different switches are pressed one after the other within ~300ms, the last triggered relay state is spuriously inverted roughly 500ms later.
Example: Light is OFF. Two quick presses → expected: OFF→ON→OFF. Actual: OFF→ON→OFF→ON (final state inverted after ~500ms).
Root Cause
_turn_off_state in MegaDCoordinator uses await asyncio.sleep(0.5) to auto-reset Click-mode sensor state. This await runs inside the HTTP request handler (MegadHttpView.get → update_port_state → _turn_off_state).
MegaD firmware sends HTTP notifications sequentially — it waits for an HTTP 200 response before sending the next one. When HA blocks the HTTP response for 500ms (the asyncio.sleep), all subsequent MegaD notifications are queued. They then arrive out of order: most critically, relay state notifications (e.g. pt=9&v=0) arrive after the delay and incorrectly update relay state in HA, causing the spurious inversion.
Environment
| Component |
Version |
| Home Assistant |
2026.5.4 |
| Integration (megad) |
v2026.5.1 |
| MegaD firmware |
4.59b9 |
| MegaD model |
MegaD-2561 |
Port Configuration Used for Reproduction
Port 2 — IN, Click mode (C):
Single click → toggle relay 9; || skips double-click; long press → PWM 11 = 255
Port 4 — IN, Click mode (C):
Single click → dim PWM 11 by 25%; || skips double-click; long press → PWM 11 = 1
Port 9 — OUT, SW (relay), Default = 0
Port 11 — OUT, PWM, Default = 0
Steps to Reproduce
Scenario A (same switch, two quick presses):
- Light (relay 9) is OFF
- Press switch (port 2) twice within ~300ms
- Expected final state: OFF. Actual: the light flips back ON ~500ms after the second press
Scenario B (two different switches, pressed in quick succession):
- Press switch port 4 (triggers action on port 11/9)
- Immediately press switch port 2 (triggers toggle on relay 9)
- Observe: relay 9 changes state, then inverts ~500ms later
Logbook Evidence — Before Fix
The 502ms gap between sensor.md2_port4 single and sensor.md2_port4 off reveals MegaD was blocked waiting for HA's HTTP response:
10:54:42.597 sensor.md2_port4 single
10:54:43.099 sensor.md2_port4 off ← 502ms gap (MegaD blocked by HA's sleep)
10:54:43.108 light.md2_port9 on
10:54:43.119 light.md2_port11 off
10:54:43.129 sensor.md2_port2 single
10:54:43.631 sensor.md2_port2 off
10:54:43.641 light.md2_port9 off ← spurious inversion
Proposed Fix
In custom_components/megad/__init__.py, MegaDCoordinator.update_port_state (~line 218):
# Before — blocks HTTP response for 500ms:
if isinstance(port, ReaderPort) or port.conf.mode == ModeInMegaD.C:
await self._turn_off_state('off', 0.5, port_id, data)
# After — returns HTTP response immediately:
if isinstance(port, ReaderPort) or port.conf.mode == ModeInMegaD.C:
self.hass.async_create_task(
self._turn_off_state('off', 0.5, port_id, data)
)
async_create_task schedules _turn_off_state as a background coroutine. HA responds to MegaD in ~5–40ms instead of 500ms, preventing notification queuing and out-of-order delivery.
Logbook Evidence — After Fix
11:16:06.252 sensor.md2_port2 single
11:16:06.291 light.md2_port9 on ← response in 39ms (was 500ms+)
11:16:06.750 sensor.md2_port2 off
11:16:07.110 sensor.md2_port2 single
11:16:07.124 light.md2_port9 off ← clean toggle, no spurious inversion
11:16:07.821 sensor.md2_port2 off
Fix tested and confirmed working with rapid repeated presses across multiple ports.
Description
When a physical switch is pressed twice in quick succession, or two different switches are pressed one after the other within ~300ms, the last triggered relay state is spuriously inverted roughly 500ms later.
Example: Light is OFF. Two quick presses → expected: OFF→ON→OFF. Actual: OFF→ON→OFF→ON (final state inverted after ~500ms).
Root Cause
_turn_off_stateinMegaDCoordinatorusesawait asyncio.sleep(0.5)to auto-reset Click-mode sensor state. Thisawaitruns inside the HTTP request handler (MegadHttpView.get→update_port_state→_turn_off_state).MegaD firmware sends HTTP notifications sequentially — it waits for an HTTP 200 response before sending the next one. When HA blocks the HTTP response for 500ms (the
asyncio.sleep), all subsequent MegaD notifications are queued. They then arrive out of order: most critically, relay state notifications (e.g.pt=9&v=0) arrive after the delay and incorrectly update relay state in HA, causing the spurious inversion.Environment
Port Configuration Used for Reproduction
Port 2 — IN, Click mode (
C):Single click → toggle relay 9;
||skips double-click; long press → PWM 11 = 255Port 4 — IN, Click mode (
C):Single click → dim PWM 11 by 25%;
||skips double-click; long press → PWM 11 = 1Port 9 — OUT, SW (relay), Default = 0
Port 11 — OUT, PWM, Default = 0
Steps to Reproduce
Scenario A (same switch, two quick presses):
Scenario B (two different switches, pressed in quick succession):
Logbook Evidence — Before Fix
The 502ms gap between
sensor.md2_port4 singleandsensor.md2_port4 offreveals MegaD was blocked waiting for HA's HTTP response:Proposed Fix
In
custom_components/megad/__init__.py,MegaDCoordinator.update_port_state(~line 218):async_create_taskschedules_turn_off_stateas a background coroutine. HA responds to MegaD in ~5–40ms instead of 500ms, preventing notification queuing and out-of-order delivery.Logbook Evidence — After Fix
Fix tested and confirmed working with rapid repeated presses across multiple ports.