From da55ef790181e7765d8a4dc90917c49ad7372abb Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 16 Feb 2024 05:27:13 -0600 Subject: [PATCH] Fix elkm1 service calls running in the executor (#110655) fixes ``` File "/usr/src/homeassistant/homeassistant/components/elkm1/__init__.py", line 416, in _set_time_service _getelk(service).panel.set_time(dt_util.now()) File "/usr/local/lib/python3.11/site-packages/elkm1_lib/panel.py", line 55, in set_time self._connection.send(rw_encode(datetime)) File "/usr/local/lib/python3.11/site-packages/elkm1_lib/connection.py", line 152, in send self._send(QueuedWrite(msg.message, msg.response_command), priority_send) File "/usr/local/lib/python3.11/site-packages/elkm1_lib/connection.py", line 148, in _send self._check_write_queue.set() File "/usr/local/lib/python3.11/asyncio/locks.py", line 192, in set fut.set_result(True) File "/usr/local/lib/python3.11/asyncio/base_events.py", line 763, in call_soon self._check_thread() File "/usr/local/lib/python3.11/asyncio/base_events.py", line 800, in _check_thread raise RuntimeError( RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one ``` --- homeassistant/components/elkm1/__init__.py | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/elkm1/__init__.py b/homeassistant/components/elkm1/__init__.py index c51cb30776a..03f1f80b4f9 100644 --- a/homeassistant/components/elkm1/__init__.py +++ b/homeassistant/components/elkm1/__init__.py @@ -10,7 +10,7 @@ from types import MappingProxyType from typing import Any from elkm1_lib.elements import Element -from elkm1_lib.elk import Elk +from elkm1_lib.elk import Elk, Panel from elkm1_lib.util import parse_url import voluptuous as vol @@ -398,22 +398,30 @@ async def async_wait_for_elk_to_sync( return success +@callback +def _async_get_elk_panel(hass: HomeAssistant, service: ServiceCall) -> Panel: + """Get the ElkM1 panel from a service call.""" + prefix = service.data["prefix"] + elk = _find_elk_by_prefix(hass, prefix) + if elk is None: + raise HomeAssistantError(f"No ElkM1 with prefix '{prefix}' found") + return elk.panel + + def _create_elk_services(hass: HomeAssistant) -> None: - def _getelk(service: ServiceCall) -> Elk: - prefix = service.data["prefix"] - elk = _find_elk_by_prefix(hass, prefix) - if elk is None: - raise HomeAssistantError(f"No ElkM1 with prefix '{prefix}' found") - return elk + """Create ElkM1 services.""" + @callback def _speak_word_service(service: ServiceCall) -> None: - _getelk(service).panel.speak_word(service.data["number"]) + _async_get_elk_panel(hass, service).speak_word(service.data["number"]) + @callback def _speak_phrase_service(service: ServiceCall) -> None: - _getelk(service).panel.speak_phrase(service.data["number"]) + _async_get_elk_panel(hass, service).speak_phrase(service.data["number"]) + @callback def _set_time_service(service: ServiceCall) -> None: - _getelk(service).panel.set_time(dt_util.now()) + _async_get_elk_panel(hass, service).set_time(dt_util.now()) hass.services.async_register( DOMAIN, "speak_word", _speak_word_service, SPEAK_SERVICE_SCHEMA