Async_setup_entry() and synchronous component - is it possible?

Hi there
I developed a synchronous HA integration (initialized by synchronous setup() function) and it’s working fine. However I’d like to use more HA features like device triggers etc, but these do require that a component is setup via a config entry, not via configuration.yaml. So I started experimenting with Config Flow code, and it doesn’t seem complicated to use it, but I encountered a problem / question.
Config entries require component setup to be done via async_setup_entry(). And here is where my problem starts. All my code is synchronous. The library I use for TCP communication is also synchronous.
I assume if I move the setup code I have from setup() to async_setup_entry() it will block the asyncio loop, right? It won’t last long (3-5 seconds, but it may vary in different user setups) but I don’t like to do it this way.

Question 1: is there an easy way to combine these 2 things - sync component and async_setup_entry()? I won’t be able to rewrite everything to asyncio, as this is beyond my python skills.

Question 2: will HA assume that the whole component is asynchronous if I use async_setup_entry()? This wouldn’t be be nice as my component would block HA event loop and slow it down, and obviously I don’t want that.

Help / input much appreciated!

Bumping…

You are correct: you are going to run into challenges if you insert sync code directly into an async context. Re: #2, using async_setup_entry is going to introduce that context throughout your component.

The hass object does provide a utility to run sync functions within an async context:

result = await hass.async_add_executor_job(func)
1 Like

thanks! I got the same reply ca 2 hours ago from discord (maybe it was even you under a different user name). So seems this is the right solution! :slight_smile:

I think it’d be good to have such info in HA dev docs (which IMO need a lot of improvements).
But hopefully this thread will serve some folks in the future searching for a solution to this problem.

RE #2

using async_setup_entry is going to introduce that context throughout your component.

What exactly do you mean by this?

I just mean that you can’t mix and match sync and async methods within a component. The presence of async_setup_entry means that anything done by async_setup_entry – like setting up entities, etc. – must be async (or must be wrapped in async_add_executor_job calls).

ok, got it. Thanks again for your input and knowledge sharing.

1 Like