Crestron Component - help with long-running Task (TCP server)

Hi all. Long-time HA user, new HA developer.

I’m working on an integration for Crestron control systems. You can use a Crestron programming symbol called an XSIG that uses a binary protocol over a TCP socket to communicate state changes.

I created a separate “hub” driver (so I can add it to PyPi as its own driver). I made the hub library asynchronous using asyncio.start_server(). There is a start() method in the hub Object that calls serve_forever() on the server object returned by asyncio.start_server().

So far so good: My hub driver works standalone updating a dict of the digital and analog values sent from the control system.

Now, to integrate with Home Assistant: I need to call the hub object’s start() method which will get the TCP server listening using a serve_forever().

Reading the developer docs section on working with async it looks like I should use async_create_task() to add my async tcp server to the home assistant event loop.

So, In my async_setup(), I create my hub object and then call hass.async_create_task(hub.start(PORT))

This seems to work quite well. The control system connects, sends is TCP packets, state on all my Entities propagates both ways.

However, it doesn’t look like Home Assistant likes this. After a restart, I get the dreaded “” in Lovelace. Then, a couple of minutes later, I see this in the log:
WARNING (MainThread) [homeassistant.bootstrap] Setup timed out for bootstrap - moving forward

So, it seems that I should not use async_create_task() for tasks/co-routings that run forever?

Is there a better way for me to add my tcp listener to the Home Assistant event loop? Would I have been better off writing a sync TCP server and adding it with async_add_executor_job()?

Code is at https://github.com/npope/home-assistant-crestron-component

1 Like

Just to follow up here in case someone else has the same problem.

Since my python driver for my “hub” component is async, there is no need to use async_create_task(), just use await instead!

So, to start() my hub I changed from this:
hass.async_create_task(hub.start(const.PORT))

to this:
await hub.start(const.PORT)

Works!

2 Likes