Skip to content

Fix spurious state inversion on rapid clicks in Click mode#22

Open
Foroxon wants to merge 1 commit into
MihVS:mainfrom
Foroxon:fix/click-mode-blocking-sleep
Open

Fix spurious state inversion on rapid clicks in Click mode#22
Foroxon wants to merge 1 commit into
MihVS:mainfrom
Foroxon:fix/click-mode-blocking-sleep

Conversation

@Foroxon
Copy link
Copy Markdown

@Foroxon Foroxon commented May 25, 2026

Fixes #21

Problem

When a physical switch is pressed twice quickly, or two switches are pressed in rapid succession, the last triggered relay state is spuriously inverted ~500ms later.

_turn_off_state uses await asyncio.sleep(0.5) inside the HTTP request handler. MegaD firmware sends notifications sequentially and waits for HTTP 200 before sending the next one. This 500ms block causes MegaD to queue all subsequent notifications, which then arrive out of order — relay state change notifications (pt=N&v=X) land after the delay and incorrectly flip relay state in HA.

Fix

# 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 runs the auto-reset as a background coroutine. HA responds to MegaD in ~5–40ms instead of 500ms, preventing notification queuing. The 500ms sensor state reset still happens correctly — just without blocking the HTTP handler.

Evidence

Before fix — 502ms gap reveals MegaD was blocked:

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.129  sensor.md2_port2  single
10:54:43.631  sensor.md2_port2  off
10:54:43.641  light.md2_port9   off       ← spurious inversion

After fix — immediate response, no spurious inversions:

11:16:06.252  sensor.md2_port2  single
11:16:06.291  light.md2_port9   on        ← response in 39ms
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

Tested with MegaD firmware 4.59b9, integration v2026.5.1, HA 2026.5.4.

MegaD sends HTTP notifications sequentially and waits for a 200
response before sending the next one. Awaiting _turn_off_state
(which contains asyncio.sleep(0.5)) inside the HTTP handler blocked
the response for 500ms, causing MegaD to queue all subsequent
notifications. Relay state change notifications then arrived out of
order and incorrectly inverted the relay state in HA.

Replacing `await` with `async_create_task` runs the auto-reset as a
background task, allowing HA to respond to MegaD immediately (~5-40ms)
and preventing notification queue buildup.

Fixes MihVS#21
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.

Rapid successive button presses cause spurious state inversion (~500ms) due to blocking asyncio.sleep in HTTP handler

1 participant