Skip to content

Commit

Permalink
Merge pull request #104 from grimmpp/feature-branch
Browse files Browse the repository at this point in the history
MGW LAN added
  • Loading branch information
grimmpp authored May 23, 2024
2 parents 519e34a + 0085317 commit f84a66c
Show file tree
Hide file tree
Showing 18 changed files with 65 additions and 41 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Elatko devices are exemplarily mentioned. You can find [here](https://www.eltako
* **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))

* **[PioTek MGW LAN](https://www.piotek.de/FAM-USB-515)** (ESP3 via TCP/LAN, port=5100, uses library [Python EnOcean](https://github.com/kipe/enocean) and [esp2_gateway_adapter](https://github.com/grimmpp/esp2_gateway_adapter))

# Installation and Configuration

Expand Down
4 changes: 4 additions & 0 deletions changes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Changes and Feature List

## Version 1.5 MGW LAN Support
* Added support for [MGW Gateway](https://www.piotek.de/PioTek-MGW-POE) (ESP3 over LAN)

## Version 1.4.4
* Thread sync clean up
* Lazy loading for ESP3 libs to prevent dependency issues

## Version 1.4.3 Compatibility to HA 2024.5
* 🐞 Incompatibility with HA 2024.5 fixed. (Cleaned up event loop synchronization)
Expand Down
6 changes: 2 additions & 4 deletions custom_components/eltako/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
"""Support for Eltako binary sensors."""
from __future__ import annotations
from typing import Literal, final

from eltakobus.util import AddressExpression, b2a, b2s
from eltakobus.util import AddressExpression
from eltakobus.eep import *

from homeassistant.components.binary_sensor import BinarySensorEntity, BinarySensorDeviceClass
from homeassistant import config_entries
from homeassistant.const import CONF_DEVICE_CLASS, STATE_ON, STATE_OFF
from homeassistant.const import CONF_DEVICE_CLASS
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers import entity_registry as er

from .device import *
from .const import *
Expand Down
1 change: 0 additions & 1 deletion custom_components/eltako/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers import entity_registry as er

from .device import *
from . import config_helpers
Expand Down
5 changes: 1 addition & 4 deletions custom_components/eltako/climate.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
"""Support for Eltako Temperature Control sources."""
from __future__ import annotations

from typing import Any

import asyncio
import time

from eltakobus.util import AddressExpression, b2a
from eltakobus.util import AddressExpression
from eltakobus.eep import *
from eltakobus.message import ESP2Message

Expand All @@ -21,7 +19,6 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers import entity_registry as er

from .gateway import EnOceanGateway
from .device import *
Expand Down
24 changes: 19 additions & 5 deletions custom_components/eltako/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

import voluptuous as vol

import ipaddress

from homeassistant import config_entries
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import device_registry as dr
Expand Down Expand Up @@ -74,11 +76,13 @@ async def manual_selection_routine(self, user_input=None, manual_setp:bool=False
if len(g_list) == 0:
errors = {CONF_GATEWAY_DESCRIPTION: ERROR_NO_GATEWAY_CONFIGURATION_AVAILABLE}

# add serial paths from configuration
# add manually added serial paths and ip addresses from configuration
for g_id in g_list_dict.keys():
g_c = config_helpers.find_gateway_config_by_id(config, g_id)
if CONF_SERIAL_PATH in g_c:
serial_paths.append(g_c[CONF_SERIAL_PATH])
if CONF_GATEWAY_ADDRESS in g_c:
serial_paths.append(g_c[CONF_GATEWAY_ADDRESS])

# get all serial paths which are not taken by existing gateways
device_registry = dr.async_get(self.hass)
Expand Down Expand Up @@ -117,11 +121,21 @@ async def validate_eltako_conf(self, user_input) -> bool:
if gdc in gateway_selection:
baud_rate = gateway.BAUD_RATE_DEVICE_TYPE_MAPPING[gdc]
break

# check ip address for esp3 over tcp
if GatewayDeviceType.LAN in gateway_selection:
try:
ip = ipaddress.ip_address(serial_path)
return True
except Exception:
return False
# check serial ports / usb
else:
path_is_valid = await self.hass.async_add_executor_job(
gateway.validate_path, serial_path, baud_rate
)
LOGGER.debug("serial_path: %s, validated with baud rate %d is %s", serial_path, baud_rate, path_is_valid)

path_is_valid = await self.hass.async_add_executor_job(
gateway.validate_path, serial_path, baud_rate
)
LOGGER.debug("serial_path: %s, validated with baud rate %d is %s", serial_path, baud_rate, path_is_valid)
return path_is_valid

def create_eltako_entry(self, user_input):
Expand Down
2 changes: 0 additions & 2 deletions custom_components/eltako/config_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType
from homeassistant.const import CONF_DEVICES, CONF_NAME, CONF_ID
from homeassistant.helpers.entity_registry import EntityRegistry, RegistryEntry
from homeassistant.helpers.entity import Entity

from eltakobus.util import AddressExpression, b2a
from eltakobus.eep import EEP
Expand Down
25 changes: 22 additions & 3 deletions custom_components/eltako/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
CONF_BASE_ID: Final = "base_id"
CONF_DEVICE_TYPE: Final = "device_type"
CONF_SERIAL_PATH: Final = "serial_path"
CONF_GATEWAY_ADDRESS: Final = "address"
CONF_CUSTOM_SERIAL_PATH: Final = "custom_serial_path"
CONF_MAX_TARGET_TEMPERATURE: Final = "max_target_temperature"
CONF_MIN_TARGET_TEMPERATURE: Final = "min_target_temperature"
Expand Down Expand Up @@ -77,6 +78,12 @@ class GatewayDeviceType(str, Enum):
GatewayEltakoFGW14USB = 'fgw14usb'
GatewayEltakoFAMUSB = 'fam-usb' # ESP2 transceiver: https://www.eltako.com/en/product/professional-standard-en/three-phase-energy-meters-and-one-phase-energy-meters/fam-usb/
EnOceanUSB300 = 'enocean-usb300' # not yet supported
EltakoFAM14 = 'fam14'
EltakoFGW14USB = 'fgw14usb'
EltakoFAMUSB = 'fam-usb'
USB300 = 'enocean-usb300'
ESP3 = 'esp3-gateway'
LAN = 'mgw-lan'

@classmethod
def find(cls, value):
Expand All @@ -87,19 +94,31 @@ def find(cls, value):

@classmethod
def is_transceiver(cls, dev_type) -> bool:
return dev_type in [GatewayDeviceType.GatewayEltakoFAMUSB, GatewayDeviceType.EnOceanUSB300]
return dev_type in [GatewayDeviceType.GatewayEltakoFAMUSB, GatewayDeviceType.EnOceanUSB300, GatewayDeviceType.USB300, GatewayDeviceType.ESP3]

@classmethod
def is_bus_gateway(cls, dev_type) -> bool:
return dev_type in [GatewayDeviceType.GatewayEltakoFAM14, GatewayDeviceType.GatewayEltakoFGW14USB]
return dev_type in [GatewayDeviceType.GatewayEltakoFAM14, GatewayDeviceType.GatewayEltakoFGW14USB,
GatewayDeviceType.EltakoFAM14, GatewayDeviceType.EltakoFAMUSB, GatewayDeviceType.EltakoFGW14USB]

@classmethod
def is_esp2_gateway(cls, dev_type) -> bool:
return dev_type in [GatewayDeviceType.GatewayEltakoFAM14, GatewayDeviceType.GatewayEltakoFGW14USB, GatewayDeviceType.GatewayEltakoFAMUSB]
return dev_type in [GatewayDeviceType.GatewayEltakoFAM14, GatewayDeviceType.GatewayEltakoFGW14USB, GatewayDeviceType.GatewayEltakoFAMUSB,
GatewayDeviceType.EltakoFAM14, GatewayDeviceType.EltakoFAMUSB, GatewayDeviceType.EltakoFGW14USB]

@classmethod
def is_lan_gateway(cls, dev_type) -> bool:
return dev_type in [GatewayDeviceType.LAN]

BAUD_RATE_DEVICE_TYPE_MAPPING: dict = {
GatewayDeviceType.GatewayEltakoFAM14: 57600,
GatewayDeviceType.GatewayEltakoFGW14USB: 57600,
GatewayDeviceType.GatewayEltakoFAMUSB: 9600,
GatewayDeviceType.EnOceanUSB300: 57600,
GatewayDeviceType.EltakoFAM14: 57600,
GatewayDeviceType.EltakoFGW14USB: 57600,
GatewayDeviceType.EltakoFAMUSB: 9600,
GatewayDeviceType.USB300: 57600,
GatewayDeviceType.ESP3: 57600,
GatewayDeviceType.LAN: -1,
}
3 changes: 0 additions & 3 deletions custom_components/eltako/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@
from homeassistant.components.cover import CoverEntity, CoverEntityFeature, ATTR_POSITION
from homeassistant.const import CONF_DEVICE_CLASS, Platform, STATE_OPEN, STATE_OPENING, STATE_CLOSED, STATE_CLOSING
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers import entity_registry as er

from .device import *
from . import config_helpers
Expand Down
1 change: 0 additions & 1 deletion custom_components/eltako/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from custom_components.eltako.eltako_integration_init import get_gateway_from_hass, get_device_config_for_gateway

from .device import *
from . import config_helpers
from .gateway import EnOceanGateway
from .const import *
from . import get_gateway_from_hass, get_device_config_for_gateway
Expand Down
16 changes: 8 additions & 8 deletions custom_components/eltako/gateway.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Representation of an Eltako gateway."""
from enum import Enum
import glob

from os.path import basename, normpath
Expand All @@ -9,25 +8,21 @@
import serial
import asyncio

from eltakobus.serial import RS485SerialInterface, RS485SerialInterfaceV2, BusInterface
from eltakobus.message import ESP2Message, RPSMessage, Regular1BSMessage, Regular4BSMessage, EltakoPoll, prettify
from eltakobus.serial import RS485SerialInterfaceV2
from eltakobus.message import ESP2Message, EltakoPoll

from eltakobus.util import AddressExpression
from eltakobus.eep import EEP

from enocean.communicators import SerialCommunicator
from enocean.protocol.packet import RadioPacket, RORG, Packet

from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_connect, dispatcher_send
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.device_registry import DeviceRegistry, DeviceInfo
from homeassistant.helpers.device_registry import DeviceRegistry
from homeassistant.config_entries import ConfigEntry

from .const import *
from . import config_helpers
from esp2_gateway_adapter.esp3_serial_com import ESP3SerialCommunicator


async def async_get_base_ids_of_registered_gateway(device_registry: DeviceRegistry) -> list[str]:
Expand Down Expand Up @@ -132,7 +127,12 @@ def _init_bus(self):

if GatewayDeviceType.is_esp2_gateway(self.dev_type):
self._bus = RS485SerialInterfaceV2(self.serial_path, baud_rate=self.baud_rate, callback=self._callback_receive_message_from_serial_bus)
elif GatewayDeviceType.is_lan_gateway(self.dev_type):
from esp2_gateway_adapter.esp3_tcp_com import TCP2SerialCommunicator
self._bus = TCP2SerialCommunicator(host=self.serial_path, port=5100, callback=self._callback_receive_message_from_serial_bus, esp2_translation_enabled=True)
else:
# lazy import to avoid preloading library
from esp2_gateway_adapter.esp3_serial_com import ESP3SerialCommunicator
self._bus = ESP3SerialCommunicator(filename=self.serial_path, callback=self._callback_receive_message_from_serial_bus, esp2_translation_enabled=True)

self._bus.set_status_changed_handler(self._fire_connection_state_changed_event)
Expand Down
1 change: 0 additions & 1 deletion custom_components/eltako/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from homeassistant.components.light import (
ATTR_BRIGHTNESS,
PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/eltako/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@
"iot_class": "local_push",
"issue_tracker": "https://github.com/grimmpp/home-assistant-eltako/issues",
"loggers": ["eltako"],
"requirements": ["eltako14bus==0.0.52","enocean==0.60.1", "StrEnum", "esp2-gateway-adapter==0.1"],
"version": "1.4.4"
"requirements": ["eltako14bus==0.0.53", "enocean==0.60.1", "StrEnum", "esp2-gateway-adapter==0.2.6"],
"version": "1.5"
}
1 change: 1 addition & 0 deletions custom_components/eltako/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +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.Optional(CONF_GATEWAY_ADDRESS): cv.string,
vol.Optional(CONF_DEVICES): vol.All(vol.Schema({
**BinarySensorSchema.platform_node(),
**LightSchema.platform_node(),
Expand Down
3 changes: 1 addition & 2 deletions custom_components/eltako/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from typing import Any

from eltakobus.util import AddressExpression, b2s
from eltakobus.util import AddressExpression
from eltakobus.eep import *

from homeassistant import config_entries
Expand All @@ -12,7 +12,6 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers import entity_registry as er

from . import config_helpers, get_gateway_from_hass, get_device_config_for_gateway
from .config_helpers import DeviceConf
Expand Down
2 changes: 1 addition & 1 deletion docs/service-send-message/eep-params.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Paramters for EEPs in Send Message Events
(This file was auto-generated by using [eltako14bus library](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py) in [version 0.0.52](https://pypi.org/project/eltako14bus/) from unit-test `TestSendMessageService` in file `./tests/test_send_message_service.py`).
(This file was auto-generated by using [eltako14bus library](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py) in [version 0.0.53](https://pypi.org/project/eltako14bus/) from unit-test `TestSendMessageService` in file `./tests/test_send_message_service.py`).

## Not Supported EEPs
* `A5-09-0C`
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
aiocoap
pyserial-asyncio
eltako14bus==0.0.52
eltako14bus==0.0.53
enocean==0.60.1
homeassistant
termcolor
StrEnum
esp2-gateway-adapter==0.1
esp2-gateway-adapter==0.2.6
2 changes: 1 addition & 1 deletion tests/test_gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class TestGateway(TestCase):
def test_gateway_types(self):
for t in GatewayDeviceType:

if t in [GatewayDeviceType.EnOceanUSB300, GatewayDeviceType.GatewayEltakoFAMUSB]:
if t in [GatewayDeviceType.GatewayEltakoFAMUSB, GatewayDeviceType.EnOceanUSB300, GatewayDeviceType.USB300, GatewayDeviceType.ESP3]:
self.assertTrue(GatewayDeviceType.is_transceiver(t))
else:
self.assertFalse(GatewayDeviceType.is_transceiver(t))
Expand Down

0 comments on commit f84a66c

Please sign in to comment.