Giter Site home page Giter Site logo

esphome / aioesphomeapi Goto Github PK

View Code? Open in Web Editor NEW
124.0 124.0 61.0 1.49 MB

Python Client for ESPHome native API. Used by Home Assistant.

Home Page: https://esphome.io/

License: MIT License

Python 97.91% Shell 0.04% Dockerfile 0.27% Cython 1.77%
asyncio home-assistant home-automation internet-of-things iot python

aioesphomeapi's Introduction

aioesphomeapi's People

Contributors

alexyao2015 avatar amomchilov avatar balloob avatar bdraco avatar blejdfist avatar dependabot[bot] avatar eternityforest avatar fabaff avatar frenck avatar github-actions[bot] avatar glmnet avatar gnumpi avatar grahambrown11 avatar jagheterfredrik avatar jesserockz avatar juliekoubova avatar kbickar avatar kbx81 avatar kroimon avatar marcelveldt avatar martgras avatar michaelmure avatar mjonuschat avatar nohat avatar ottowinter avatar oxan avatar paulmonigatti avatar peterg79 avatar rfdarter avatar syndtr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aioesphomeapi's Issues

Remove extra timeouts

both start and finish have an extra safety. I have audited the code and we aren’t missing any timeouts anymore. Since we control the code path end to end here we should remove the extra safeties when we have sufficient coverage

# Allow 2 minutes for connect and setup; this is only as a last measure

Use as pseudo-esphome device

Hi!

I'm looking for a way to normalize my assorted homebrew home automations (from mqtt to udp etc etc).
Since esphome/feature-requests#817 seems stuck, I'd like to try to flank the problem and to use this library to run a "pseudo-esphome" device (fed with those my automations) in native api mode.

How do I do that, if ever?

TIA,
--Vladimir

Client design makes it too easy to leak bluetooth notify callbacks on disconnect

The current design of bluetooth_gatt_start_notify returns two callables:

  • One that the caller must call when the device disconnects
  • One that the caller must call to unsubscribe from a notification

We should only return one callable and handle cleaning up disconnecting the callback in _on_bluetooth_device_connection_response so callers can't get it wrong and leak a callback

Upgrade protocol buffers

From discussion in home-assistant/core#80432 we need this library to support newer versions of protocol buffer in order to move forward other packages.

I tried to upgrade this myself, but i'm having a hard time understanding the protoc workflow in this library.

