Skip to content

Commit

Permalink
Merge pull request #101 from grimmpp/feature-branch
Browse files Browse the repository at this point in the history
Feature branch
  • Loading branch information
grimmpp authored May 14, 2024
2 parents 9d15ade + 4328585 commit 70d7e3c
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 30 deletions.
19 changes: 6 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
>
> <img width="846" alt="image" src="https://github.com/grimmpp/home-assistant-eltako/assets/46369917/96c44c86-2407-4c80-85f1-4668975d3148">
Expand Down
3 changes: 3 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
7 changes: 5 additions & 2 deletions custom_components/eltako/config_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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

Expand Down
15 changes: 10 additions & 5 deletions custom_components/eltako/eltako_integration_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
22 changes: 13 additions & 9 deletions custom_components/eltako/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
)


Expand All @@ -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
)


Expand All @@ -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):
Expand Down Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion custom_components/eltako/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down

0 comments on commit 70d7e3c

Please sign in to comment.