airgradienthq / arduino

Firmware of open-source hardware air quality monitors AirGradient ONE (indoor) and AirGradient Open Air (outdoor).
https://www.airgradient.com/documentation/
Other
220 stars 116 forks source link

Home Assistant Integration - stuck on already_in_progress if AirGradient is initially inaccessible #183

Closed asheroto closed 1 month ago

asheroto commented 5 months ago

Hello, I came here from here, let me know if it's the wrong spot: https://forum.airgradient.com/t/native-airgradient-integration-with-homeassistant/2125

I upgraded the firmware on my AirGradient and added it to Home Assistant. Initially my setup said Unknown error occurred. Upon further inspection, I found that I had some firewall rules limiting access. I changed those rules, then tried to connect again. This time I got the error message already_in_progress.

2024-06-18_00-03-28_1174

So, two things here:

1.) The Unknown error occurred may want to be a bit more verbose, or at the very least say "check the Home Assistant logs for details". You could likely integrate a check to confirm connectivity first, then if connectivity fails, tell the user something like, "We couldn't connect to your device. Check network/switch/firewall rules", etc. 2.) I'm guessing already_in_progress appeared because it was stuck on the initial connection. The way I resolved this was to Restart Server on Home Assistant, then re-add the AirGradient integration. Although this is a feasible workaround, it might be better for the AirGradient integration setup to "soft fail" where it cancels if the Unknown error occurred occurs. This way even if somebody simply had their AirGradient disconnected, it wouldn't get stuck on setup. 😊

Here are the logs:

Details

``` 2024-06-17 23:50:34.819 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved (None) Traceback (most recent call last): File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1025, in _wrap_create_connection return await self._loop.create_connection(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1120, in create_connection raise exceptions[0] File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1102, in create_connection sock = await self._connect_sock( ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1005, in _connect_sock await self.sock_connect(sock, address) File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 641, in sock_connect return await fut ^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 681, in _sock_connect_cb raise OSError(err, f'Connect call failed {address}') ConnectionRefusedError: [Errno 111] Connect call failed ('192.168.0.93', 80) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1262, in async_init flow, result = await self._async_init(flow_id, handler, context, data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1292, in _async_init result = await self._async_handle_step(flow, flow.init_step, data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 517, in _async_handle_step result: _FlowResultT = await getattr(flow, method)(user_input) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/airgradient/config_flow.py", line 50, in async_step_zeroconf await self.client.get_current_measures() File "/usr/local/lib/python3.12/site-packages/airgradient/airgradient.py", line 80, in get_current_measures response = await self._request("measures/current") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/airgradient/airgradient.py", line 60, in _request response = await self.session.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/client.py", line 581, in _request conn = await self._connector.connect( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 544, in connect proto = await self._create_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 944, in _create_connection _, proto = await self._create_direct_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1257, in _create_direct_connection raise last_exc File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1226, in _create_direct_connection transp, proto = await self._wrap_create_connection( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1033, in _wrap_create_connection raise client_error(req.connection_key, exc) from exc aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host 192.168.0.93:80 ssl:default [Connect call failed ('192.168.0.93', 80)] 2024-06-17 23:56:30.822 ERROR (MainThread) [aiohttp.server] Error handling request Traceback (most recent call last): File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1025, in _wrap_create_connection return await self._loop.create_connection(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1120, in create_connection raise exceptions[0] File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1102, in create_connection sock = await self._connect_sock( ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1005, in _connect_sock await self.sock_connect(sock, address) File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 641, in sock_connect return await fut ^^^^^^^^^ File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 681, in _sock_connect_cb raise OSError(err, f'Connect call failed {address}') ConnectionRefusedError: [Errno 111] Connect call failed ('192.168.0.93', 80) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request resp = await request_handler(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/web_app.py", line 543, in _handle resp = await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 114, in impl return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 210, in forwarded_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 32, in headers_middleware response = await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle result = await handler(request, **request.match_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 81, in with_admin return await func(self, request, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 222, in post return await super().post(request, flow_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 70, in wrapper return await method(view, request, data, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 122, in post result = await self._flow_mgr.async_configure(flow_id, data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 368, in async_configure result = await self._async_configure(flow_id, user_input) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 414, in _async_configure result = await self._async_handle_step( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 517, in _async_handle_step result: _FlowResultT = await getattr(flow, method)(user_input) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/airgradient/config_flow.py", line 85, in async_step_user current_measures = await self.client.get_current_measures() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/airgradient/airgradient.py", line 80, in get_current_measures response = await self._request("measures/current") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/airgradient/airgradient.py", line 60, in _request response = await self.session.request( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/client.py", line 581, in _request conn = await self._connector.connect( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 544, in connect proto = await self._create_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 944, in _create_connection _, proto = await self._create_direct_connection(req, traces, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1257, in _create_direct_connection raise last_exc File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1226, in _create_direct_connection transp, proto = await self._wrap_create_connection( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1033, in _wrap_create_connection raise client_error(req.connection_key, exc) from exc aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host 192.168.0.93:80 ssl:default [Connect call failed ('192.168.0.93', 80)] 2024-06-18 00:05:08.519 WARNING (Thread-4 (_do_shutdown)) [homeassistant.util.executor] Thread[SyncWorker_12] is still running at shutdown: File "/usr/local/lib/python3.12/threading.py", line 1030, in _bootstrap self._bootstrap_inner() File "/usr/local/lib/python3.12/threading.py", line 1073, in _bootstrap_inner self.run() File "/usr/local/lib/python3.12/threading.py", line 1010, in run self._target(*self._args, **self._kwargs) File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 89, in _worker work_item = work_queue.get(block=True) 2024-06-18 00:05:08.536 CRITICAL (SyncWorker_12) [concurrent.futures] Exception in worker Traceback (most recent call last): File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 82, in _worker work_item = work_queue.get_nowait() ^^^^^^^^^^^^^^^^^^^^^^^ _queue.Empty During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 89, in _worker work_item = work_queue.get(block=True) ^^^^^^^^^^^^^^^^^^^^^^^^^^ SystemExit ```


As a separate comment, perhaps the entity ID prefix should be something more descriptive, like "sensor.airgradient_carbon_dioxide", "sensor.airgradient2_carbon_dioxide". That would be easier to find and remember than sensor.i_9psl_carbon_dioxide. 😊

Great job guys, this is much easier than it used to be!

joostlek commented 5 months ago

I'll probably have to catch some exception better to make sure it shows the right message. That's also the reason why you probably see already_in_progress since that happens when you try to start a flow that is already ongoing (but the old one did not stop because the exception didnt capture properly).

About the naming, we try to set the device name to something a user can recognize, so if you for example have an indoor and outdoor monitor and add them both, you would have sensor.airgradient_temperature and sensor.airgradient_temperature_2, which is harder to distinguish. So that's why we chose to put the model name in there so you know which one is which. You can rename a device, and then HA will ask if you want to update all entities as well and then you can easily change i_9psl to whatever you like

airgradienthq commented 5 months ago

@joostlek Please update this ticket and let me know how to proceed with this. Thanks.

joostlek commented 1 month ago

It's fixed in the latest home assistant release, so this can be closed

asheroto commented 1 month ago

Will do! Thanks!