mjoshd / hyperhdr-ha

HyperHDR custom component for Home Assistant
https://github.com/awawa-dev/HyperHDR
MIT License
56 stars 7 forks source link

Integration fails if more than 891 LEDS are defined. #22

Open Alexxxeyyy opened 5 months ago

Alexxxeyyy commented 5 months ago

Hi,

Hope you can help. Just finished my projector HyperHDR setup with 1172 LEDS. The HyperHDR is working really well but Home Assistant integration doesn't work. I have spent a few hours trying to track down the issue and found that as soon as I define more than 891 LEDs, the integration crashes and can no longer connect. Anything up to 891 LEDS works flawlessly.

I am using Rapsberry PI 5 with HyperHDR 20 beta. The error is HA logs are follows: Traceback (most recent call last): File "/usr/local/lib/python3.11/asyncio/streams.py", line 548, in readline line = await self.readuntil(sep) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/asyncio/streams.py", line 626, in readuntil raise exceptions.LimitOverrunError( asyncio.exceptions.LimitOverrunError: Separator is not found, and chunk exceed the limit

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request resp = await request_handler(request) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 543, in _handle resp = await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/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 85, in security_filter_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 80, in ban_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 233, in auth_middleware return await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 31, in headers_middleware response = await handler(request) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 149, in handle result = await handler(request, request.match_info) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 63, in with_admin return await func(self, request, *args, *kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 177, in post return await super().post(request, flow_id) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 72, in wrapper result = await method(view, request, data, args, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 110, in post result = await self._flow_mgr.async_configure(flow_id, data) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 320, in async_configure result = await self._async_handle_step( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 416, in _async_handle_step result: FlowResult = await getattr(flow, method)(user_input) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/hyperhdr/config_flow.py", line 234, in async_step_user return await self._advance_to_auth_step_if_necessary( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/hyperhdr/config_flow.py", line 141, in _advance_to_auth_step_if_necessary return await self.async_step_confirm() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/config/custom_components/hyperhdr/config_flow.py", line 401, in async_step_confirm async with self._create_client() as hyperhdr_client: File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 149, in aenter result = await self.async_client_connect() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 369, in async_client_connect await self.async_client_disconnect() File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 422, in async_client_disconnect return await self._async_client_disconnect_internal() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 451, in _async_client_disconnect_internal await self._await_or_stop_task(receive_task, stop_task=True) File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 588, in _await_or_stop_task await task File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 568, in _receive_task_loop while await self._async_receive_once(): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 608, in _async_receive_once resp_json = await self._async_safely_read_command(use_timeout=False) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/hyperhdr/client.py", line 485, in _async_safely_read_command resp = await asyncio.wait_for(future_resp, timeout=timeout_secs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/asyncio/tasks.py", line 452, in wait_for return await fut ^^^^^^^^^ File "/usr/local/lib/python3.11/asyncio/streams.py", line 557, in readline raise ValueError(e.args[0]) ValueError: Separator is not found, and chunk exceed the limit

Alexxxeyyy commented 5 months ago

I got it to work by hacking at the code. After some hours of debugging, I could see that hyperHDR is sending the full LED device data and it is overflowing the buffer. I made some changes to hyperhdr/client.py (under hyperhdr-py) by finding a post on google regarding how to read a stream and catch partial read exception. I then forced a second read under json.loads exception to get the full buffer. It is a not a pretty solution, but it got my integration to load and work. Posting it here in case this can help in fixing the code correctly. Technically, this should be posted under https://github.com/mjoshd/hyperhdr-py.

client.py

change line 484 to: future_resp = self._readWithoutLimit(self._reader)

line 514, remove "Return None" and replace with: future_resp = self._readWithoutLimit(self._reader) resp = resp + await asyncio.wait_for(future_resp, timeout=timeout_secs)

I also removed the LOGGER.warning (line 510) so it doesn't appear in my home assistant log. This is a not "good" code but works until someone with more knowledge than me can fix it correctly. Unfortunately, I know nothing about asyncio functionality.

Pr0mises commented 5 months ago

I'm actually wondering what huge projector you have, for using 1172 leds, that's insane (in a good way) I'm intersted in how you accomplished that project. If you're willing to share your project i won't mind :D