grimmpp / home-assistant-eltako

Integration for Eltako 14 series in Home Assistant
MIT License
40 stars 7 forks source link

Allow specifying serial device path manually #121

Open legnad opened 4 months ago

legnad commented 4 months ago

Is it possible to add the option to manually specify the serial device path? Would this allow serial devices to be connected via ser2net?

Since I've run into USB stability problems in conjunction with running HA on a Synology NAS (VM), I've migrated the zigbee radio to an old Raspberry Pi running a ser2net docker container and set the connection port in ZHA config (see https://community.home-assistant.io/t/connecting-to-a-remote-zigbee-coordinator-with-zha-using-ser2net/561762)

With e.g. ZHA it is possible to do:

grafik

grafik

legnad commented 4 months ago

Sorry, I just figured this may be configured by providing the serial_path option in the gateway: YAML section. Good stuff! Going to try it out soon!

(docs: https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/gateway_usage)

legnad commented 4 months ago

Well, I can not get it to work. I have an RPi up and running ser2net-docker successfully (2 docker containers actually, another one for ZHA which works like a charm).

Now, when trying to set up the Eltako Integration (a second gateway actually, which worked before when physically plugged in via usb) there is "Unknown error occurred": grafik

Relevant Debug-Logging:

2024-07-23 23:17:06.753 DEBUG (MainThread) [eltako] Available gateways to be added: ['EnOcean Gateway - enocean-usb300 (Id: 2, BaseId: FF-9F-5E-80)']
2024-07-23 23:17:06.753 DEBUG (MainThread) [eltako] Available serial paths: ['/dev/serial/by-path/pci-0000:00:04.0-usb-0:2:1.0-port0', '/dev/serial/by-path/pci-0000:00:04.0-usbv2-0:2:1.0-port0', 'tcp://192.168.2.7:20109']
2024-07-23 23:17:08.679 DEBUG (MainThread) [eltako] Add new gateway
2024-07-23 23:17:08.696 DEBUG (MainThread) [eltako] Config: {'gateway': [{'id': 1, 'base_id': 'FF-AA-80-00', 'device_type': 'fgw14usb', 'devices': {'binary_sensor': [{'id': 'FE-D8-33-09', 'eep': 'F6-02-01', 'name': 'Binary sensor', 'invert_signal': False}, {'id': 'FE-DA-61-60', 'eep': 'F6-10-00', 'name': 'Fenster Kinderzimmer', 'invert_signal': False}], 'sensor': [{'id': 'FF-CD-01-92', 'eep': 'A5-10-12', 'name': 'Arbeitszimmer Temperatur & Luftfeuchte', 'language': 'en', 'meter_tariffs': [1], 'voc_type_indexes': [0]}, {'id': 'FF-BC-01-12', 'eep': 'A5-10-12', 'name': 'Schlafzimmer Temperatur & Luftfeuchte', 'language': 'en', 'meter_tariffs': [1], 'voc_type_indexes': [0]}, {'id': 'FF-AC-9D-12', 'eep': 'A5-10-12', 'name': 'Kinderzimmer Temperatur & Luftfeuchte', 'language': 'en', 'meter_tariffs': [1], 'voc_type_indexes': [0]}, {'id': 'FF-DB-A6-92', 'eep': 'A5-10-12', 'name': 'Bibliothek Temperatur & Luftfeuchte', 'language': 'en', 'meter_tariffs': [1], 'voc_type_indexes': [0]}], 'light': [{'id': '00-00-00-0C', 'eep': 'A5-38-08', 'name': 'Arbeitszimmer Dimmer', 'sender': {'id': '00-00-B0-0C', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0A', 'eep': 'A5-38-08', 'name': 'Schlafzimmer Dimmer', 'sender': {'id': '00-00-B0-0A', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0B', 'eep': 'A5-38-08', 'name': 'Kinderzimmer Dimmer', 'sender': {'id': '00-00-B0-0B', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0F', 'eep': 'M5-38-08', 'name': 'Bibliothek Licht', 'sender': {'id': '00-00-B0-0F', 'eep': 'A5-38-08'}}, {'id': '00-00-00-13', 'eep': 'M5-38-08', 'name': 'Badezimmer Licht', 'sender': {'id': '00-00-B0-13', 'eep': 'A5-38-08'}}, {'id': '00-00-00-15', 'eep': 'M5-38-08', 'name': 'Badezimmer LED Panel (Eltako)', 'sender': {'id': '00-00-B0-15', 'eep': 'A5-38-08'}}, {'id': '00-00-00-16', 'eep': 'M5-38-08', 'name': 'Flur Licht', 'sender': {'id': '00-00-B0-16', 'eep': 'A5-38-08'}}], 'cover': [{'id': '00-00-00-01', 'eep': 'G5-3F-7F', 'name': 'Schlafzimmer Rolladen', 'sender': {'id': '00-00-B0-01', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-02', 'eep': 'G5-3F-7F', 'name': 'Kinderzimmer Rolladen', 'sender': {'id': '00-00-B0-02', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-04', 'eep': 'G5-3F-7F', 'name': 'Arbeitszimmer Rolladen', 'sender': {'id': '00-00-B0-04', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-06', 'eep': 'G5-3F-7F', 'name': 'Bibliothek Rolladen', 'sender': {'id': '00-00-B0-06', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 29, 'time_closes': 28}, {'id': '00-00-00-07', 'eep': 'G5-3F-7F', 'name': 'Küche Rolladen', 'sender': {'id': '00-00-B0-07', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>}]}, 'name': ''}, {'id': 2, 'base_id': 'FF-9F-5E-80', 'device_type': 'enocean-usb300', 'serial_path': 'tcp://192.168.2.7:20109', 'devices': {'climate': [{'id': 'FF-E9-20-9B', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Schlafzimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9B', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-BC-01-01', 'eep': 'A5-10-06'}, 'min_target_temperature': 17, 'max_target_temperature': 25}, {'id': 'FF-E9-20-9C', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Kinderzimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9C', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-AC-9D-01', 'eep': 'A5-10-06'}, 'min_target_temperature': 17, 'max_target_temperature': 25}, {'id': 'FF-E9-20-9D', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Arbeitszimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9D', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-CD-01-81', 'eep': 'A5-10-06'}, 'min_target_temperature': 17, 'max_target_temperature': 25}, {'id': 'FF-E9-20-9E', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Bibliothek Thermostat', 'sender': {'id': 'FF-9F-5E-9E', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-DB-A6-81', 'eep': 'A5-10-06'}, 'min_target_temperature': 17, 'max_target_temperature': 25}]}, 'name': ''}]}

2024-07-23 23:17:08.698 ERROR (MainThread) [aiohttp.server] Error handling request
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/ban.py", line 85, in ban_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 74, 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 415, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 518, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/eltako/config_flow.py", line 41, in async_step_detect
    return await self.manual_selection_routine(user_input)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/eltako/config_flow.py", line 63, in manual_selection_routine
    if await self.validate_eltako_conf(user_input):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/eltako/config_flow.py", line 134, in validate_eltako_conf
    path_is_valid = await self.hass.async_add_executor_job(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/eltako/gateway.py", line 380, in validate_path
    serial.serial_for_url(path, baud_rate, timeout=0.1)
  File "/usr/local/lib/python3.12/site-packages/serial/__init__.py", line 85, in serial_for_url
    raise ValueError('invalid URL, protocol {!r} not known'.format(protocol))
ValueError: invalid URL, protocol 'tcp' not known

My eltako.yaml:

...
  - id: 2
    base_id: FF-9F-5E-80 # PioTek FAM-USB 515 # /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0P4TMI-if00-port0
    device_type: "enocean-usb300"
    serial_path: "tcp://192.168.2.7:20109"
    devices:
...
legnad commented 4 months ago

No luck by using the bare IP and port too:


2024-07-23 23:27:41.551 DEBUG (MainThread) [eltako] Available gateways to be added: ['EnOcean Gateway - enocean-usb300 (Id: 2, BaseId: FF-9F-5E-80)']
2024-07-23 23:27:41.551 DEBUG (MainThread) [eltako] Available serial paths: ['/dev/serial/by-path/pci-0000:00:04.0-usb-0:2:1.0-port0', '192.168.2.7:20109', '/dev/serial/by-path/pci-0000:00:04.0-usbv2-0:2:1.0-port0']
2024-07-23 23:27:43.017 DEBUG (MainThread) [eltako] Add new gateway
2024-07-23 23:27:43.034 DEBUG (MainThread) [eltako] Config: {'gateway': [{'id': 1, 'base_id': 'FF-AA-80-00', 'device_type': 'fgw14usb', 'devices': {'binary_sensor': [{'id': 'FE-D8-33-09', 'eep': 'F6-02-01', 'invert_signal': False, 'name': 'Binary sensor'}, {'id': 'FE-DA-61-60', 'eep': 'F6-10-00', 'name': 'Fenster Kinderzimmer', 'invert_signal': False}], 'sensor': [{'id': 'FF-CD-01-92', 'eep': 'A5-10-12', 'name': 'Arbeitszimmer Temperatur & Luftfeuchte', 'voc_type_indexes': [0], 'language': 'en', 'meter_tariffs': [1]}, {'id': 'FF-BC-01-12', 'eep': 'A5-10-12', 'name': 'Schlafzimmer Temperatur & Luftfeuchte', 'voc_type_indexes': [0], 'language': 'en', 'meter_tariffs': [1]}, {'id': 'FF-AC-9D-12', 'eep': 'A5-10-12', 'name': 'Kinderzimmer Temperatur & Luftfeuchte', 'voc_type_indexes': [0], 'language': 'en', 'meter_tariffs': [1]}, {'id': 'FF-DB-A6-92', 'eep': 'A5-10-12', 'name': 'Bibliothek Temperatur & Luftfeuchte', 'voc_type_indexes': [0], 'language': 'en', 'meter_tariffs': [1]}], 'light': [{'id': '00-00-00-0C', 'eep': 'A5-38-08', 'name': 'Arbeitszimmer Dimmer', 'sender': {'id': '00-00-B0-0C', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0A', 'eep': 'A5-38-08', 'name': 'Schlafzimmer Dimmer', 'sender': {'id': '00-00-B0-0A', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0B', 'eep': 'A5-38-08', 'name': 'Kinderzimmer Dimmer', 'sender': {'id': '00-00-B0-0B', 'eep': 'A5-38-08'}}, {'id': '00-00-00-0F', 'eep': 'M5-38-08', 'name': 'Bibliothek Licht', 'sender': {'id': '00-00-B0-0F', 'eep': 'A5-38-08'}}, {'id': '00-00-00-13', 'eep': 'M5-38-08', 'name': 'Badezimmer Licht', 'sender': {'id': '00-00-B0-13', 'eep': 'A5-38-08'}}, {'id': '00-00-00-15', 'eep': 'M5-38-08', 'name': 'Badezimmer LED Panel (Eltako)', 'sender': {'id': '00-00-B0-15', 'eep': 'A5-38-08'}}, {'id': '00-00-00-16', 'eep': 'M5-38-08', 'name': 'Flur Licht', 'sender': {'id': '00-00-B0-16', 'eep': 'A5-38-08'}}], 'cover': [{'id': '00-00-00-01', 'eep': 'G5-3F-7F', 'name': 'Schlafzimmer Rolladen', 'sender': {'id': '00-00-B0-01', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-02', 'eep': 'G5-3F-7F', 'name': 'Kinderzimmer Rolladen', 'sender': {'id': '00-00-B0-02', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-04', 'eep': 'G5-3F-7F', 'name': 'Arbeitszimmer Rolladen', 'sender': {'id': '00-00-B0-04', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 22, 'time_closes': 20}, {'id': '00-00-00-06', 'eep': 'G5-3F-7F', 'name': 'Bibliothek Rolladen', 'sender': {'id': '00-00-B0-06', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>, 'time_opens': 29, 'time_closes': 28}, {'id': '00-00-00-07', 'eep': 'G5-3F-7F', 'name': 'Küche Rolladen', 'sender': {'id': '00-00-B0-07', 'eep': 'H5-3F-7F'}, 'device_class': <CoverDeviceClass.SHUTTER: 'shutter'>}]}, 'name': ''}, {'id': 2, 'base_id': 'FF-9F-5E-80', 'device_type': 'enocean-usb300', 'serial_path': '192.168.2.7:20109', 'devices': {'climate': [{'id': 'FF-E9-20-9B', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Schlafzimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9B', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-BC-01-01', 'eep': 'A5-10-06'}, 'max_target_temperature': 25, 'min_target_temperature': 17}, {'id': 'FF-E9-20-9C', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Kinderzimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9C', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-AC-9D-01', 'eep': 'A5-10-06'}, 'max_target_temperature': 25, 'min_target_temperature': 17}, {'id': 'FF-E9-20-9D', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Arbeitszimmer Thermostat', 'sender': {'id': 'FF-9F-5E-9D', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-CD-01-81', 'eep': 'A5-10-06'}, 'max_target_temperature': 25, 'min_target_temperature': 17}, {'id': 'FF-E9-20-9E', 'eep': 'A5-10-06', 'temperature_unit': '°C', 'name': 'Bibliothek Thermostat', 'sender': {'id': 'FF-9F-5E-9E', 'eep': 'A5-10-06'}, 'thermostat': {'id': 'FF-DB-A6-81', 'eep': 'A5-10-06'}, 'max_target_temperature': 25, 'min_target_temperature': 17}]}, 'name': ''}]}

2024-07-23 23:27:43.035 WARNING (SyncWorker_8) [eltako] Gateway path 192.168.2.7:20109 is invalid: [Errno 2] could not open port 192.168.2.7:20109: [Errno 2] No such file or directory: '192.168.2.7:20109'
2024-07-23 23:27:43.036 DEBUG (MainThread) [eltako] serial_path: 192.168.2.7:20109, validated with baud rate 57600 is False
2024-07-23 23:27:43.052 DEBUG (MainThread) [eltako] Available gateways to be added: ['EnOcean Gateway - enocean-usb300 (Id: 2, BaseId: FF-9F-5E-80)']
2024-07-23 23:27:43.052 DEBUG (MainThread) [eltako] Available serial paths: ['/dev/serial/by-path/pci-0000:00:04.0-usb-0:2:1.0-port0', '192.168.2.7:20109', '/dev/serial/by-path/pci-0000:00:04.0-usbv2-0:2:1.0-port0']
2024-07-23 23:27:44.943 ERROR (Thread-6) [eltakobus.serial] [Errno 5] I/O error
legnad commented 4 months ago

I've studied the pySerial package code. The rfc2217.py module contains a comment regarding the url format:

# How to identify ports? pySerial might want to support other protocols in the
# future, so lets use an URL scheme.
# for RFC2217 compliant servers we will use this:
#    rfc2217://<host>:<port>[?option[&option...]]

So by using this url signature I can successfully configure by using the following ser2net.yaml with a PioTek FAM-USB 515. However I cannot manage to connect from home assistant eltako integration (2024-07-24 00:21:01.447 ERROR (Thread-92) [enocean.communicators.SerialCommunicator] [Errno 2] could not open port rfc2217://192.168.2.7:20109: [Errno 2] No such file or directory: 'rfc2217://192.168.2.7:20109').

Any recommendation on the ser2net setup to get it to work with pySerial?

ser2net.yaml:

%YAML 1.1
---

define: &banner Connected to port \N(\d)\r\n

default:
      name: local
      value: true
      class: serialdev

default:
      name: mdns
      value: true

default:
      name: mdns-sysattrs
      value: true

connection: &toS0telnet
      accepter: telnet(rfc2217),tcp,20109
      enable: on
      connector: serialdev,/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0P4TMI-if00-port0,local,remctl,banner
      options:
              banner: *banner
              kickolduser: true
              chardelay-min: 0
              chardelay-max: 0
grimmpp commented 4 months ago

Can you try configure it as PioTek FAM-USB 515. This ist actually the same.

https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/gateways#piotek-enocean-multigateway-usblanwifi

legnad commented 4 months ago

I don't understand the exact relevance of your suggestion. The configuration works with device_type: "enocean-usb300" when plugging the device in directly. I just don't manage to get connection via Ser2Net and Serial over TCP/TELNET configuration.

However, setting the device_type string to "PioTek FAM-USB 515" is not possible: grafik

grimmpp commented 4 months ago

behind the device_type is actually more or less a template which preconfigures the gateway. device_type: enocean-usb300 is for wireless gateways pluged in via USB and talking ESP3 protocol device_type: mgw-lan is for gateways translating from wireless to TCP based on ESP3 protocol. You could this one out.

grimmpp commented 4 months ago

Did you find out how to specify the serial_port? https://pyserial.readthedocs.io/en/stable/examples.html

Each serial port becomes available as one TCP/IP server. e.g. /dev/ttyUSB0 is reachable at <host>:7000.

Have you tried: 192.168.2.7:20109

legnad commented 4 months ago

Using bare IP Address and Port doesn't work (as in https://github.com/grimmpp/home-assistant-eltako/issues/121#issuecomment-2246350791).

I think from the pySerial/Eltako-side the configuration would probebly work using

...
  - id: 2
    base_id: FF-9F-5E-80 # PioTek FAM-USB 515 # /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0P4TMI-if00-port0
    device_type: "enocean-usb300"
    serial_path: "tcp://192.168.2.7:20109"
    devices:
...

but I am not sure wether the Ser2Net configuration is correct and was hoping for someone to managed to successfully create this setup stack with home-assistant-eltako. As mentioned before, the Ser2Net works perfectly with ZHA and a Conbee II Zigbee Coordinator connected via Ser2Net.

grimmpp commented 4 months ago

Can you try out:

  - id: 2
    base_id: FF-9F-5E-80 
    device_type: mgw-lan  # esp3 protocol + uses address and port field instead of serial_path
    address: 192.168.2.7
    port: 20109
    devices:

or

  - id: 2
    base_id: FF-9F-5E-80 
    device_type: fam-usb # esp2 protocol
    serial_path: "192.168.2.7:20109"

or

  - id: 2
    base_id: FF-9F-5E-80 
    device_type: enocean-usb300 # esp3 protocol
    serial_path: "192.168.2.7:20109"
legnad commented 4 months ago

grafik

No luck... with the other too. I also tried socket://192.168.2.7:20109 as in accordance with the pySerial docs:

2024-07-29 14:16:55.460 ERROR (Thread-21) [enocean.communicators.SerialCommunicator] [Errno 2] could not open port socket://192.168.2.7:20109: [Errno 2] No such file or directory: 'socket://192.168.2.7:20109'

grimmpp commented 4 months ago

Are you actually sure that the port matches?

legnad commented 4 months ago

Yes, I checked with netstat -l and the RPi is listening on 0.0.0.0:20109

legnad commented 3 months ago

I made a mini Python script to test if bare pySerial (run on a windows machine) could connect and it works:

import serial
import time

success = False
while success == False:
    try:
        with serial.serial_for_url('socket://192.168.2.7:20109', 57600) as s:
            print('Online', s)
        #success = True
        time.sleep(1)
    except:
        print('Offline')
        time.sleep(1)

Output (stdout) when the Ser2Net container on the RPi is offline and is then turned on while looping:

Offline
Offline
Offline
Offline
Online Serial<id=0x209083a5390, open=True>(port='socket://192.168.2.7:20109', baudrate=57600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
Online Serial<id=0x209083f03a0, open=True>(port='socket://192.168.2.7:20109', baudrate=57600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)
Online Serial<id=0x209083a5390, open=True>(port='socket://192.168.2.7:20109', baudrate=57600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)

I don't know how to proceed with further testing. Any idea?

legnad commented 3 months ago

Could the issue be that https://github.com/kipe/enocean/blob/master/enocean/communicators/serialcommunicator.py uses serial.Serial instead of serial.serial_for_url? (https://pyserial.readthedocs.io/en/latest/pyserial_api.html?highlight=url#serial.serial_for_url)

See https://github.com/kipe/enocean/blob/80a253bcea1e3cb99295f53f04c0558190dca5f3/enocean/communicators/serialcommunicator.py#L17

I see when validating the gateway path you use it https://github.com/grimmpp/home-assistant-eltako/blob/f342e8ea45761369b9e99869c36f9d1302aade14/custom_components/eltako/gateway.py#L393

    """Return True if the provided path points to a valid serial port, False otherwise."""
    try:
        serial.serial_for_url(path, baud_rate, timeout=0.1)
        return True
    except serial.SerialException as exception:
        LOGGER.warning("Gateway path %s is invalid: %s", path, str(exception))
        return False

So validating probably works, because I can create the Integration. But the logs show communication failure:

2024-08-06 20:26:49.349 ERROR (Thread-14) [enocean.communicators.SerialCommunicator] [Errno 2] could not open port socket://192.168.2.7:20109: [Errno 2] No such file or directory: 'socket://192.168.2.7:20109'

legnad commented 3 months ago

Well I could achieve a step forward...

So apparently you use a different approach when setting mgw-lan as device type. BUT it is not possible to configure the port option in the HA YAML file in the gateway section, because the config validator rejects the option and says it is invalid. However, I figured that you have set 5100 as the default port in your GatewaySchemaclass right here: https://github.com/grimmpp/home-assistant-eltako/blob/f342e8ea45761369b9e99869c36f9d1302aade14/custom_components/eltako/schema.py#L268

So I've edited my Ser2Net configuration and set 5100 as the port:

default:
      name: local
      value: true
      class: serialdev

default:
      name: mdns
      value: true

default:
      name: mdns-sysattrs
      value: true

connection: &toS0telnet
      accepter: tcp,ipv4,5100
      enable: on
      connector: serialdev,/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0P4TMI-if00-port0,57600N81,nobreak,local
      options:
              banner: *banner
              kickolduser: true
              chardelay-min: 0
              chardelay-max: 0

And it could connect! However, the connection seems not to be working as the connection status changes every ~10 secs: grafik

Logging output:

2024-08-06 21:38:28.783 ERROR (Thread-29) [eltakobus.tcp2serial] [Errno 9] Bad file descriptor
2024-08-06 21:38:28.783 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected False
2024-08-06 21:38:39.785 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected True
2024-08-06 21:38:50.799 ERROR (Thread-29) [eltakobus.tcp2serial] [Errno 9] Bad file descriptor
2024-08-06 21:38:50.799 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected False
2024-08-06 21:39:01.802 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected True
2024-08-06 21:39:05.105 DEBUG (Thread-29) [eltako] [Gateway] [Id: 2] Received message: <Regular4BSMessage from ff db a6 81, data 00 85 60 0f, status = 0x00>
2024-08-06 21:39:06.639 DEBUG (Thread-29) [eltako] [Gateway] [Id: 2] Received message: <Regular4BSMessage from ff e9 20 9e, data 00 85 60 0f, status = 0x30>
2024-08-06 21:39:06.644 DEBUG (SyncWorker_45) [eltako] [climate ff-e9-20-9e] Change state triggered by actuator: ff-e9-20-9e
2024-08-06 21:39:18.213 ERROR (Thread-29) [eltakobus.tcp2serial] [Errno 9] Bad file descriptor
2024-08-06 21:39:18.213 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected False
2024-08-06 21:39:29.216 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected True
2024-08-06 21:39:40.229 ERROR (Thread-29) [eltakobus.tcp2serial] [Errno 9] Bad file descriptor
2024-08-06 21:39:40.230 DEBUG (MainThread) [eltako] [binary_sensor] [Gateway Id 2] connected False
legnad commented 3 months ago

10 second connect-disconnect interval:

113

legnad commented 3 months ago

According to https://github.com/grimmpp/home-assistant-eltako/issues/121#issuecomment-2272017040 and with rerefence to #113 and #124 I have managed to establish a (so far) stable connection using Ser2Net Docker on a Raspberry Pi in conjunction with a PioTek FAM-USB 515.

I'll try out with a FGW14-USB now, as I have USB-Serial-Connection stability issues when connecting the FGW14 to a Synolgoy NAS and forwarding the USB Device to a virtual machine (which is running HAOS).