mirror of
https://github.com/Andre0512/hon.git
synced 2026-06-15 03:36:27 +00:00
fix(thread-safety): marshal pyhon MQTT push updates onto the event loop
PR #43 (cherry-picked in the previous commit) only swaps async_write_ha_state() for schedule_update_ha_state() inside entity command methods, which run on the event loop anyway. It does NOT address the actual root cause of mmalolepszy/hon-revived#44. pyhon-revived delivers MQTT push notifications from the awscrt network thread: MQTTClient._on_publish_received -> Hon.notify -> self._notify_function(None), with no loop marshalling. The integration registered coordinator.async_set_updated_data directly as that subscriber, so the loop-affine @callback (which fans out to listeners and arms loop timers via _schedule_refresh) was being invoked from a foreign thread. HA Core 2026.5.x enforces thread safety and raises on this, breaking live state updates on 2026.5.4 even with PR #43 applied. Wrap the subscriber in a @callback that re-dispatches via hass.loop.call_soon_threadsafe, so the coordinator update always runs on the event loop. The None payload is preserved (entities read state from self._device, not coordinator.data, so it is only a listener trigger). Refs: https://developers.home-assistant.io/docs/asyncio_thread_safety/ Fixes mmalolepszy/hon-revived#44 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
047800ccbf
commit
ca8ed250c2
|
|
@ -6,7 +6,7 @@ import voluptuous as vol # type: ignore[import-untyped]
|
|||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
|
||||
from homeassistant.helpers import config_validation as cv, aiohttp_client
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
from pyhon import Hon
|
||||
|
||||
|
|
@ -48,7 +48,21 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
coordinator: DataUpdateCoordinator[dict[str, Any]] = DataUpdateCoordinator(
|
||||
hass, _LOGGER, name=DOMAIN
|
||||
)
|
||||
hon.subscribe_updates(coordinator.async_set_updated_data)
|
||||
|
||||
@callback
|
||||
def _push_update(data: Any) -> None:
|
||||
"""Apply a pyhon push update on the event loop.
|
||||
|
||||
pyhon-revived delivers MQTT push notifications from the awscrt
|
||||
network thread and invokes this subscriber synchronously (see
|
||||
pyhon.connection.mqtt.MQTTClient._on_publish_received ->
|
||||
Hon.notify). Calling the loop-affine ``async_set_updated_data``
|
||||
directly from that foreign thread raises a thread-safety error on
|
||||
HA Core 2026.5.x, so we marshal it onto the event loop.
|
||||
"""
|
||||
hass.loop.call_soon_threadsafe(coordinator.async_set_updated_data, data)
|
||||
|
||||
hon.subscribe_updates(_push_update)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
hass.data[DOMAIN][entry.unique_id] = {"hon": hon, "coordinator": coordinator}
|
||||
|
|
|
|||
Loading…
Reference in a new issue