From 6a8378bec02a84e0730d2119a53e0599a9d1d533 Mon Sep 17 00:00:00 2001 From: Ziv <16467659+ziv1234@users.noreply.github.com> Date: Tue, 11 Aug 2020 19:33:16 +0300 Subject: [PATCH] Add Dynalite service to request the channel level (#38735) * added service to request the channel level * cleanup * Update homeassistant/components/dynalite/__init__.py Co-authored-by: Martin Hjelmare * Update homeassistant/components/dynalite/__init__.py Co-authored-by: Martin Hjelmare * Update services.yaml Co-authored-by: Martin Hjelmare --- homeassistant/components/dynalite/__init__.py | 47 ++++++++++----- homeassistant/components/dynalite/const.py | 3 + .../components/dynalite/services.yaml | 13 +++++ tests/components/dynalite/test_init.py | 58 +++++++++++++++++-- 4 files changed, 99 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/dynalite/__init__.py b/homeassistant/components/dynalite/__init__.py index f04869d7160..dd485af0441 100644 --- a/homeassistant/components/dynalite/__init__.py +++ b/homeassistant/components/dynalite/__init__.py @@ -1,7 +1,7 @@ """Support for the Dynalite networks.""" import asyncio -from typing import Any, Dict, List, Union +from typing import Any, Dict, Union import voluptuous as vol @@ -49,6 +49,8 @@ from .const import ( DOMAIN, ENTITY_PLATFORMS, LOGGER, + SERVICE_REQUEST_AREA_PRESET, + SERVICE_REQUEST_CHANNEL_LEVEL, ) @@ -201,27 +203,27 @@ async def async_setup(hass: HomeAssistant, config: Dict[str, Any]) -> bool: ) ) - def get_bridges(host: str) -> List[DynaliteBridge]: - result = [] - for entry_id in hass.data[DOMAIN]: - cur_bridge = hass.data[DOMAIN][entry_id] + async def dynalite_service(service_call: ServiceCall): + data = service_call.data + host = data.get(ATTR_HOST, "") + bridges = [] + for cur_bridge in hass.data[DOMAIN].values(): if not host or cur_bridge.host == host: - result.append(cur_bridge) - return result - - async def request_area_preset_service(service_call: ServiceCall): - host = service_call.data.get(ATTR_HOST, "") - bridges = get_bridges(host) + bridges.append(cur_bridge) LOGGER.debug("Selected bridged for service call: %s", bridges) - area = service_call.data[ATTR_AREA] - channel = service_call.data.get(ATTR_CHANNEL) + if service_call.service == SERVICE_REQUEST_AREA_PRESET: + bridge_attr = "request_area_preset" + elif service_call.service == SERVICE_REQUEST_CHANNEL_LEVEL: + bridge_attr = "request_channel_level" for bridge in bridges: - bridge.dynalite_devices.request_area_preset(area, channel) + getattr(bridge.dynalite_devices, bridge_attr)( + data[ATTR_AREA], data.get(ATTR_CHANNEL) + ) hass.services.async_register( DOMAIN, - "request_area_preset", - request_area_preset_service, + SERVICE_REQUEST_AREA_PRESET, + dynalite_service, vol.Schema( { vol.Optional(ATTR_HOST): cv.string, @@ -231,6 +233,19 @@ async def async_setup(hass: HomeAssistant, config: Dict[str, Any]) -> bool: ), ) + hass.services.async_register( + DOMAIN, + SERVICE_REQUEST_CHANNEL_LEVEL, + dynalite_service, + vol.Schema( + { + vol.Optional(ATTR_HOST): cv.string, + vol.Required(ATTR_AREA): int, + vol.Required(ATTR_CHANNEL): int, + } + ), + ) + return True diff --git a/homeassistant/components/dynalite/const.py b/homeassistant/components/dynalite/const.py index be8d94b6e46..cfe48bdc475 100644 --- a/homeassistant/components/dynalite/const.py +++ b/homeassistant/components/dynalite/const.py @@ -55,3 +55,6 @@ ATTR_CHANNEL = "channel" ATTR_HOST = "host" ATTR_PACKET = "packet" ATTR_PRESET = "preset" + +SERVICE_REQUEST_AREA_PRESET = "request_area_preset" +SERVICE_REQUEST_CHANNEL_LEVEL = "request_channel_level" diff --git a/homeassistant/components/dynalite/services.yaml b/homeassistant/components/dynalite/services.yaml index ccaa06ed19a..afdb01bf351 100644 --- a/homeassistant/components/dynalite/services.yaml +++ b/homeassistant/components/dynalite/services.yaml @@ -11,3 +11,16 @@ request_area_preset: description: "Channel to request the preset to be reported from. Default is channel 1" example: 1 +request_channel_level: + description: "Requests Dynalite to report the level of a specific channel." + fields: + host: + description: "Host gateway IP to send to or all configured gateways if not specified." + example: "192.168.0.101" + area: + description: "Area for the requested channel" + example: 2 + channel: + description: "Channel to request the level for." + example: 1 + diff --git a/tests/components/dynalite/test_init.py b/tests/components/dynalite/test_init.py index 6d2fd66f1a2..e36e6aeba2a 100644 --- a/tests/components/dynalite/test_init.py +++ b/tests/components/dynalite/test_init.py @@ -1,6 +1,9 @@ """Test Dynalite __init__.""" +import pytest +from voluptuous import MultipleInvalid + import homeassistant.components.dynalite.const as dynalite from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_ROOM from homeassistant.setup import async_setup_component @@ -93,12 +96,8 @@ async def test_service_request_area_preset(hass): { dynalite.DOMAIN: { dynalite.CONF_BRIDGES: [ - { - CONF_HOST: "1.2.3.4", - CONF_PORT: 1234, - dynalite.CONF_AREA: {"7": {CONF_NAME: "test"}}, - }, - {CONF_HOST: "5.6.7.8", CONF_PORT: 5678}, + {CONF_HOST: "1.2.3.4"}, + {CONF_HOST: "5.6.7.8"}, ] } }, @@ -144,6 +143,53 @@ async def test_service_request_area_preset(hass): mock_req_area_pres.assert_called_once_with(7, 1) +async def test_service_request_channel_level(hass): + """Test requesting the level of a channel via service call.""" + with patch( + "homeassistant.components.dynalite.bridge.DynaliteDevices.async_setup", + return_value=True, + ), patch( + "dynalite_devices_lib.dynalite.Dynalite.request_channel_level", + return_value=True, + ) as mock_req_chan_lvl: + assert await async_setup_component( + hass, + dynalite.DOMAIN, + { + dynalite.DOMAIN: { + dynalite.CONF_BRIDGES: [ + { + CONF_HOST: "1.2.3.4", + dynalite.CONF_AREA: {"7": {CONF_NAME: "test"}}, + }, + {CONF_HOST: "5.6.7.8"}, + ] + } + }, + ) + await hass.async_block_till_done() + assert len(hass.config_entries.async_entries(dynalite.DOMAIN)) == 2 + await hass.services.async_call( + dynalite.DOMAIN, + "request_channel_level", + {"host": "1.2.3.4", "area": 2, "channel": 3}, + ) + await hass.async_block_till_done() + mock_req_chan_lvl.assert_called_once_with(2, 3) + mock_req_chan_lvl.reset_mock() + with pytest.raises(MultipleInvalid): + await hass.services.async_call( + dynalite.DOMAIN, "request_channel_level", {"area": 3}, + ) + await hass.async_block_till_done() + mock_req_chan_lvl.assert_not_called() + await hass.services.async_call( + dynalite.DOMAIN, "request_channel_level", {"area": 4, "channel": 5}, + ) + await hass.async_block_till_done() + assert mock_req_chan_lvl.mock_calls == [call(4, 5), call(4, 5)] + + async def test_async_setup_bad_config1(hass): """Test a successful with bad config on templates.""" with patch(