______________________________ ERROR collecting tests/test_client.py _______________________________
tests/test_client.py:6: in <module>
    from aioesphomeapi.api_pb2 import (
aioesphomeapi/__init__.py:3: in <module>
    from .client import APIClient
aioesphomeapi/client.py:21: in <module>
    from .api_pb2 import (  # type: ignore
aioesphomeapi/api_pb2.py:16: in <module>
    from . import api_options_pb2 as api__options__pb2
aioesphomeapi/api_options_pb2.py:36: in <module>
    _descriptor.EnumValueDescriptor(
venv/lib/python3.9/site-packages/google/protobuf/descriptor.py:755: in __new__
    _message.Message._CheckCalledFromGeneratedFile()
E   TypeError: Descriptors cannot not be created directly.
E   If this call came from a _pb2.py file, your generated code is out of date and must be regenerated with protoc >= 3.19.0.
E   If you cannot immediately regenerate your protos, some other possible workarounds are:
E    1. Downgrade the protobuf package to 3.20.x or lower.
E    2. Set PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python (but this will use pure-Python parsing and will be much slower).
E   
E   More information: https://developers.google.com/protocol-buffers/docs/news/2022-05-06#python-updates

Investigate connected race

2022-10-23 22:14:45.384 DEBUG (MainThread) [aiohomekit.controller.ble.pairing] Eve Motion 41A4 [CA:D5:1A:5B:E3:A9] (id=4B:10:3C:BB:EF:8E): Polling subscriptions for changes during disconnection; rssi=-65
2022-10-23 22:14:45.384 DEBUG (MainThread) [aiohomekit.controller.ble.pairing] Eve Motion 41A4 [CA:D5:1A:5B:E3:A9] (id=4B:10:3C:BB:EF:8E): Client not connected; rssi=-65
2022-10-23 22:14:45.384 WARNING (MainThread) [aiohomekit.controller.ble.pairing] Eve Motion 41A4 [CA:D5:1A:5B:E3:A9] (id=4B:10:3C:BB:EF:8E): Failed to fetch disconnected events: Eve Motion 41A4 [CA:D5:1A:5B:E3:A9] (id=4B:10:3C:BB:EF:8E) is not connected; rssi=-65

There is some type of race where we never get a disconnected callback but we are not actually connected anymore

Speed up reconnecting

If the first reconnect fails, keep the zeroconf listener running and cancel the connection attempt if we are not in phase 2 as soon as we see the device.

To make this cancel safe we need to split the connection logic into two phases

Phase 1: actual connection
Phase 2: setup connection

Phase 1 must be cancel safe

Find cancelation race on bluetooth operation (there are likely multiple since there are different paths)

I got a level bolt for testing and found this

2023-07-19 12:56:48.780 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry A13 for homekit_controller
Traceback (most recent call last):
  File "/Users/bdraco/home-assistant/homeassistant/config_entries.py", line 391, in async_setup
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/homeassistant/components/homekit_controller/__init__.py", line 44, in async_setup_entry
    await conn.async_setup()
  File "/Users/bdraco/home-assistant/homeassistant/components/homekit_controller/connection.py", line 245, in async_setup
    await self.pairing.async_populate_accessories_state(
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 1059, in async_populate_accessories_state
    await self._async_populate_accessories_state(force_update, attempts)
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 189, in _async_operation_lock_wrap
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/bleak_retry_connector/__init__.py", line 454, in _async_wrap_bluetooth_connection_error_retry
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 205, in _async_disconnect_on_missing_services_wrap
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 1072, in _async_populate_accessories_state
    await self._populate_accessories_and_characteristics(force_update, attempts)
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 1117, in _populate_accessories_and_characteristics
    accessories = await self._async_fetch_gatt_database()
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 872, in _async_fetch_gatt_database
    decoded = await self._read_signature(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aiohomekit/controller/ble/pairing.py", line 810, in _read_signature
    payload = await self.client.read_gatt_char(char)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/bleak/__init__.py", line 637, in read_gatt_char
    return await self._backend.read_gatt_char(char_specifier, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/homeassistant/components/esphome/bluetooth/client.py", line 83, in _async_wrap_bluetooth_connected_operation
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/homeassistant/components/esphome/bluetooth/client.py", line 109, in _async_wrap_bluetooth_operation
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/homeassistant/components/esphome/bluetooth/client.py", line 596, in read_gatt_char
    return await self._client.bluetooth_gatt_read(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aioesphomeapi/client.py", line 862, in bluetooth_gatt_read
    resp = await self._send_bluetooth_message_await_response(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aioesphomeapi/client.py", line 507, in _send_bluetooth_message_await_response
    resp = await self._connection.send_message_await_response_complex(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/bdraco/home-assistant/venv/lib/python3.11/site-packages/aioesphomeapi/connection.py", line 662, in send_message_await_response_complex
    await fut
asyncio.exceptions.CancelledError

Home Assistant can not connected to ESPHome device due to: google.protobuf.message.DecodeError: Field number 0 is illegal.

Error while reading incoming messages: Invalid preamble 5e
2022-12-13 12:14:38.800 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/connection.py", line 137, in _do_cleanup
await self._process_task
File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/connection.py", line 559, in _process_loop
msg.ParseFromString(pkt.data)
File "/usr/local/lib/python3.10/site-packages/google/protobuf/message.py", line 202, in ParseFromString
return self.MergeFromString(serialized)
File "/usr/local/lib/python3.10/site-packages/google/protobuf/internal/python_message.py", line 1128, in MergeFromString
if self._InternalParse(serialized, 0, length) != length:
File "/usr/local/lib/python3.10/site-packages/google/protobuf/internal/python_message.py", line 1178, in InternalParse
raise message_mod.DecodeError('Field number 0 is illegal.')
google.protobuf.message.DecodeError: Field number 0 is illegal.

Socket not closed when failed to connect may leak file descriptors

When trying to connect to a device which is offline, the socket isn't closed and the file descriptor is leaked.
Running python with the -W default -X tracemalloc options shows the following warning after each connection attempt.

/usr/lib/python3.7/traceback.py:357: ResourceWarning: unclosed <socket.socket fd=6, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.0.100', 43254)>
  filename, lineno, name, lookup_line=False, locals=f_locals))
Object allocated at (most recent call last):
  File "/home/pi/programs/influx_esphome/venv/lib/python3.7/site-packages/aioesphomeapi/connection.py", lineno 112
    self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Changing connection.py as follows appears to fix the issue:

--- connection.py.orig  2020-02-05 14:17:04.468032907 +0000
+++ connection.py       2020-02-05 14:25:02.458536299 +0000
@@ -62,12 +62,11 @@
         self._params.eventloop.create_task(func())
 
     async def _close_socket(self) -> None:
-        if not self._socket_connected:
-            return
-        async with self._write_lock:
-            self._socket_writer.close()
-            self._socket_writer = None
-            self._socket_reader = None
+        if self._socket_connected:
+            async with self._write_lock:
+                self._socket_writer.close()
+                self._socket_writer = None
+                self._socket_reader = None
         if self._socket is not None:
             self._socket.close()
         self._socket_connected = False

log level issue

My ESPHome device publish some logs with log level DEBUG.

If I try to subscribe to the log with subscribe_logs(log_callback, LOG_LEVEL_DEBUG) I receive nothing.
Messages are received only with subscribe_logs(log_callback, LOG_LEVEL_VERBOSE) or subscribe_logs(log_callback, LOG_LEVEL_VERY_VERBOSE).

Output example:

level: LOG_LEVEL_VERBOSE
message: "\033[0;36m[D][AirCon:976]: 0001776712: [=>] [BB 00 01 80 01 00 08 00] 1C 27 00 00 00 00 00 00 [1E 58] \033[0m"

There is a string "[D]" in output. It means that message has LOG_LEVEL = DEBUG.

It looks like an incorrect comparison somewhere in the code. "<" instead of "<=" or something like that.

Login error leaves read_loop/ping tasks hanging

I was doing some testing on my program using the API and a found a problem with the read_loop/ping tasks left hanging when I try the following with an incorrect password:

       ...
        try:
            self._esphome = aioesphomeapi.APIClient(eventloop=asyncio.get_running_loop(), address=url, port=port, password=password)
            await self._esphome.connect(login=True)
        except InvalidAuthAPIError as e:
            _LOGGER.error(f"ESPHome login failed: {e}")
            return False
       ...

The InvalidAuthAPIError exception is caught but now when await self._esphome.disconnect() is called during shutdown the disconnect code finds self._connection is now None so there is no way to clean up the hanging tasks as it returns immediately,

    async def disconnect(self, force: bool = False) -> None:
        if self._connection is None:
            return
        if force:

resulting in the error message on exit:

Task was destroyed but it is pending!
task: <Task pending name='Task-5' coro=<APIConnection._connect_start_ping.<locals>.func() done, defined at ...
...
Task was destroyed but it is pending!
task: <Task pending name='Task-6' coro=<Event.wait() done, defined at ...
...

Readme examples probably should be fixed

There is Subscribe to state changes of an ESPHome device example in the Readme.
This example generates an error:

Task exception was never retrieved
future: <Task finished name='Task-1' coro=<main() done, defined at test_from_github.py:4> exception=TypeError('__init__() takes 4 positional arguments but 5 were given')>
Traceback (most recent call last):
  File "test_from_github.py", line 7, in main
    cli = aioesphomeapi.APIClient(loop, "IP_ADDRESS", 6053, "API_PASSWORD")
TypeError: __init__() takes 4 positional arguments but 5 were given

Looks like loop should be deleted from APIClient() call

Unsafe removal of zeroconf listener from zeroconf callback

2023-09-05 18:03:34.850 DEBUG (MainThread) [aioesphomeapi.reconnect_logic] disco @ 192.168.211.119: Triggering connect because of received mDNS record record[ptr,in,_esphomelib._tcp.local.]=4500.0/4500,disco._esphomelib._tcp.local.
2023-09-05 18:03:34.851 DEBUG (MainThread) [aioesphomeapi.reconnect_logic] Removing zeroconf listener for disco
2023-09-05 18:03:34.851 ERROR (MainThread) [homeassistant] Error doing job: Exception in callback _SelectorDatagramTransport._read_ready()
Traceback (most recent call last):
  File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/events.py", line 80, in _run
    self._context.run(self._callback, *self._args)
  File "/opt/homebrew/Cellar/[email protected]/3.11.5/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/selector_events.py", line 1169, in _read_ready
    self._protocol.datagram_received(data, addr)
  File "src/zeroconf/_listener.py", line 80, in zeroconf._listener.AsyncListener.datagram_received
  File "src/zeroconf/_listener.py", line 161, in zeroconf._listener.AsyncListener.datagram_received
  File "src/zeroconf/_handlers/record_manager.py", line 134, in zeroconf._handlers.record_manager.RecordManager.async_updates_from_response
  File "src/zeroconf/_handlers/record_manager.py", line 58, in zeroconf._handlers.record_manager.RecordManager.async_updates
RuntimeError: set changed size during iteration

Malformed packet received during handshake results in indefinite pause

Background:
One of my devices is in an area with poor network connectivity and frequently disconnects and reconnects. Sometimes (time between 12 hours - 1 month), the device will disconnect and never reconnect even though it is connected to the wifi network.

Diagnosis:
After carefully monitoring the issue over a number of months and adding extra debug lines as necessary, it appears that this results from a perfectly timed disconnect during the handshake process.

Some extra logs were added and the relevant logs are displayed below.

2022-09-24 02:33:49.069 DEBUG (MainThread) [aioesphomeapi.connection] sonoff_switch_2 @ sonoff_switch_2.local: Got message of type <class 'api_pb2.ConnectResponse'>: 
2022-09-24 02:33:49.070 INFO (MainThread) [aioesphomeapi.connection] sonoff_switch_2 @ sonoff_switch_2.local: Error while reading incoming messages: Error while reading data: 0 bytes read on a total of 1 expected bytes
<-- Report fatal is run here following the error in reading the message -->
2022-09-24 02:33:49.073 DEBUG (MainThread) [aioesphomeapi.connection] connection complete for sonoff_switch_2 @ sonoff_switch_2.local

From this, it seems that the connect method is being run and login is called successfully. However, a packet is received that is malformed and calls the _report_fatal_error prior to the connect method returning. This results in the connection being closed while it remains marked as connected in reconnect_logic. Since the connection was closed and cleaned up, the disconnect callback is never called and thus a reconnect is never attempted again.

Solution:
I'm not sure if the malformed packet received during the connection phase should be ignored or passed along to reset the connection post initialization. Either

  1. A mutex is added to _report_fatal_error to postphone it from excecuting during the connection phase.
  2. Simply ignore the error during the connection phase.

For completeness below are additional unmodified logs:

2022-09-24 02:33:41.434 DEBUG (MainThread) [aioesphomeapi.connection] Starting connection for sonoff @ sonoff.local
2022-09-24 02:33:41.443 DEBUG (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Connecting to sonoff.local:6053 (AddrInfo(family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, proto=6, sockaddr=IPv4Sockaddr(address='10.0.0.179', port=6053)))
2022-09-24 02:33:41.479 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: Opened socket
2022-09-24 02:33:41.482 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: Sending <class 'api_pb2.HelloRequest'>: client_info: "Home Assistant 2022.8.7"
2022-09-24 02:33:41.482 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: finished sending
2022-09-24 02:33:41.510 DEBUG (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Got message of type <class 'api_pb2.HelloResponse'>: api_version_major: 1
api_version_minor: 3
server_info: "sonoff (esphome v1.15.3)"

2022-09-24 02:33:41.511 DEBUG (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Successfully connected ('sonoff (esphome v1.15.3)' API=1.3)
2022-09-24 02:33:41.512 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: Sending <class 'api_pb2.ConnectRequest'>: password: "REDACTED"

2022-09-24 02:33:41.512 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: finished sending
2022-09-24 02:33:49.068 DEBUG (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Got message of type <class 'api_pb2.GetTimeRequest'>: 
2022-09-24 02:33:49.068 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: Sending <class 'api_pb2.GetTimeResponse'>: epoch_seconds: 1664004829
2022-09-24 02:33:49.069 DEBUG (MainThread) [aioesphomeapi.connection] sonoff.local: finished sending
2022-09-24 02:33:49.069 DEBUG (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Got message of type <class 'api_pb2.ConnectResponse'>: 
2022-09-24 02:33:49.070 INFO (MainThread) [aioesphomeapi.connection] sonoff @ sonoff.local: Error while reading incoming messages: Error while reading data: 0 bytes read on a total of 1 expected bytes
2022-09-24 02:33:49.070 DEBUG (MainThread) [aioesphomeapi.connection] report fatal: Before cleanup for sonoff @ sonoff.local
2022-09-24 02:33:49.070 DEBUG (MainThread) [aioesphomeapi.connection] _cleanup: before framehelper for sonoff @ sonoff.local
2022-09-24 02:33:49.070 DEBUG (MainThread) [aioesphomeapi.connection] _cleanup: before socket for sonoff @ sonoff.local
2022-09-24 02:33:49.071 DEBUG (MainThread) [aioesphomeapi.connection] _cleanup: before on stop for sonoff @ sonoff.local
2022-09-24 02:33:49.071 DEBUG (MainThread) [aioesphomeapi.connection] _cleanup: finished for sonoff @ sonoff.local
2022-09-24 02:33:49.072 DEBUG (MainThread) [aioesphomeapi.connection] report fatal: after cleanup for sonoff @ sonoff.local
2022-09-24 02:33:49.073 DEBUG (MainThread) [aioesphomeapi.connection] connection complete for sonoff @ sonoff.local
2022-09-24 02:33:49.073 DEBUG (MainThread) [aioesphomeapi.reconnect_logic] _try_connect: after connect sonoff @ sonoff.local
2022-09-24 02:33:49.073 INFO (MainThread) [aioesphomeapi.reconnect_logic] Successfully connected to sonoff @ sonoff.local
2022-09-24 02:33:49.073 DEBUG (MainThread) [aioesphomeapi.reconnect_logic] sonoff @ sonoff.local: aioesphome._try_connect setting connected to false
2022-09-24 02:33:49.073 DEBUG (MainThread) [custom_components.esphome] Starting on_connect for sonoff.local
2022-09-24 02:33:49.074 WARNING (MainThread) [custom_components.esphome] Error getting initial data for sonoff.local: Connection not done for sonoff @ sonoff.local!
Traceback (most recent call last):
  File "/config/custom_components/esphome/__init__.py", line 272, in on_connect
    entry_data.device_info = await cli.device_info()
  File "/config/aioesphomeapi/client.py", line 244, in device_info
    self._check_connected()
  File "/config/aioesphomeapi/client.py", line 235, in _check_connected
    raise APIConnectionError(f"Connection not done for {self._log_name}!")
aioesphomeapi.core.APIConnectionError: Connection not done for sonoff @ sonoff.local!
2022-09-24 02:33:49.076 DEBUG (MainThread) [aioesphomeapi.reconnect_logic] _reconnect_once: waiting for sonoff @ sonoff.local

can't compile: 'requirements.txt' is missing in Pypi's SDIST archive

Hi everybody,

not sure if it's ok to report this issue here, please check and add it:

 * Package:    dev-python/aioesphomeapi-2.6.3
 * Repository: HomeAssistantRepository
 * Maintainer: [email protected]
 * Upstream:   [email protected]
 * USE:        abi_x86_64 amd64 elibc_glibc kernel_linux python_targets_python3_7 test userland_GNU
 * FEATURES:   network-sandbox preserve-libs sandbox userpriv usersandbox
>>> Unpacking source...
>>> Unpacking aioesphomeapi-2.6.3.tar.gz to /var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work
>>> Source unpacked in /var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work
>>> Preparing source in /var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work/aioesphomeapi-2.6.3 ...
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work/aioesphomeapi-2.6.3 ...
>>> Source configured.
>>> Compiling source in /var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work/aioesphomeapi-2.6.3 ...
 * python3_7: running distutils-r1_run_phase distutils-r1_python_compile
python3.7 setup.py build -j 10
Traceback (most recent call last):
  File "setup.py", line 32, in <module>
    with open(os.path.join(here, 'requirements.txt')) as requirements_txt:
FileNotFoundError: [Errno 2] No such file or directory: '/var/tmp/portage/dev-python/aioesphomeapi-2.6.3/work/aioesphomeapi-2.6.3/requirements.txt'
 * ERROR: dev-python/aioesphomeapi-2.6.3::HomeAssistantRepository failed (compile phase):
 *   (no error message)

But works with the archive from Github.

Just re-checked, all the older versions compile with the SDIST source:

root@g18-hasstest:/usr/portage/homeassistant/dev-python/aioesphomeapi # l
insgesamt 84
drwxr-xr-x   2 b homeassistant  4096  5. Sep 13:39 ./
drwxr-xr-x 980 b homeassistant 36864  5. Sep 12:23 ../
-rw-r--r--   1 b homeassistant   666 25. Aug 00:21 aioesphomeapi-2.4.0.ebuild
-rw-r--r--   1 b homeassistant   666 25. Aug 00:21 aioesphomeapi-2.4.1.ebuild
-rw-r--r--   1 b homeassistant   794 25. Aug 00:21 aioesphomeapi-2.4.2-r1.ebuild
-rw-r--r--   1 b homeassistant   794 25. Aug 00:21 aioesphomeapi-2.5.0.ebuild
-rw-r--r--   1 b homeassistant   794 25. Aug 00:21 aioesphomeapi-2.6.0.ebuild
-rw-r--r--   1 b homeassistant   824 25. Aug 00:21 aioesphomeapi-2.6.1.ebuild
-rw-r--r--   1 b homeassistant   949  5. Sep 13:36 aioesphomeapi-2.6.3.ebuild
-rw-r--r--   1 b homeassistant  4652  5. Sep 13:39 Manifest
-rw-r--r--   1 b homeassistant   460  5. Sep 13:27 metadata.xml
root@g18-hasstest:/usr/portage/homeassistant/dev-python/aioesphomeapi #

esphome on a separate network?

Hi!
Can interactions be done from outside the local area network?
I want to control an esp device that is not under the same LAN as my home assistant, not sure if this library might allow that.

Thanks

Edit: This description make me think is possible but I would appreciate an example/confirmation
imagen

Edit2: just found that on Oct 2019 was not possible, wondering if are there any updates.
esphome/feature-requests#441

home assistant logs "Error doing job: Task was destroyed but it is pending!"

home assistant logs "Error doing job: Task was destroyed but it is pending!". also, HA fails to connect to some devices sometimes. after the failure, a few seconds later, it reconnects successfully. I'm not sure they are related. installed HA via pip + virtualenv.

homeassistant              2022.10.3
aioesphomeapi              11.1.0
2022-10-12 11:31:23.830 ERROR (MainThread) [homeassistant] Error doing job: Task was destroyed but it is pending!:   File "/usr/home/hass/hass/.tox/python/bin/hass", line 10, in <module>
    sys.exit(main())                                                                                                                    
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/homeassistant/__main__.py", line 191, in main                       
    exit_code = runner.run(runtime_conf)                                                                                                
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/homeassistant/runner.py", line 119, in run                          
    return loop.run_until_complete(setup_and_run_hass(runtime_config))                                                                  
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 634, in run_until_complete                                               
    self.run_forever()                                                                                                                  
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 601, in run_forever                                                      
    self._run_once()                                                                                                                                                                                                                                                            
  File "/usr/local/lib/python3.9/asyncio/base_events.py", line 1897, in _run_once                                                       
    handle._run()                                                                                                                       
  File "/usr/local/lib/python3.9/asyncio/events.py", line 80, in _run                                                                   
    self._context.run(self._callback, *self._args)                                                                                      
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/reconnect_logic.py", line 171, in _reconnect_loop                                                                                                                                             
    await self._reconnect_once()                                    
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/reconnect_logic.py", line 166, in _reconnect_once
    await self._try_connect()                                       
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/reconnect_logic.py", line 121, in _try_connect
    await self._cli.connect(on_stop=self._on_disconnect, login=True)                                                                    
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/client.py", line 240, in connect                      
    await self._connection.connect(login=login)                                                                                         
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/connection.py", line 305, in connect                  
    await _do_connect()                                             
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/connection.py", line 294, in _do_connect              
    await self._connect_init_frame_helper()                         
  File "/usr/home/hass/hass/.tox/python/lib/python3.9/site-packages/aioesphomeapi/connection.py", line 205, in _connect_init_frame_helper
    asyncio.create_task(self._process_loop())                                                                                           
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 361, in create_task                                                            
    task = loop.create_task(coro)                                   

How to build logic on disconnect

It is not clear to me how to build code based on if the state gets disconnected, because i can't find any documentation on this topic. How can i retry a connection on disconnect, or build logic when the connection to the ESP device is lost?

`ValueError: 6 is not a valid ClimateMode` when getting climate device entities

I'm encountering this error enumerating the entities of my climate device.

This problem is occurring within Homeassistant as well (see logs).

asyncio funkiness because I'm running in Jupyter.

Successfully installed aioesphomeapi-2.8.0

import nest_asyncio
nest_asyncio.apply()
import aioesphomeapi
import asyncio

async def main():
    """Connect to an ESPHome device and get details."""
    loop = asyncio.get_running_loop()

    # Establish connection
    api = aioesphomeapi.APIClient(loop, "prusa_enclosure.local", 6053, "")
    await api.connect(login=True)

    # Get API version of the device's firmware
    print(api.api_version)

    # Show device details
    device_info = await api.device_info()

    # List all entities of the device
    entities = await api.list_entities_services()
    for entity in entities[0]:
        print(entity)


loop = asyncio.get_event_loop()
loop.run_until_complete(main())
APIVersion(major=1, minor=4)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-2-764d321eea0b> in <module>
     25 
     26 loop = asyncio.get_event_loop()
---> 27 loop.run_until_complete(main())

~/.venv3/lib/python3.9/site-packages/nest_asyncio.py in run_until_complete(self, future)
     68                 raise RuntimeError(
     69                     'Event loop stopped before Future completed.')
---> 70             return f.result()
     71 
     72     def _run_once(self):

/usr/lib/python3.9/asyncio/futures.py in result(self)
    199         self.__log_traceback = False
    200         if self._exception is not None:
--> 201             raise self._exception
    202         return self._result
    203 

/usr/lib/python3.9/asyncio/tasks.py in __step(***failed resolving arguments***)
    254                 # We use the `send` method directly, because coroutines
    255                 # don't have `__iter__` and `__next__` methods.
--> 256                 result = coro.send(None)
    257             else:
    258                 result = coro.throw(exc)

<ipython-input-2-764d321eea0b> in main()
     19 
     20     # List all entities of the device
---> 21     entities = await api.list_entities_services()
     22     for entity in entities[0]:
     23         print(entity)

~/.venv3/lib/python3.9/site-packages/aioesphomeapi/client.py in list_entities_services(self)
    135             for key, _ in attr.fields_dict(cls).items():
    136                 kwargs[key] = getattr(msg, key)
--> 137             entities.append(cls(**kwargs))
    138         return entities, services
    139 

~/.venv3/lib/python3.9/site-packages/aioesphomeapi/model.py in __init__(self, object_id, key, name, unique_id, supports_current_temperature, supports_two_point_target_temperature, supported_modes, visual_min_temperature, visual_max_temperature, visual_temperature_step, supports_away, supports_action, supported_fan_modes, supported_swing_modes)
      7     self.supports_two_point_target_temperature = supports_two_point_target_temperature
      8     if supported_modes is not NOTHING:
----> 9         self.supported_modes = __attr_converter_supported_modes(supported_modes)
     10     else:
     11         self.supported_modes = __attr_converter_supported_modes(__attr_factory_supported_modes())

~/.venv3/lib/python3.9/site-packages/aioesphomeapi/model.py in _convert_climate_modes(value)
    243 
    244 def _convert_climate_modes(value):
--> 245     return [ClimateMode(val) for val in value]
    246 
    247 

~/.venv3/lib/python3.9/site-packages/aioesphomeapi/model.py in <listcomp>(.0)
    243 
    244 def _convert_climate_modes(value):
--> 245     return [ClimateMode(val) for val in value]
    246 
    247 

/usr/lib/python3.9/enum.py in __call__(cls, value, names, module, qualname, type, start)
    358         """
    359         if names is None:  # simple value lookup
--> 360             return cls.__new__(cls, value)
    361         # otherwise, functional API: we're creating a new Enum type
    362         return cls._create_(

/usr/lib/python3.9/enum.py in __new__(cls, value)
    675             ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
    676             if result is None and exc is None:
--> 677                 raise ve_exc
    678             elif exc is None:
    679                 exc = TypeError(

ValueError: 6 is not a valid ClimateMode
esphome:
  name: prusa_enclosure
  platform: ESP32
  board: esp32dev

wifi:
  ssid: ""
  password: ""

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Prusa Enclosure Fallback Hotspot"
    password: ""

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:

output:
  - platform: ledc
    pin: GPIO32
    id: fan_output
    frequency: "25kHz"

  - platform: template
    id: fan_output_scaled
    type: float
    write_action:
      - output.set_level:
          id: fan_output
          level: !lambda |-
                 return (state ? state*.55+.20 : 0);

light:
  - platform: monochromatic
    name: "Enclosure fan"
    output: fan_output_scaled
    gamma_correct: 1
    default_transition_length: 0s

  - platform: fastled_clockless
    chipset: WS2812B
    pin: GPIO26
    num_leds: 68
    rgb_order: GRB
    name: "Enclosure light"

sensor:
  - platform: pulse_counter
    pin: GPIO33
    name: 'Fan speed'
    filters:
      - multiply: 0.5
    update_interval: 1s
        
  - platform: dht
    pin: 25
    temperature:
            name: "Enclosure temperature"
            id: "enclosure_temp"
            unit_of_measurement: "°C"
    humidity:
            name: "Enclosure humidity"
    update_interval: 1s
    model: DHT22


climate:
  - platform: pid
    name: "Enclosure PID controller"
    id: pid_enclosure
    sensor: enclosure_temp
    default_target_temperature: 26.00C
    cool_output: fan_output
    control_parameters:
        kp: 0.25000
        ki: 0.00150
        kd: 0.15000


switch:
  - platform: template
    name: "PID Autotune"
    turn_on_action:
      - climate.pid.autotune:
              id: pid_enclosure
              noiseband: 0.10
              negative_output: -75%
2021-06-16 09:15:10 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/esphome/__init__.py", line 214, in on_login
    entity_infos, services = await cli.list_entities_services()
  File "/usr/local/lib/python3.8/site-packages/aioesphomeapi/client.py", line 137, in list_entities_services
    entities.append(cls(**kwargs))
  File "<attrs generated init aioesphomeapi.model.ClimateInfo>", line 9, in __init__
    self.supported_modes = __attr_converter_supported_modes(supported_modes)
  File "/usr/local/lib/python3.8/site-packages/aioesphomeapi/model.py", line 245, in _convert_climate_modes
    return [ClimateMode(val) for val in value]
  File "/usr/local/lib/python3.8/site-packages/aioesphomeapi/model.py", line 245, in <listcomp>
    return [ClimateMode(val) for val in value]
  File "/usr/local/lib/python3.8/enum.py", line 339, in __call__
    return cls.__new__(cls, value)
  File "/usr/local/lib/python3.8/enum.py", line 662, in __new__
    raise ve_exc
ValueError: 6 is not a valid ClimateMode

LOG_LEVEL_CONFIG is missed; LOG_LEVEL_DEBUG, LOG_LEVEL_VERBOSE and LOG_LEVEL_VERY_VERBOSE are reduced by 1

name='LOG_LEVEL_DEBUG', index=4, number=4,

I'm GitHub newbie and I don't know if anyone will see my message in the closed issue. So I made new one.

There is some discrepancy in the LOG_LEVEL constants of ESPHome and aioesphomeapi:

In ESPHome core/log.h

#define ESPHOME_LOG_LEVEL_NONE 0
#define ESPHOME_LOG_LEVEL_ERROR 1
#define ESPHOME_LOG_LEVEL_WARN 2
#define ESPHOME_LOG_LEVEL_INFO 3
#define ESPHOME_LOG_LEVEL_CONFIG 4
#define ESPHOME_LOG_LEVEL_DEBUG 5
#define ESPHOME_LOG_LEVEL_VERBOSE 6
#define ESPHOME_LOG_LEVEL_VERY_VERBOSE 7

In aioesphomeapi api_pb2.py

    ...
    _descriptor.EnumValueDescriptor(
      name='LOG_LEVEL_INFO', index=3, number=3,
      serialized_options=None,
      type=None),
    _descriptor.EnumValueDescriptor(
      name='LOG_LEVEL_DEBUG', index=4, number=4,
      serialized_options=None,
      type=None),
    ...

From LOG_LEVEL_NONE to LOG_LEVEL_INFO all constants are the same.
From LOG_LEVEL_DEBUG to LOG_LEVEL_VERY_VERBOSE all constants are reduced by 1.

There is no LOG_LEVEL_CONFIG in aioesphomeapi and this is the reason for shifting constants by one and the incorrect work of subscribe_logs(log_callback, LOG_LEVEL_DEBUG).

Using adressable_set from aioesphomeapi

I'm trying to use aioesphomeapi from a Python program to drive some leds with fastled. The aim is to choose which color on which led i wanna to turn on. I was thinking of sending an array like this one : [ n_led, color_r, color_b, color_g , n_led_next, color_r, color_b, color_g ... ]
I'm confuse on how to do that, I try to read the documentation but i do not understand on how to add an argument on a call from aiesphomeapi and what to add on the YAML for my ESP.

Can somebody have an example or explain to me how to do it ?

Thanks

esphome voice_assistant: "Server could not be started"

I have an ESP32 DevKit C board with an I2S microphone and speaker which I am trying to get to work using the ESPHome / Home Assistant voice_assistant integration / pipeline. I have a binary_sensor that triggers voice_assistant.start on press and voice_assistant.end on release, just as in the documentation. This seems to work well according to the logs:

[10:39:02][I][app:102]: ESPHome version 2023.4.4 compiled on May 10 2023, 15:09:22
[10:39:02][C][wifi:505]: WiFi:
[10:39:02][C][wifi:363]:   Local MAC: C8:F0:9E:50:4C:48
[10:39:02][C][wifi:364]:   SSID: [redacted]
[10:39:02][C][wifi:365]:   IP Address: 192.168.30.131
[10:39:02][C][wifi:367]:   BSSID: [redacted]
[10:39:02][C][wifi:368]:   Hostname: 'kitchen-voice-assistant'
[10:39:02][C][wifi:370]:   Signal strength: -50 dB ▂▄▆█
[10:39:02][C][wifi:374]:   Channel: 10
[10:39:02][C][wifi:375]:   Subnet: 255.255.255.0
[10:39:02][C][wifi:376]:   Gateway: 192.168.30.1
[10:39:02][C][wifi:377]:   DNS1: 192.168.30.1
[10:39:02][C][wifi:378]:   DNS2: 0.0.0.0
[10:39:02][C][logger:294]: Logger:
[10:39:02][C][logger:295]:   Level: DEBUG
[10:39:02][C][logger:296]:   Log Baud Rate: 115200
[10:39:02][C][logger:297]:   Hardware UART: UART0
[10:39:03][C][gpio.binary_sensor:015]: GPIO Binary Sensor 'voice_button'
[10:39:03][C][gpio.binary_sensor:016]:   Pin: GPIO13
[10:39:03][C][mdns:108]: mDNS:
[10:39:03][C][mdns:109]:   Hostname: kitchen-voice-assistant
[10:39:03][C][ota:093]: Over-The-Air Updates:
[10:39:03][C][ota:094]:   Address: kitchen-voice-assistant.local:3232
[10:39:03][C][ota:097]:   Using Password.
[10:39:03][C][api:138]: API Server:
[10:39:03][C][api:139]:   Address: kitchen-voice-assistant.local:6053
[10:39:03][C][api:141]:   Using noise encryption: YES
[10:40:02][D][binary_sensor:036]: 'voice_button': Sending state ON
[10:40:02][D][voice_assistant:065]: Requesting start...
[10:40:02][D][voice_assistant:045]: Starting...
[10:40:02][D][voice_assistant:083]: Assist Pipeline running
[10:40:07][D][binary_sensor:036]: 'voice_button': Sending state OFF
[10:40:07][D][voice_assistant:073]: Signaling stop...
[10:40:15][D][binary_sensor:036]: 'voice_button': Sending state ON
[10:40:15][D][voice_assistant:065]: Requesting start...
[10:40:15][D][voice_assistant:045]: Starting...
[10:40:17][D][binary_sensor:036]: 'voice_button': Sending state OFF
[10:40:17][D][voice_assistant:073]: Signaling stop...

However, the HA voice assistant pipeline is never activated on the Home Assistant end, and aioesphomeapi.client reports a "Server could not be started` error:

2023-05-16 10:38:59.321 INFO (MainThread) [aioesphomeapi.reconnect_logic] Successfully connected to kitchen-voice-assistant @ 192.168.30.131
2023-05-16 10:40:15.096 ERROR (MainThread) [aioesphomeapi.client] Server could not be started
2023-05-16 10:40:32.230 WARNING (MainThread) [homeassistant.components.esphome.voice_assistant] Pipeline timeout

This error happens on the second button press. I tried to understand the code paths involved but failed at that.

ESPHome version is 2023.4.4, Home Assistant is 2023.5.3 meaning aioesphomeapi is at version 3.7.4. I'm not running HASS, HA is running as a docker-compose image but with network_mode: host and privileged: true so it should be fine for it to open UDP ports.

Here is the relevant part of my config YAML:

api:
  encryption:
    key: !secret api_key

binary_sensor:
  - platform: gpio
    pin:
      number: GPIO13
      inverted: true
      mode:
        pullup: true
        input: true
    id: voice_button
    internal: true
    filters:
      - delayed_on: 10ms
      - delayed_off: 10ms
    on_press:
      - voice_assistant.start:
    on_release:
      - voice_assistant.stop:

i2s_audio:
  - id: i2smicrophone
    i2s_lrclk_pin: GPIO27
    i2s_bclk_pin: GPIO14

microphone:
  - id: microphone_id
    platform: i2s_audio
    i2s_din_pin: GPIO26
    i2s_audio_id: i2smicrophone

voice_assistant:
  microphone: microphone_id

Since the error happens within aioesphomeapi.client, I thought this would be the best venue for the bug report, but please do let me know if that should go in the HA core or ESPHome repos. Any advice would be appreciated!

Invalid protobuf message: expected bytes, bytearray found

Was building a new version of my Docker container that is using the ESPHome API.
Upon building, the following error gets raised. This error wasn't there before, and the changes I made to my container are unrelated to the ESPHome part, so I believe something got broken recently in the API package

energy-meter-1.local: Connection error occurred: Invalid protobuf message: expected bytes, bytearray found
Fatal error: protocol.data_received() call failed.
protocol: <aioesphomeapi._frame_helper.APIPlaintextFrameHelper object at 0x7f6fedd8bb50>
transport: <_SelectorSocketTransport closing fd=6 read=idle write=<idle, bufsize=0>>
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/asyncio/selector_events.py", line 876, in _read_ready__data_received
    self._protocol.data_received(data)
  File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/_frame_helper.py", line 195, in data_received
    self._callback_packet(msg_type_int, packet_data)
  File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/_frame_helper.py", line 110, in _callback_packet
    self._on_pkt(Packet(type_, data))
  File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/connection.py", line 581, in _process_packet
    msg.ParseFromString(pkt.data)
TypeError: expected bytes, bytearray found

The ESPHome device is and ESP32 and is running on ESPHome 2022.12.3 FW

Let me know if you need any debugging or more information

Communication happens, but socket is closed when device info is requested.

I am using home assistant docker on a raspberry pi 4 (64bit os). HA can't connect to my esphome devices. I was able to pull this out of the logs and I am unsure how to further debug this at the moment. I will try and dig deeper in a bit, but wanted to see if anyone else had this issue. This is working just fine with home assistant docker on a x86 machine.

LOG

2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Connecting to 10.10.10.116:6053 (AddrInfo(family=<AddressFamily.AF_INET: 2>, type=<SocketKind.SOCK_STREAM: 1>, proto=6, sockaddr=IPv4S
ockaddr(address='10.10.10.116', port=6053)))
2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Opened socket for
2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Sending <class 'api_pb2.HelloRequest'>: client_info: "aioesphomeapi"

2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi._frame_helper] Sending plaintext frame 000f010a0d61696f657370686f6d65617069
2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Got message of type <class 'api_pb2.HelloResponse'>: api_version_major: 1
api_version_minor: 6
server_info: "sunroom-light (esphome v2022.1.1)"

2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Successfully connected ('sunroom-light (esphome v2022.1.1)' API=1.6)
2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Sending <class 'api_pb2.DeviceInfoRequest'>:
2022-01-26 22:11:34 DEBUG (MainThread) [aioesphomeapi._frame_helper] Sending plaintext frame 000009
2022-01-26 22:11:44 DEBUG (MainThread) [aioesphomeapi.connection] 10.10.10.116: Socket closed, stopping read loop

Log error during HA shutdown

During shutdown of HA I always get the following log line:

2021-06-27 18:02:31 INFO (MainThread) [aioesphomeapi.connection] 192.168.xxx.yyy: Error while reading incoming messages: Error while receiving data: 0 bytes read on a total of 1 expected bytes

Please notice that beside it should not be logged at all, it's has a Error description with INFO log level.

Simone

Can't connect after latest update "A Stream Socket was expected" Error

Traceback (most recent call last): File "C:\Users\Administrator\aio\aio\lib\site-packages\aioesphomeapi\client.py", line 176, in connect await self._connection.connect() File "C:\Users\Administrator\aio\aio\lib\site-packages\aioesphomeapi\connection.py", line 157, in connect self._socket_reader, self._socket_writer = await asyncio.open_connection( File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\asyncio\streams.py", line 52, in open_connection transport, _ = await loop.create_connection( File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 1047, in create_connection raise ValueError( ValueError: A Stream Socket was expected, got <socket.socket fd=592, family=AddressFamily.AF_INET, type=0, proto=6, laddr=('192.168.2.4', 32149), raddr=('192.168.2.25', 6053)> The above exception was the direct cause of the following exception: Traceback (most recent call last): File "t.py", line 24, in <module> loop.run_until_complete(main()) File "C:\Users\Administrator\AppData\Local\Programs\Python\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete return future.result() File "t.py", line 10, in main await api.connect(login=True) File "C:\Users\Administrator\aio\aio\lib\site-packages\aioesphomeapi\client.py", line 184, in connect raise APIConnectionError( aioesphomeapi.core.APIConnectionError: Unexpected error while connecting to 192.168.2.25: A Stream Socket was expected, got <socket.socket fd=592, family=AddressFamily.AF_INET, type=0, proto=6, laddr=('192.168.2.4', 32149), raddr=('192.168.2.25', 6053)>

After replacing, in line 132 of connection.py

self._socket = socket.socket( family=addr.family, type=addr.type, proto=addr.proto )

with

self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

The problem is fixed.

Encryption instead of password

I have the native API enabled using encryption and key instead of password. The example shows connecting using password for aioesphomeapi. Do you have an example use encryption and key or can this not be done with aioesphomeapi?

led turn on example?

It's hard to find examples online! :)

Anyone know how I'd turn an LED on? (Eventually one of a few relays)?

Here's my yaml and python code.
(With some stuff cut from the yaml, like time-server, for brevity):
---- sprinklers.yaml ------------------

esphome:
  name: sprinklers

esp8266:
  board: nodemcuv2

# Enable logging
logger:

api:
  password: "meowmix"
  reboot_timeout: 0s
  services:
    - service: yellow_on
      then:
        - switch.turn_on: yellow_pin

ota:
  password: "meowmix"

captive_portal:

switch:
- platform: gpio
  pin: D8
  id: yellow_pin
  # mode:
  #   input: false
  #   pullup: false
- platform: gpio
  pin: D3
  id: green_pin
- platform: gpio
  id: red_pin
  pin:
    number: D4
    mode: OUTPUT
  restore_mode: ALWAYS_OFF 
  on_turn_on:
    - logger.log: "RED On!"
  on_turn_off:
    - logger.log: "RED Off!"

- platform: template
  name: "Yellow LED"
  optimistic: yes
  id: yellowled
  turn_on_action:
  - while:
      condition:
        lambda: 'return true;'
      then:
      - switch.turn_on: yellow_pin
      - delay: 500ms 
      - switch.turn_off: yellow_pin
      - delay: 500ms
  turn_off_action:
  - switch.turn_off: yellow_pin

# - platform: template
#   name: "Red LED"
#   optimistic: yes
#   id: redled
#   turn_on_action:
#   - switch.turn_on: red_pin
#   turn_off_action:
#   - switch.turn_off: red_pin

- platform: template
  name: "Green LED"
  optimistic: yes
  id: greenled
  turn_on_action:
  - switch.turn_on: green_pin
  turn_off_action:
  - switch.turn_off: green_pin

---------- sprinkler_led_on_test.py -------------------

#!/usr/bin/env python

import aioesphomeapi
from aioesphomeapi.model import (UserService)
import asyncio
import ipdb

async def main():
	"""Connect to an ESPHome device and get details."""

	# Establish connection
	api = aioesphomeapi.APIClient("sprinklers.local", 6053, "meowmix")
	await api.connect(login=True)

	# List all entities of the device
	entities = await api.list_entities_services()
	print("\nEntities:")
	for eli, entlist in enumerate(entities):
		for ei, ent in enumerate(entlist):
			print(f"[{eli}][{ei}] {ent}")

	service = UserService(
			name="yellow_on",
			)
	await api.execute_service(service, data={})
	#ipdb.set_trace()
	# print( [f" {i}\n" for i in entities])

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

device_class for TextSensor ?

I'm using device_class to find the device type associated to an Entity. For example, device_class=='power', it's a power-meter. This is for SensorInfo, but some component in ESPHome only support TextSensor. This is the case in example for the ble_scanner. This sounds good because it returns a JSON string, but as TextSensorInfo doesn't provide device_class, I'm unable to find if this is ble_scanner or any other TextSensor component.

Is there a way to fix this (without having to hardcode this information in another field like the name for example) ?

Best regards.

send message complex is too slow

The current client needs to create two closures for each Bluetooth message.

Need to come up with a way to have a single place where futures are resolved to avoid creating the closures

DeprecationWarning: Call to deprecated protobuf functions

DeprecationWarning: Call to deprecated create function EnumValueDescriptor(). Note: Create unlinked descriptors is going to go away. Please use get/find descriptors from generated code or query the descriptor_pool.

DeprecationWarning: Call to deprecated create function FileDescriptor(). Note: Create unlinked descriptors is going to go away. Please use get/find descriptors from generated code or query the descriptor_pool.

DeprecationWarning: Call to deprecated create function EnumDescriptor(). Note: Create unlinked descriptors is going to go away. Please use get/find descriptors from generated code or query the descriptor_pool.

DeprecationWarning: Call to deprecated create function Descriptor(). Note: Create unlinked descriptors is going to go away. Please use get/find descriptors from generated code or query the descriptor_pool.

The warning gets printed ~100 times while running the home-assistant test suite.

Just a heads up, not sure how much attention you pay to the home-assistant component tests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.