Asking for help with understanding (and fixing) Async behaviour in DataUpdateCoordinator

I have a custom integration CharlesGillanders/homeassistant-alphaESS: Monitor your energy generation, storage, and usage data using the official API from Alpha ESS. (github.com) that uses a pypi library to make an external API call to gather data for my sensors.

The integration is logging warnings like:

Detected blocking call to open inside the event loop by custom integration 'alphaess' at custom_components/alphaess/coordinator.py, line 30: jsondata: json = await self.api.getdata() (offender: /usr/local/lib/python3.12/netrc.py, line 74: with open(file, encoding="utf-8") as fp:),

My code looks like this:

class AlphaESSDataUpdateCoordinator(DataUpdateCoordinator):
    """Class to manage fetching data from the API."""

    def __init__(self, hass: HomeAssistant, client: alphaess.alphaess) -> None:
        """Initialize."""
        super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)
        self.api = client
        self.update_method = self._async_update_data
        self.data: dict[str, dict[str, float]] = {}

    async def _async_update_data(self):
        """Update data via library."""
        try:
            jsondata: json = await self.api.getdata()

I have looked at advice from other similar questions in the forum, particularly this advice: Blocking Call inside event loop - Development - Home Assistant Community (home-assistant.io).

The method I call in the library is an asynchronous method, so I am not 100% certain that the answer to use async_add_executor_job is quite right for my case but anyway when I try it I get an error rather than a warning.

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 312, in _async_refresh
    self.data = await self._async_update_data()
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/alphaess/coordinator.py", line 30, in _async_update_data
    jsondata: json = await self.hass.async_add_executor_job(self.api.getdata)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/core.py", line 876, in async_add_executor_job
    task = self.loop.run_in_executor(None, target, *args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 850, in run_in_executor
    self._check_callback(func, 'run_in_executor')
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 805, in _check_callback
    raise TypeError(
TypeError: coroutines cannot be used with run_in_executor()

I am clearly not understanding correctly how to work with Asynchronous updates but I am unclear on where to look for more suggestions, the example code in the development docs seems closer to my original (working, but warning) code so I thought I was using the correct approach but if so - why the warning, and why does the warning refer to using open when this is a rest API call not a file open?

Any suggestions would be very gratefully received.

The way you are calling api.get_data is correct if your api is async.

I suspect that there is something in your api that is blocking. I would turn on debugging for your api (as you have lots of debug statements in it) and see which call from your get_data method is causing it. I am wondering if it is the calls to time and if they are trying to load timezone info (not 100% whether this returns a local time by default), which would cause a file read.

Read this to implement your call in an executor Blocking operations with asyncio | Home Assistant Developer Docs