Skip to content

Commit

Permalink
tests and bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
grimmpp committed Mar 28, 2024
1 parent 5200922 commit b0e1a67
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 13 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ Elatko devices are exemplarily mentioned. You can find [here](https://www.eltako
* A5-38-08 (light and switch)
* H5-3F-7F (cover)
* [Send Message Service](https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/service-send-message/readme.md) Sends any EnOcean Message. Can be used for [automatinos in Home Assistant](https://www.home-assistant.io/getting-started/automation/) so that none-EnOcean and EnOcean deviecs can be combined.
* Not supported EEPs: A5-09-0C (Air Quality), A5-38-08 (Central Command)

[**Gateway**](https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/gateways/readme.md) (See also [how to use gateways](https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/gateway_usage/readme.md) and [multiple gateway support](https://github.com/grimmpp/home-assistant-eltako/tree/main/docs/multiple-gateway-support/readme.md))
* **Eltako FAM14** and Eltako **FGW14-USB** (based on ESP2, rs485 bus and baud rate 57600, uses library [eltako14bus](https://github.com/grimmpp/eltako14bus))
Expand Down
1 change: 1 addition & 0 deletions changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Unit-Tests added and improved for EEP A5-04-01, A5-04-02, A5-10-06, A5-10-12, A5-13-01, and F6-10-00.
* EEP A5-04-03 added for Eltako FFT60 (temperature and humiditry)
* EEP A5-06-01 added for light sensor (currently twilight and daylight are combinded in one illumination sensor/entity)
* Bug fixes in EEPs (in [eltako14bus library](https://github.com/grimmpp/eltako14bus))

## Version 1.4.0 ESP3 Support (USB300)
* Docs about gateway usage added.
Expand Down
2 changes: 1 addition & 1 deletion custom_components/eltako/config_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def get_device_config(config: dict, id: int) -> dict:
return g[CONF_DEVICES]
return None

async def async_get_list_of_gateway_descriptions(hass: HomeAssistant, CONFIG_SCHEMA: dict, get_integration_config=async_integration_yaml_config, filter_out: [str]=[]) -> dict:
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:
config = await async_get_home_assistant_config(hass, CONFIG_SCHEMA, get_integration_config)
return get_list_of_gateway_descriptions(config, filter_out)

Expand Down
9 changes: 5 additions & 4 deletions custom_components/eltako/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ async def async_setup(self):


# Command Section
async def async_service_send_message(self, event) -> None:
async def async_service_send_message(self, event, raise_exception=False) -> None:
"""Send an arbitrary message with the provided eep."""
LOGGER.debug(f"[Service Send Message: {event.service}] Received event data: {event.data}")

Expand Down Expand Up @@ -252,10 +252,11 @@ async def async_service_send_message(self, event) -> None:
msg = eep.encode_message(sender_id[0])
LOGGER.debug(f"[Service Send Message: {event.service}] Generated message: {msg} Serialized: {msg.serialize().hex()}")
# send message
event_id = config_helpers.get_bus_event_type(self.base_id, SIGNAL_SEND_MESSAGE)
dispatcher_send(self.hass, event_id, msg)
except:
self.send_message(msg)
except Exception as e:
LOGGER.error(f"[Service Send Message: {event.service}] Cannot send message.", exc_info=True, stack_info=True)
if raise_exception:
raise e



Expand Down
2 changes: 1 addition & 1 deletion 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.48","enocean==0.60.1", "StrEnum", "esp2-gateway-adapter==0.1"],
"requirements": ["eltako14bus==0.0.49","enocean==0.60.1", "StrEnum", "esp2-gateway-adapter==0.1"],
"version": "1.4.1"
}
28 changes: 28 additions & 0 deletions docs/service-send-message/eep-params.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Paramters for EEPs in Send Message Events
## Not Supported EEPs
* A5-09-0C
* A5-38-08

## Parameters for events:
* A5-04-01: humidity, learn_button, temp_availability, temperature
* A5-04-02: humidity, learn_button, temperature
* A5-04-03: humidity, learn_button, telegram_type, temperature
* A5-06-01: day_light, illumination, twilight
* A5-07-01: learn_button, pir_status, pir_status_on, support_volrage_availability, support_voltage
* A5-08-01: illumination, learn_button, occupancy_button, pir_status, supply_voltage, temperature
* A5-10-06: current_temp, mode, stand_by, target_temp
* A5-10-12: current_temperature, humidity, target_temperature
* A5-12-01: data_type, divisor, learn_button, measurement_channel, meter_reading
* A5-12-02: data_type, divisor, learn_button, measurement_channel, meter_reading
* A5-12-03: data_type, divisor, learn_button, measurement_channel, meter_reading
* A5-13-01: dawn_sensor, day_night, hemisphere, identifier, learn_button, rain_indication, sun_east, sun_south, sun_west, temperature, wind_speed
* D5-00-01: contact, learn_button
* F6-02-01: energy_bow, rocker_first_action, rocker_second_action, second_action
* F6-02-02: energy_bow, rocker_first_action, rocker_second_action, second_action
* F6-10-00: handle_position, movement
* G5-3F-7F: direction, state, time
* H5-3F-7F: command, learn_button, time
* M5-38-08: state

## References:
Implementation of EEPs can be found [eltako14bus library](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py).
2 changes: 1 addition & 1 deletion docs/service-send-message/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ This service is mainly inteded to combine none-EnOcean and EnOcean devices. Serv

Create an [automation](https://www.home-assistant.io/getting-started/automation/) in Home Assistant. Use the upper sections to react on anything you like, dependent on you sensor/sender.

`Add Action` and search for `eltako`. It proposes a service to send messages for every available gateway. In addition you need to enter in the data section what to send. The fields `id` and `eep` must be specified. `id` stands for the sender address. (Keep in mind: bus gateways do not send in wireless network and wireless tranceivers do only have 128 hardcoded addresses to be used.) `eep` is the message format you what to use. Dependent on the eep specific information is put into the messages to be sent. You can either check in the [code](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py) or in the logs what attribute need to be set.
`Add Action` and search for `eltako`. It proposes a service to send messages for every available gateway. In addition you need to enter in the data section what to send. The fields `id` and `eep` must be specified. `id` stands for the sender address. (Keep in mind: bus gateways do not send in wireless network and wireless tranceivers do only have 128 hardcoded addresses to be used.) `eep` is the message format you what to use. Dependent on the eep specific information is put into the messages to be sent. You can either check in the [code](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py) or in this automatically generated [parameter list for EEPs](eep-params.md). In the logs you can see what parameters has been transferred and which will be set as default to 0.

<img src="send_message_logs_screenshot.png" />

Expand Down
5 changes: 5 additions & 0 deletions tests/mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class HassMock():

def __init__(self) -> None:
self.bus = BusMock()
self.loop = asyncio.get_event_loop()

# def async_create_task(self, async_call):
# asyncio.run( async_call )
Expand All @@ -43,6 +44,10 @@ def __init__(self):
def is_active(self):
return self._is_active

class EventMock():
def __init__(self, service:str, data:dict) -> None:
self.service = service
self.data = data
class GatewayMock(EnOceanGateway):

def __init__(self, general_settings:dict=DEFAULT_GENERAL_SETTINGS, dev_id: int=123, base_id:AddressExpression=AddressExpression.parse('FF-AA-80-00')):
Expand Down
12 changes: 6 additions & 6 deletions tests/test_cover_G5_3F_7F.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,15 @@ def test_open_cover(self):
ec.open_cover()
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x04\x01\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x0b\x01\x08\x00\x00\xb1\x06\x00')

def test_close_cover(self):
ec = self.create_cover()

ec.close_cover()
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x04\x02\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x0b\x02\x08\x00\x00\xb1\x06\x00')

def test_stop_cover(self):
ec = self.create_cover()
Expand All @@ -139,7 +139,7 @@ def test_set_cover_position(self):
ec.set_cover_position(position=50)
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x01\x02\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x05\x02\x08\x00\x00\xb1\x06\x00')
self.assertEqual(ec._attr_is_closing, True)
self.assertEqual(ec._attr_is_opening, False)
self.last_sent_command = None
Expand All @@ -148,7 +148,7 @@ def test_set_cover_position(self):
ec.set_cover_position(position=50)
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x01\x01\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x05\x01\x08\x00\x00\xb1\x06\x00')
self.assertEqual(ec._attr_is_closing, False)
self.assertEqual(ec._attr_is_opening, True)
self.last_sent_command = None
Expand All @@ -157,7 +157,7 @@ def test_set_cover_position(self):
ec.set_cover_position(position=0)
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x04\x02\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x0b\x02\x08\x00\x00\xb1\x06\x00')
self.assertEqual(ec._attr_is_closing, True)
self.assertEqual(ec._attr_is_opening, False)
self.last_sent_command = None
Expand All @@ -166,7 +166,7 @@ def test_set_cover_position(self):
ec.set_cover_position(position=100)
self.assertEqual(
self.last_sent_command.body,
b'k\x07\x00\x04\x01\x08\x00\x00\xb1\x06\x00')
b'k\x07\x00\x0b\x01\x08\x00\x00\xb1\x06\x00')
self.assertEqual(ec._attr_is_closing, False)
self.assertEqual(ec._attr_is_opening, True)
self.last_sent_command = None
Expand Down
77 changes: 77 additions & 0 deletions tests/test_send_message_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import unittest
from mocks import *
from unittest import mock
from homeassistant.helpers import dispatcher
import inspect

dispatcher.dispatcher_send = mock.Mock(return_value=None)

class TestSendMessageService(unittest.IsolatedAsyncioTestCase):

def create_gateway(self):
gateway = GatewayMock(dev_id=123)

return gateway

def get_all_eep_names(self):
subclasses = set()
work = [EEP]
while work:
parent = work.pop()
for child in parent.__subclasses__():
if child not in subclasses:
subclasses.add(child)
work.append(child)
return sorted(set([s.__name__.upper().replace('_','-') for s in subclasses if len(s.__name__) == 8 and s.__name__.count('_') == 2]))

NOT_SUPPORTED_EEPS = ['A5-09-0C', 'A5-38-08']

async def test_send_message(self):
g = self.create_gateway()
# Mock send_message
g.send_message = lambda *args: None

for eep_name in self.get_all_eep_names():

if eep_name in self.NOT_SUPPORTED_EEPS:
continue

event = EventMock('service_name', {
'id': 'FF-DD-CC-BB',
'eep': eep_name,
'command': 1,
'identifier': 1
})

await g.async_service_send_message(event, True)


async def test_write_eep_params_to_docs_file(self):
text = '# Paramters for EEPs in Send Message Events'
text += '\n'

text += "## Not Supported EEPs \n"
for eep_name in self.NOT_SUPPORTED_EEPS:
text += f"* {eep_name}\n"
text += '\n'

text += '## Parameters for events: \n'

for eep_name in self.get_all_eep_names():

if eep_name in self.NOT_SUPPORTED_EEPS:
continue

sig = inspect.signature(EEP.find(eep_name).__init__)
eep_init_args = sorted([param.name for param in sig.parameters.values() if param.kind == param.POSITIONAL_OR_KEYWORD and param.name != 'self'])
text += f"* {eep_name}: {', '.join(eep_init_args)}\n"

text += '\n'
text += '## References:\n'
text += 'Implementation of EEPs can be found [eltako14bus library](https://github.com/grimmpp/eltako14bus/blob/master/eltakobus/eep.py).\n'

file='./docs/service-send-message/eep-params.md'
with open(file, 'w') as filetowrite:
filetowrite.write(text)


0 comments on commit b0e1a67

Please sign in to comment.