grimmpp / home-assistant-eltako

Integration for Eltako 14 series in Home Assistant
MIT License
28 stars 5 forks source link

Problems with the new version of Home Assistant Core 2024.5.0 #98

Closed JSchmid6 closed 1 month ago

JSchmid6 commented 2 months ago

After upgrading to 2024.5.0 I encountered an issue with your integration. The integration crashed on first use after a reboot of HA. I think the problem has something to do with the topic described here: https://developers.home-assistant.io/blog/2024/03/09/import_executor_default/ If Home Assistant is running and I reload your integration, it works again.

Error Log is: Uncaught thread exception Traceback (most recent call last): File "/usr/local/lib/python3.12/threading.py", line 1073, in _bootstrap_inner self.run() File "/usr/local/lib/python3.12/site-packages/eltakobus/serial.py", line 176, in run self.__callback(parsed_msg) File "/config/custom_components/eltako/gateway.py", line 300, in _callback_receive_message_from_serial_bus self._fire_last_message_received_event() File "/config/custom_components/eltako/gateway.py", line 107, in _fire_last_message_received_event self.hass.async_create_task( File "/usr/src/homeassistant/homeassistant/core.py", line 816, in async_create_task self.verify_event_loop_thread("async_create_task") File "/usr/src/homeassistant/homeassistant/core.py", line 440, in verify_event_loop_thread frame.report( File "/usr/src/homeassistant/homeassistant/helpers/frame.py", line 162, in report _report_integration(what, integration_frame, level, error_if_integration) File "/usr/src/homeassistant/homeassistant/helpers/frame.py", line 203, in _report_integration raise RuntimeError( RuntimeError: Detected that custom integration 'eltako' calls async_create_task from a thread at custom_components/eltako/gateway.py, line 107: self.hass.async_create_task(. Please report it to the author of the 'eltako' custom integration.

If fixed it localy by a try: execpt: block around the async_create_task calles on gateway.py. A change to the manifest as mentioned in the link, didn't help so far.

N8schatten commented 2 months ago

Same Problem. But thanks for the workaround.

factor4 commented 2 months ago

Same here with 2024.5.1. A reload solved it! Thanks!

Pegasus500 commented 1 month ago

Problem still exists with 2024.5.2. But also here reloading the integration helps.

boredomwontgetus commented 1 month ago

Yeah i noticed the same problem. Also, reloading the integration once after restart helps in the meantime.

grimmpp commented 1 month ago

I think I found the issue but currently I'm short handed.

My guess is that those two lines/events are fired in the wrong thread: https://github.com/grimmpp/home-assistant-eltako/blob/dcbbde9c01e72db7f34caafe917e2d85b191eef3/custom_components/eltako/gateway.py#L300 Since 2024.5.1 there is a thread safety check which could detect it and raise the exception. If you like you can try to comment out line 300 and 301 and check if it still occurs.

LutzDi commented 1 month ago

Since 2024.5.1 there is a thread safety check which could detect it and raise the exception. If you like you can try to comment out line 300 and 301 and check if it still occurs.

Hey all, I can confirm that commenting out lines 300 and 301 in the /config/custom_components/eltako/gateway.py fixes the bug as a workaround... Tested with 2024.05.1. Happy to see you helping @grimmpp, also when you are short with time... 👍 Cheers Lutz

grimmpp commented 1 month ago

I hope i fixed it now with v1.4.3. Can you please confirm?

bdraco commented 1 month ago

https://github.com/grimmpp/home-assistant-eltako/compare/v1.4.2-added-eep-a5-30-01-and-a5-30-03...v1.4.3-compatibility-to-ha-2024.5

It looks like the change was to pass the loop directly which will bypass the thread safety check. Unfortunately this does not solve the problem. The thread safety check is in place to prevent crashing Home Assistant.

Instead change hass.async_create_task to hass.create_task

More details https://deploy-preview-2171--developers-home-assistant.netlify.app/docs/asyncio_thread_safety#hassasync_create_task

I would suggest developing with asyncio debug mode on and Home Assistant's debug mode on as it will help catch thread safety problems https://community.home-assistant.io/t/2024-5-tracking-down-instability-issues-caused-by-integrations/724441

grimmpp commented 1 month ago

Hello @bdraco,

thanks a lot for your comment. Unfortunately, async_create_task did not work out for me. There the same error message popped up. Is there a good example how to transfer message/sync a communication lib using a independent thread with the HA core loop?

I just found an example in the tuya integration which is also not using async_create_task, instead it is using asyncio.run_coroutine_threadsafe which works for me as well. https://github.com/make-all/tuya-local/blob/d0e1465574258e53d1519d67c5731a0abd224f8c/custom_components/tuya_local/device.py#L147C38-L147C62

bdraco commented 1 month ago

For tuya-local I added some suggestions: https://github.com/make-all/tuya-local/issues/1916 https://github.com/make-all/tuya-local/issues/1917

bdraco commented 1 month ago

Unfortunately, async_create_task did not work out for me. There the same error message popped up. Is there a good example how to transfer message/sync a communication lib using a independent thread with the HA core loop?

Assuming your callbacks are running in a thread other than the event loop thread and you are always calling coroutines that should run in the event loop, something like this should work:

diff --git a/custom_components/eltako/gateway.py b/custom_components/eltako/gateway.py
index 7dfd08d..117302f 100644
--- a/custom_components/eltako/gateway.py
+++ b/custom_components/eltako/gateway.py
@@ -93,9 +93,8 @@ class EnOceanGateway:

     def _fire_connection_state_changed_event(self, status):
         if self._connection_state_handler:
-            asyncio.ensure_future(
+            self.hass.create_task(
                 self._connection_state_handler(status),
-                loop= self._loop
             )

@@ -105,9 +104,8 @@ class EnOceanGateway:

     def _fire_last_message_received_event(self):
         if self._last_message_received_handler:
-            asyncio.ensure_future(
+            self.hass.create_task(
                 self._last_message_received_handler( datetime.utcnow().replace(tzinfo=pytz.utc) ),
-                loop= self._loop
             )

@@ -118,9 +116,8 @@ class EnOceanGateway:
     def _fire_received_message_count_event(self):
         self._received_message_count += 1
         if self._received_message_count_handler:
-            asyncio.ensure_future(
+            self.hass.create_task(
                 self._received_message_count_handler( self._received_message_count ),
-                loop= self._loop
             )

     def process_messages(self, data=None):
@@ -293,7 +290,7 @@ class EnOceanGateway:
                 LOGGER.debug("[Gateway] [Id: %d] Send message: %s - Serialized: %s", self.dev_id, msg, msg.serialize().hex())

                 # put message on serial bus
-                asyncio.ensure_future(self._bus.send(msg), loop=self._loop)
+                self.hass.create_task(self._bus.send(msg))
         else:
             LOGGER.warn("[Gateway] [Id: %d] Serial port %s is not available!!! message (%s) was not sent.", self.dev_id, self.serial_path, msg)
grimmpp commented 1 month ago

Really, that easy! You don't what to know what I had tried out to do the same 🙈

It's work for me fine. Thanks a lot!!!