diff --git a/README.md b/README.md index b016d19a..fb6ba563 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ Elatko devices are exemplarily mentioned. You can find [here](https://www.eltako * **Eltako FAM14** and Eltako **FGW14-USB** (based on ESP2, rs485 bus and baud rate 57600, uses library [eltako14bus](https://github.com/grimmpp/eltako14bus)) * **Eltako FAM-USB** (based on ESP2, baud rate 9600, uses library [eltako14bus](https://github.com/grimmpp/eltako14bus)) * **EnOcean USB300** (based on ESP3 but only ESP2 feature set supported, baud rate 57600, uses library [Python EnOcean](https://github.com/kipe/enocean) and [esp2_gateway_adapter](https://github.com/grimmpp/esp2_gateway_adapter)) + * **[PioTek FAM-USB 515](https://www.piotek.de/FAM-USB-515)** (based on ESP3 but only ESP2 feature set supported, baud rate 57600, uses library [Python EnOcean](https://github.com/kipe/enocean) and [esp2_gateway_adapter](https://github.com/grimmpp/esp2_gateway_adapter)) # Installation and Configuration @@ -88,30 +89,22 @@ While this is not integrated into home assistant's repositories. You need to ins *Alternative 2:* Copying directory ``eltako``** from this repository into your home assistant's ``/config/custom_components`` directory. For easy installation just clone this repository ``git clone https://github.com/grimmpp/home-assistant-eltako.git`` and execute the installation script of this repo ``./install_custom_component_eltako.sh``. -2. Before you add the integration you have to add at least one dummy entry in the "configuration.yaml". It must have at least 1 dummy device. Example: +2. Before you add the integration you have to provide a list of gateways and devices you want to use. Here is a minimum example you need to put into ``/config/configuration.yaml`` to start with. The configuration can be change and adapt at any point in time. ``` eltako: gateway: - id: 1 base_id: FF-AA-80-00 - device_type: fgw14usb # Supported gateways: gam14, fgw14usb - devices: - light: - - id: 00-00-00-01 - eep: M5-38-08 - name: FSR14_4x - 1 - sender: - id: 00-00-B0-01 - eep: A5-38-08 + device_type: fgw14usb ``` -3. To **enable this component**, go to your integrations, press the "add" button and select "Eltako". In the presented sheet just select the detected USB gateway. Manual paths can be added in the gateway configuration section under serial_path and will be displayed additionally in the installation sheet. +3. To **enable this component**, go to your integrations, press the "add" button and select "Eltako". In the presented sheet just select the detected USB gateway. 4. **Update Home Assistant configuration** ``/config/configuration.yaml`` and add all devices and sensors you want to integrate. See [How to update Home Assistant Configuration](https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/update_home_assistant_configuration.md) to see how the configuration should look like. -There is also a scipt which can detect devices and sensors and creates a prepared configuration because in big setups it can be a little effort doing that manually. For more details have a look into [Device and Sensor Discovery for Home Assistant Configuration](https://github.com/grimmpp/home-assistant-eltako/tree/main/eltakodevice_discovery/) +In order to automatically generate the configuration and managing your devices you can use [Enocean Device Manager (eo_man)](https://github.com/grimmpp/enocean-device-manager). > [!IMPORTANT] -> Devices that are later removed from the configuration are not deleted in HA. Although it is possible to delete the entity, it is currently not possible to delete the device via a button. The easiest and quickest way to clean up is to delete the Eltako HUB and create a new one. Don't worry, the automations, scenes, scripts, dashboard settings and historical data will not be lost. These are linked to the device ID and are reassigned after the Eltako HUB has been created. +> Devices that are later removed from the configuration are not deleted in HA. Although it is possible to delete the entity, it is currently not possible to delete the device via a button. The easiest and quickest way to clean up is to delete the Eltako HUB and create a new one. Don't worry, the automations, scenes, scripts, dashboard settings and historical data will not be lost. These are linked to the device ID and are reassigned after the Eltako HUB has been recreated. > > image diff --git a/changes.md b/changes.md index 3744fe14..1eee1a32 100644 --- a/changes.md +++ b/changes.md @@ -1,5 +1,8 @@ # Changes and Feature List +## Version 1.4.4 +* Configuration Management cleaned up + ## Version 1.4.3 Compatibility to HA 2024.5 * 🐞 Incompatibility with HA 2024.5 fixed. (Cleaned up event loop synchronization) diff --git a/custom_components/eltako/config_helpers.py b/custom_components/eltako/config_helpers.py index 6abad980..6493a1c8 100644 --- a/custom_components/eltako/config_helpers.py +++ b/custom_components/eltako/config_helpers.py @@ -120,7 +120,10 @@ def get_device_config(config: dict, id: int) -> dict: gateways = config[CONF_GATEWAY] for g in gateways: if g[CONF_ID] == id: - return g[CONF_DEVICES] + if CONF_DEVICES in g: + return g[CONF_DEVICES] + else: + return {} return None async def async_get_list_of_gateway_descriptions(hass: HomeAssistant, CONFIG_SCHEMA: dict, get_integration_config=async_integration_yaml_config, filter_out: list[str]=[]) -> dict: @@ -150,7 +153,7 @@ def config_check_gateway(config: dict) -> bool: g_ids.append(g[CONF_ID]) if len(g_ids) == 0: - return False + return True return True diff --git a/custom_components/eltako/eltako_integration_init.py b/custom_components/eltako/eltako_integration_init.py index 01fe35e5..a7d53553 100644 --- a/custom_components/eltako/eltako_integration_init.py +++ b/custom_components/eltako/eltako_integration_init.py @@ -74,7 +74,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b # Check domain if config_entry.domain != DOMAIN: - raise Exception(f"[{LOG_PREFIX}] Ooops, received configuration entry of wrong domain '%s' (expected: '')!", config_entry.domain, DOMAIN) + LOGGER.warn(f"[{LOG_PREFIX}] Ooops, received configuration entry of wrong domain '%s' (expected: '')!", config_entry.domain, DOMAIN) + return # Read the config @@ -98,20 +99,24 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b # Initialise the gateway # get base_id from user input if CONF_GATEWAY_DESCRIPTION not in config_entry.data.keys(): - raise Exception("[{LOG_PREFIX}] Ooops, device information for gateway is not available. Try to delete and recreate the gateway.") + LOGGER.warn("[{LOG_PREFIX}] Ooops, device information for gateway is not available. Try to delete and recreate the gateway.") + return gateway_description = config_entry.data[CONF_GATEWAY_DESCRIPTION] # from user input if not ('(' in gateway_description and ')' in gateway_description): - raise Exception("[{LOG_PREFIX}] Ooops, no base id of gateway available. Try to delete and recreate the gateway.") + LOGGER.warn("[{LOG_PREFIX}] Ooops, no base id of gateway available. Try to delete and recreate the gateway.") + return gateway_id = config_helpers.get_id_from_name(gateway_description) # get home assistant configuration section matching base_id gateway_config = await config_helpers.async_find_gateway_config_by_id(gateway_id, hass, CONFIG_SCHEMA) if not gateway_config: - raise Exception(f"[{LOG_PREFIX}] Ooops, no gateway configuration found in '/homeassistant/configuration.yaml'.") + LOGGER.warn(f"[{LOG_PREFIX}] Ooops, no gateway configuration found in '/homeassistant/configuration.yaml'.") + return # get serial path info if CONF_SERIAL_PATH not in config_entry.data.keys(): - raise Exception("[{LOG_PREFIX}] Ooops, no information about serial path available for gateway.") + LOGGER.warn("[{LOG_PREFIX}] Ooops, no information about serial path available for gateway.") + return gateway_serial_path = config_entry.data[CONF_SERIAL_PATH] # only transceiver can send teach-in telegrams diff --git a/custom_components/eltako/gateway.py b/custom_components/eltako/gateway.py index 7dfd08dc..db2a0d98 100644 --- a/custom_components/eltako/gateway.py +++ b/custom_components/eltako/gateway.py @@ -4,7 +4,7 @@ from os.path import basename, normpath import pytz -from datetime import datetime +from datetime import datetime, UTC import serial import asyncio @@ -93,9 +93,9 @@ def set_connection_state_changed_handler(self, handler): def _fire_connection_state_changed_event(self, status): if self._connection_state_handler: - asyncio.ensure_future( + asyncio.run_coroutine_threadsafe( self._connection_state_handler(status), - loop= self._loop + loop = self._loop ) @@ -105,9 +105,9 @@ def set_last_message_received_handler(self, handler): def _fire_last_message_received_event(self): if self._last_message_received_handler: - asyncio.ensure_future( - self._last_message_received_handler( datetime.utcnow().replace(tzinfo=pytz.utc) ), - loop= self._loop + asyncio.run_coroutine_threadsafe( + self._last_message_received_handler( datetime.now(UTC).replace(tzinfo=pytz.UTC) ), + loop = self._loop ) @@ -118,9 +118,9 @@ def set_received_message_count_handler(self, handler): def _fire_received_message_count_event(self): self._received_message_count += 1 if self._received_message_count_handler: - asyncio.ensure_future( + asyncio.run_coroutine_threadsafe( self._received_message_count_handler( self._received_message_count ), - loop= self._loop + loop = self._loop ) def process_messages(self, data=None): @@ -293,7 +293,11 @@ def _callback_send_message_to_serial_bus(self, msg): LOGGER.debug("[Gateway] [Id: %d] Send message: %s - Serialized: %s", self.dev_id, msg, msg.serialize().hex()) # put message on serial bus - asyncio.ensure_future(self._bus.send(msg), loop=self._loop) + # asyncio.ensure_future(self._bus.send(msg), loop=self._loop) + asyncio.run_coroutine_threadsafe( + self._bus.send(msg), + loop = self._loop + ) else: LOGGER.warn("[Gateway] [Id: %d] Serial port %s is not available!!! message (%s) was not sent.", self.dev_id, self.serial_path, msg) diff --git a/custom_components/eltako/schema.py b/custom_components/eltako/schema.py index 71665004..9de19698 100644 --- a/custom_components/eltako/schema.py +++ b/custom_components/eltako/schema.py @@ -263,7 +263,7 @@ class GatewaySchema(EltakoPlatformSchema): vol.Required(CONF_BASE_ID): cv.matches_regex(CONF_ID_REGEX), vol.Optional(CONF_NAME, default=""): cv.string, vol.Optional(CONF_SERIAL_PATH): cv.string, - vol.Required(CONF_DEVICES): vol.All(vol.Schema({ + vol.Optional(CONF_DEVICES): vol.All(vol.Schema({ **BinarySensorSchema.platform_node(), **LightSchema.platform_node(), **SwitchSchema.platform_node(),