Refactor home --> hap for Homematic IP Cloud (#27368)

* Refactor home to hap for Homematic IP Cloud

* Add some tests

* Rename ha_entity --> ha_state

* use asynctest.Mock
This commit is contained in:
SukramJ 2019-10-11 16:36:46 +02:00 committed by Martin Hjelmare
parent 0c8e208fd8
commit 8bbf261302
17 changed files with 872 additions and 289 deletions

View File

@ -2,7 +2,6 @@
import logging import logging
from homematicip.aio.group import AsyncSecurityZoneGroup from homematicip.aio.group import AsyncSecurityZoneGroup
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import WindowState from homematicip.base.enums import WindowState
from homeassistant.components.alarm_control_panel import AlarmControlPanel from homeassistant.components.alarm_control_panel import AlarmControlPanel
@ -16,6 +15,7 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -31,15 +31,15 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP alrm control panel from a config entry.""" """Set up the HomematicIP alrm control panel from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
security_zones = [] security_zones = []
for group in home.groups: for group in hap.home.groups:
if isinstance(group, AsyncSecurityZoneGroup): if isinstance(group, AsyncSecurityZoneGroup):
security_zones.append(group) security_zones.append(group)
if security_zones: if security_zones:
devices.append(HomematicipAlarmControlPanel(home, security_zones)) devices.append(HomematicipAlarmControlPanel(hap, security_zones))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -48,9 +48,9 @@ async def async_setup_entry(
class HomematicipAlarmControlPanel(AlarmControlPanel): class HomematicipAlarmControlPanel(AlarmControlPanel):
"""Representation of an alarm control panel.""" """Representation of an alarm control panel."""
def __init__(self, home: AsyncHome, security_zones) -> None: def __init__(self, hap: HomematicipHAP, security_zones) -> None:
"""Initialize the alarm control panel.""" """Initialize the alarm control panel."""
self._home = home self._home = hap.home
self.alarm_state = STATE_ALARM_DISARMED self.alarm_state = STATE_ALARM_DISARMED
for security_zone in security_zones: for security_zone in security_zones:

View File

@ -20,7 +20,6 @@ from homematicip.aio.device import (
AsyncWeatherSensorPro, AsyncWeatherSensorPro,
) )
from homematicip.aio.group import AsyncSecurityGroup, AsyncSecurityZoneGroup from homematicip.aio.group import AsyncSecurityGroup, AsyncSecurityZoneGroup
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import SmokeDetectorAlarmType, WindowState from homematicip.base.enums import SmokeDetectorAlarmType, WindowState
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
@ -41,6 +40,7 @@ from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .device import ATTR_GROUP_MEMBER_UNREACHABLE from .device import ATTR_GROUP_MEMBER_UNREACHABLE
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -85,18 +85,18 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP Cloud binary sensor from a config entry.""" """Set up the HomematicIP Cloud binary sensor from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.devices: for device in hap.home.devices:
if isinstance(device, AsyncAccelerationSensor): if isinstance(device, AsyncAccelerationSensor):
devices.append(HomematicipAccelerationSensor(home, device)) devices.append(HomematicipAccelerationSensor(hap, device))
if isinstance(device, (AsyncContactInterface, AsyncFullFlushContactInterface)): if isinstance(device, (AsyncContactInterface, AsyncFullFlushContactInterface)):
devices.append(HomematicipContactInterface(home, device)) devices.append(HomematicipContactInterface(hap, device))
if isinstance( if isinstance(
device, device,
(AsyncShutterContact, AsyncShutterContactMagnetic, AsyncRotaryHandleSensor), (AsyncShutterContact, AsyncShutterContactMagnetic, AsyncRotaryHandleSensor),
): ):
devices.append(HomematicipShutterContact(home, device)) devices.append(HomematicipShutterContact(hap, device))
if isinstance( if isinstance(
device, device,
( (
@ -105,28 +105,28 @@ async def async_setup_entry(
AsyncMotionDetectorPushButton, AsyncMotionDetectorPushButton,
), ),
): ):
devices.append(HomematicipMotionDetector(home, device)) devices.append(HomematicipMotionDetector(hap, device))
if isinstance(device, AsyncPresenceDetectorIndoor): if isinstance(device, AsyncPresenceDetectorIndoor):
devices.append(HomematicipPresenceDetector(home, device)) devices.append(HomematicipPresenceDetector(hap, device))
if isinstance(device, AsyncSmokeDetector): if isinstance(device, AsyncSmokeDetector):
devices.append(HomematicipSmokeDetector(home, device)) devices.append(HomematicipSmokeDetector(hap, device))
if isinstance(device, AsyncWaterSensor): if isinstance(device, AsyncWaterSensor):
devices.append(HomematicipWaterDetector(home, device)) devices.append(HomematicipWaterDetector(hap, device))
if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)): if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)):
devices.append(HomematicipRainSensor(home, device)) devices.append(HomematicipRainSensor(hap, device))
if isinstance( if isinstance(
device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro) device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro)
): ):
devices.append(HomematicipStormSensor(home, device)) devices.append(HomematicipStormSensor(hap, device))
devices.append(HomematicipSunshineSensor(home, device)) devices.append(HomematicipSunshineSensor(hap, device))
if isinstance(device, AsyncDevice) and device.lowBat is not None: if isinstance(device, AsyncDevice) and device.lowBat is not None:
devices.append(HomematicipBatterySensor(home, device)) devices.append(HomematicipBatterySensor(hap, device))
for group in home.groups: for group in hap.home.groups:
if isinstance(group, AsyncSecurityGroup): if isinstance(group, AsyncSecurityGroup):
devices.append(HomematicipSecuritySensorGroup(home, group)) devices.append(HomematicipSecuritySensorGroup(hap, group))
elif isinstance(group, AsyncSecurityZoneGroup): elif isinstance(group, AsyncSecurityZoneGroup):
devices.append(HomematicipSecurityZoneSensorGroup(home, group)) devices.append(HomematicipSecurityZoneSensorGroup(hap, group))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -249,9 +249,9 @@ class HomematicipWaterDetector(HomematicipGenericDevice, BinarySensorDevice):
class HomematicipStormSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipStormSensor(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud storm sensor.""" """Representation of a HomematicIP Cloud storm sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize storm sensor.""" """Initialize storm sensor."""
super().__init__(home, device, "Storm") super().__init__(hap, device, "Storm")
@property @property
def icon(self) -> str: def icon(self) -> str:
@ -267,9 +267,9 @@ class HomematicipStormSensor(HomematicipGenericDevice, BinarySensorDevice):
class HomematicipRainSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipRainSensor(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud rain sensor.""" """Representation of a HomematicIP Cloud rain sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize rain sensor.""" """Initialize rain sensor."""
super().__init__(home, device, "Raining") super().__init__(hap, device, "Raining")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -285,9 +285,9 @@ class HomematicipRainSensor(HomematicipGenericDevice, BinarySensorDevice):
class HomematicipSunshineSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipSunshineSensor(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud sunshine sensor.""" """Representation of a HomematicIP Cloud sunshine sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize sunshine sensor.""" """Initialize sunshine sensor."""
super().__init__(home, device, "Sunshine") super().__init__(hap, device, "Sunshine")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -314,9 +314,9 @@ class HomematicipSunshineSensor(HomematicipGenericDevice, BinarySensorDevice):
class HomematicipBatterySensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipBatterySensor(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud low battery sensor.""" """Representation of a HomematicIP Cloud low battery sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize battery sensor.""" """Initialize battery sensor."""
super().__init__(home, device, "Battery") super().__init__(hap, device, "Battery")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -332,10 +332,10 @@ class HomematicipBatterySensor(HomematicipGenericDevice, BinarySensorDevice):
class HomematicipSecurityZoneSensorGroup(HomematicipGenericDevice, BinarySensorDevice): class HomematicipSecurityZoneSensorGroup(HomematicipGenericDevice, BinarySensorDevice):
"""Representation of a HomematicIP Cloud security zone group.""" """Representation of a HomematicIP Cloud security zone group."""
def __init__(self, home: AsyncHome, device, post: str = "SecurityZone") -> None: def __init__(self, hap: HomematicipHAP, device, post: str = "SecurityZone") -> None:
"""Initialize security zone group.""" """Initialize security zone group."""
device.modelType = f"HmIP-{post}" device.modelType = f"HmIP-{post}"
super().__init__(home, device, post) super().__init__(hap, device, post)
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -389,9 +389,9 @@ class HomematicipSecuritySensorGroup(
): ):
"""Representation of a HomematicIP security group.""" """Representation of a HomematicIP security group."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize security group.""" """Initialize security group."""
super().__init__(home, device, "Sensors") super().__init__(hap, device, "Sensors")
@property @property
def device_state_attributes(self): def device_state_attributes(self):

View File

@ -4,7 +4,6 @@ from typing import Awaitable
from homematicip.aio.device import AsyncHeatingThermostat, AsyncHeatingThermostatCompact from homematicip.aio.device import AsyncHeatingThermostat, AsyncHeatingThermostatCompact
from homematicip.aio.group import AsyncHeatingGroup from homematicip.aio.group import AsyncHeatingGroup
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import AbsenceType from homematicip.base.enums import AbsenceType
from homematicip.functionalHomes import IndoorClimateHome from homematicip.functionalHomes import IndoorClimateHome
@ -24,6 +23,7 @@ from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -41,11 +41,11 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP climate from a config entry.""" """Set up the HomematicIP climate from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.groups: for device in hap.home.groups:
if isinstance(device, AsyncHeatingGroup): if isinstance(device, AsyncHeatingGroup):
devices.append(HomematicipHeatingGroup(home, device)) devices.append(HomematicipHeatingGroup(hap, device))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -54,13 +54,13 @@ async def async_setup_entry(
class HomematicipHeatingGroup(HomematicipGenericDevice, ClimateDevice): class HomematicipHeatingGroup(HomematicipGenericDevice, ClimateDevice):
"""Representation of a HomematicIP heating group.""" """Representation of a HomematicIP heating group."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize heating group.""" """Initialize heating group."""
device.modelType = "Group-Heating" device.modelType = "Group-Heating"
self._simple_heating = None self._simple_heating = None
if device.actualTemperature is None: if device.actualTemperature is None:
self._simple_heating = _get_first_heating_thermostat(device) self._simple_heating = _get_first_heating_thermostat(device)
super().__init__(home, device) super().__init__(hap, device)
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> str:

View File

@ -31,13 +31,13 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP cover from a config entry.""" """Set up the HomematicIP cover from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.devices: for device in hap.home.devices:
if isinstance(device, AsyncFullFlushBlind): if isinstance(device, AsyncFullFlushBlind):
devices.append(HomematicipCoverSlats(home, device)) devices.append(HomematicipCoverSlats(hap, device))
elif isinstance(device, AsyncFullFlushShutter): elif isinstance(device, AsyncFullFlushShutter):
devices.append(HomematicipCoverShutter(home, device)) devices.append(HomematicipCoverShutter(hap, device))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)

View File

@ -4,17 +4,17 @@ from typing import Optional
from homematicip.aio.device import AsyncDevice from homematicip.aio.device import AsyncDevice
from homematicip.aio.group import AsyncGroup from homematicip.aio.group import AsyncGroup
from homematicip.aio.home import AsyncHome
from homeassistant.components import homematicip_cloud from homeassistant.components import homematicip_cloud
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.helpers import device_registry as dr, entity_registry as er
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_MODEL_TYPE = "model_type" ATTR_MODEL_TYPE = "model_type"
ATTR_GROUP_ID = "group_id"
ATTR_ID = "id" ATTR_ID = "id"
ATTR_IS_GROUP = "is_group" ATTR_IS_GROUP = "is_group"
# RSSI HAP -> Device # RSSI HAP -> Device
@ -46,15 +46,16 @@ DEVICE_ATTRIBUTES = {
"id": ATTR_ID, "id": ATTR_ID,
} }
GROUP_ATTRIBUTES = {"modelType": ATTR_MODEL_TYPE, "id": ATTR_GROUP_ID} GROUP_ATTRIBUTES = {"modelType": ATTR_MODEL_TYPE}
class HomematicipGenericDevice(Entity): class HomematicipGenericDevice(Entity):
"""Representation of an HomematicIP generic device.""" """Representation of an HomematicIP generic device."""
def __init__(self, home: AsyncHome, device, post: Optional[str] = None) -> None: def __init__(self, hap: HomematicipHAP, device, post: Optional[str] = None) -> None:
"""Initialize the generic device.""" """Initialize the generic device."""
self._home = home self._hap = hap
self._home = hap.home
self._device = device self._device = device
self.post = post self.post = post
# Marker showing that the HmIP device hase been removed. # Marker showing that the HmIP device hase been removed.
@ -81,6 +82,7 @@ class HomematicipGenericDevice(Entity):
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""Register callbacks.""" """Register callbacks."""
self._hap.hmip_device_by_entity_id[self.entity_id] = self._device
self._device.on_update(self._async_device_changed) self._device.on_update(self._async_device_changed)
self._device.on_remove(self._async_device_removed) self._device.on_remove(self._async_device_removed)
@ -104,6 +106,7 @@ class HomematicipGenericDevice(Entity):
# Only go further if the device/entity should be removed from registries # Only go further if the device/entity should be removed from registries
# due to a removal of the HmIP device. # due to a removal of the HmIP device.
if self.hmip_device_removed: if self.hmip_device_removed:
del self._hap.hmip_device_by_entity_id[self.entity_id]
await self.async_remove_from_registries() await self.async_remove_from_registries()
async def async_remove_from_registries(self) -> None: async def async_remove_from_registries(self) -> None:

View File

@ -79,6 +79,7 @@ class HomematicipHAP:
self._retry_task = None self._retry_task = None
self._tries = 0 self._tries = 0
self._accesspoint_connected = True self._accesspoint_connected = True
self.hmip_device_by_entity_id = {}
async def async_setup(self, tries: int = 0): async def async_setup(self, tries: int = 0):
"""Initialize connection.""" """Initialize connection."""

View File

@ -9,7 +9,6 @@ from homematicip.aio.device import (
AsyncFullFlushDimmer, AsyncFullFlushDimmer,
AsyncPluggableDimmer, AsyncPluggableDimmer,
) )
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import RGBColorState from homematicip.base.enums import RGBColorState
from homematicip.base.functionalChannels import NotificationLightChannel from homematicip.base.functionalChannels import NotificationLightChannel
@ -25,6 +24,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -41,26 +41,26 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP Cloud lights from a config entry.""" """Set up the HomematicIP Cloud lights from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.devices: for device in hap.home.devices:
if isinstance(device, AsyncBrandSwitchMeasuring): if isinstance(device, AsyncBrandSwitchMeasuring):
devices.append(HomematicipLightMeasuring(home, device)) devices.append(HomematicipLightMeasuring(hap, device))
elif isinstance(device, AsyncBrandSwitchNotificationLight): elif isinstance(device, AsyncBrandSwitchNotificationLight):
devices.append(HomematicipLight(home, device)) devices.append(HomematicipLight(hap, device))
devices.append( devices.append(
HomematicipNotificationLight(home, device, device.topLightChannelIndex) HomematicipNotificationLight(hap, device, device.topLightChannelIndex)
) )
devices.append( devices.append(
HomematicipNotificationLight( HomematicipNotificationLight(
home, device, device.bottomLightChannelIndex hap, device, device.bottomLightChannelIndex
) )
) )
elif isinstance( elif isinstance(
device, device,
(AsyncDimmer, AsyncPluggableDimmer, AsyncBrandDimmer, AsyncFullFlushDimmer), (AsyncDimmer, AsyncPluggableDimmer, AsyncBrandDimmer, AsyncFullFlushDimmer),
): ):
devices.append(HomematicipDimmer(home, device)) devices.append(HomematicipDimmer(hap, device))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -69,9 +69,9 @@ async def async_setup_entry(
class HomematicipLight(HomematicipGenericDevice, Light): class HomematicipLight(HomematicipGenericDevice, Light):
"""Representation of a HomematicIP Cloud light device.""" """Representation of a HomematicIP Cloud light device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the light device.""" """Initialize the light device."""
super().__init__(home, device) super().__init__(hap, device)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -107,9 +107,9 @@ class HomematicipLightMeasuring(HomematicipLight):
class HomematicipDimmer(HomematicipGenericDevice, Light): class HomematicipDimmer(HomematicipGenericDevice, Light):
"""Representation of HomematicIP Cloud dimmer light device.""" """Representation of HomematicIP Cloud dimmer light device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the dimmer light device.""" """Initialize the dimmer light device."""
super().__init__(home, device) super().__init__(hap, device)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -143,13 +143,13 @@ class HomematicipDimmer(HomematicipGenericDevice, Light):
class HomematicipNotificationLight(HomematicipGenericDevice, Light): class HomematicipNotificationLight(HomematicipGenericDevice, Light):
"""Representation of HomematicIP Cloud dimmer light device.""" """Representation of HomematicIP Cloud dimmer light device."""
def __init__(self, home: AsyncHome, device, channel: int) -> None: def __init__(self, hap: HomematicipHAP, device, channel: int) -> None:
"""Initialize the dimmer light device.""" """Initialize the dimmer light device."""
self.channel = channel self.channel = channel
if self.channel == 2: if self.channel == 2:
super().__init__(home, device, "Top") super().__init__(hap, device, "Top")
else: else:
super().__init__(home, device, "Bottom") super().__init__(hap, device, "Bottom")
self._color_switcher = { self._color_switcher = {
RGBColorState.WHITE: [0.0, 0.0], RGBColorState.WHITE: [0.0, 0.0],

View File

@ -20,7 +20,6 @@ from homematicip.aio.device import (
AsyncWeatherSensorPlus, AsyncWeatherSensorPlus,
AsyncWeatherSensorPro, AsyncWeatherSensorPro,
) )
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import ValveState from homematicip.base.enums import ValveState
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -36,6 +35,7 @@ from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .device import ATTR_IS_GROUP, ATTR_MODEL_TYPE from .device import ATTR_IS_GROUP, ATTR_MODEL_TYPE
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -55,12 +55,12 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP Cloud sensors from a config entry.""" """Set up the HomematicIP Cloud sensors from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [HomematicipAccesspointStatus(home)] devices = [HomematicipAccesspointStatus(hap)]
for device in home.devices: for device in hap.home.devices:
if isinstance(device, (AsyncHeatingThermostat, AsyncHeatingThermostatCompact)): if isinstance(device, (AsyncHeatingThermostat, AsyncHeatingThermostatCompact)):
devices.append(HomematicipHeatingThermostat(home, device)) devices.append(HomematicipHeatingThermostat(hap, device))
devices.append(HomematicipTemperatureSensor(home, device)) devices.append(HomematicipTemperatureSensor(hap, device))
if isinstance( if isinstance(
device, device,
( (
@ -72,8 +72,8 @@ async def async_setup_entry(
AsyncWeatherSensorPro, AsyncWeatherSensorPro,
), ),
): ):
devices.append(HomematicipTemperatureSensor(home, device)) devices.append(HomematicipTemperatureSensor(hap, device))
devices.append(HomematicipHumiditySensor(home, device)) devices.append(HomematicipHumiditySensor(hap, device))
if isinstance( if isinstance(
device, device,
( (
@ -87,7 +87,7 @@ async def async_setup_entry(
AsyncWeatherSensorPro, AsyncWeatherSensorPro,
), ),
): ):
devices.append(HomematicipIlluminanceSensor(home, device)) devices.append(HomematicipIlluminanceSensor(hap, device))
if isinstance( if isinstance(
device, device,
( (
@ -96,15 +96,15 @@ async def async_setup_entry(
AsyncFullFlushSwitchMeasuring, AsyncFullFlushSwitchMeasuring,
), ),
): ):
devices.append(HomematicipPowerSensor(home, device)) devices.append(HomematicipPowerSensor(hap, device))
if isinstance( if isinstance(
device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro) device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro)
): ):
devices.append(HomematicipWindspeedSensor(home, device)) devices.append(HomematicipWindspeedSensor(hap, device))
if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)): if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)):
devices.append(HomematicipTodayRainSensor(home, device)) devices.append(HomematicipTodayRainSensor(hap, device))
if isinstance(device, AsyncPassageDetector): if isinstance(device, AsyncPassageDetector):
devices.append(HomematicipPassageDetectorDeltaCounter(home, device)) devices.append(HomematicipPassageDetectorDeltaCounter(hap, device))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -113,9 +113,9 @@ async def async_setup_entry(
class HomematicipAccesspointStatus(HomematicipGenericDevice): class HomematicipAccesspointStatus(HomematicipGenericDevice):
"""Representation of an HomeMaticIP Cloud access point.""" """Representation of an HomeMaticIP Cloud access point."""
def __init__(self, home: AsyncHome) -> None: def __init__(self, hap: HomematicipHAP) -> None:
"""Initialize access point device.""" """Initialize access point device."""
super().__init__(home, home) super().__init__(hap, hap.home)
@property @property
def device_info(self): def device_info(self):
@ -162,9 +162,9 @@ class HomematicipAccesspointStatus(HomematicipGenericDevice):
class HomematicipHeatingThermostat(HomematicipGenericDevice): class HomematicipHeatingThermostat(HomematicipGenericDevice):
"""Representation of a HomematicIP heating thermostat device.""" """Representation of a HomematicIP heating thermostat device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize heating thermostat device.""" """Initialize heating thermostat device."""
super().__init__(home, device, "Heating") super().__init__(hap, device, "Heating")
@property @property
def icon(self) -> str: def icon(self) -> str:
@ -191,9 +191,9 @@ class HomematicipHeatingThermostat(HomematicipGenericDevice):
class HomematicipHumiditySensor(HomematicipGenericDevice): class HomematicipHumiditySensor(HomematicipGenericDevice):
"""Representation of a HomematicIP Cloud humidity device.""" """Representation of a HomematicIP Cloud humidity device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the thermometer device.""" """Initialize the thermometer device."""
super().__init__(home, device, "Humidity") super().__init__(hap, device, "Humidity")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -214,9 +214,9 @@ class HomematicipHumiditySensor(HomematicipGenericDevice):
class HomematicipTemperatureSensor(HomematicipGenericDevice): class HomematicipTemperatureSensor(HomematicipGenericDevice):
"""Representation of a HomematicIP Cloud thermometer device.""" """Representation of a HomematicIP Cloud thermometer device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the thermometer device.""" """Initialize the thermometer device."""
super().__init__(home, device, "Temperature") super().__init__(hap, device, "Temperature")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -251,9 +251,9 @@ class HomematicipTemperatureSensor(HomematicipGenericDevice):
class HomematicipIlluminanceSensor(HomematicipGenericDevice): class HomematicipIlluminanceSensor(HomematicipGenericDevice):
"""Representation of a HomematicIP Illuminance device.""" """Representation of a HomematicIP Illuminance device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the device.""" """Initialize the device."""
super().__init__(home, device, "Illuminance") super().__init__(hap, device, "Illuminance")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -277,9 +277,9 @@ class HomematicipIlluminanceSensor(HomematicipGenericDevice):
class HomematicipPowerSensor(HomematicipGenericDevice): class HomematicipPowerSensor(HomematicipGenericDevice):
"""Representation of a HomematicIP power measuring device.""" """Representation of a HomematicIP power measuring device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the device.""" """Initialize the device."""
super().__init__(home, device, "Power") super().__init__(hap, device, "Power")
@property @property
def device_class(self) -> str: def device_class(self) -> str:
@ -300,9 +300,9 @@ class HomematicipPowerSensor(HomematicipGenericDevice):
class HomematicipWindspeedSensor(HomematicipGenericDevice): class HomematicipWindspeedSensor(HomematicipGenericDevice):
"""Representation of a HomematicIP wind speed sensor.""" """Representation of a HomematicIP wind speed sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the device.""" """Initialize the device."""
super().__init__(home, device, "Windspeed") super().__init__(hap, device, "Windspeed")
@property @property
def state(self) -> float: def state(self) -> float:
@ -333,9 +333,9 @@ class HomematicipWindspeedSensor(HomematicipGenericDevice):
class HomematicipTodayRainSensor(HomematicipGenericDevice): class HomematicipTodayRainSensor(HomematicipGenericDevice):
"""Representation of a HomematicIP rain counter of a day sensor.""" """Representation of a HomematicIP rain counter of a day sensor."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the device.""" """Initialize the device."""
super().__init__(home, device, "Today Rain") super().__init__(hap, device, "Today Rain")
@property @property
def state(self) -> float: def state(self) -> float:
@ -351,10 +351,6 @@ class HomematicipTodayRainSensor(HomematicipGenericDevice):
class HomematicipPassageDetectorDeltaCounter(HomematicipGenericDevice): class HomematicipPassageDetectorDeltaCounter(HomematicipGenericDevice):
"""Representation of a HomematicIP passage detector delta counter.""" """Representation of a HomematicIP passage detector delta counter."""
def __init__(self, home: AsyncHome, device) -> None:
"""Initialize the device."""
super().__init__(home, device)
@property @property
def state(self) -> int: def state(self) -> int:
"""Representation of the HomematicIP passage detector delta counter value.""" """Representation of the HomematicIP passage detector delta counter value."""

View File

@ -12,7 +12,6 @@ from homematicip.aio.device import (
AsyncPrintedCircuitBoardSwitchBattery, AsyncPrintedCircuitBoardSwitchBattery,
) )
from homematicip.aio.group import AsyncSwitchingGroup from homematicip.aio.group import AsyncSwitchingGroup
from homematicip.aio.home import AsyncHome
from homeassistant.components.switch import SwitchDevice from homeassistant.components.switch import SwitchDevice
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -20,6 +19,7 @@ from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .device import ATTR_GROUP_MEMBER_UNREACHABLE from .device import ATTR_GROUP_MEMBER_UNREACHABLE
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -33,9 +33,9 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP switch from a config entry.""" """Set up the HomematicIP switch from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.devices: for device in hap.home.devices:
if isinstance(device, AsyncBrandSwitchMeasuring): if isinstance(device, AsyncBrandSwitchMeasuring):
# BrandSwitchMeasuring inherits PlugableSwitchMeasuring # BrandSwitchMeasuring inherits PlugableSwitchMeasuring
# This device is implemented in the light platform and will # This device is implemented in the light platform and will
@ -44,24 +44,24 @@ async def async_setup_entry(
elif isinstance( elif isinstance(
device, (AsyncPlugableSwitchMeasuring, AsyncFullFlushSwitchMeasuring) device, (AsyncPlugableSwitchMeasuring, AsyncFullFlushSwitchMeasuring)
): ):
devices.append(HomematicipSwitchMeasuring(home, device)) devices.append(HomematicipSwitchMeasuring(hap, device))
elif isinstance( elif isinstance(
device, (AsyncPlugableSwitch, AsyncPrintedCircuitBoardSwitchBattery) device, (AsyncPlugableSwitch, AsyncPrintedCircuitBoardSwitchBattery)
): ):
devices.append(HomematicipSwitch(home, device)) devices.append(HomematicipSwitch(hap, device))
elif isinstance(device, AsyncOpenCollector8Module): elif isinstance(device, AsyncOpenCollector8Module):
for channel in range(1, 9): for channel in range(1, 9):
devices.append(HomematicipMultiSwitch(home, device, channel)) devices.append(HomematicipMultiSwitch(hap, device, channel))
elif isinstance(device, AsyncMultiIOBox): elif isinstance(device, AsyncMultiIOBox):
for channel in range(1, 3): for channel in range(1, 3):
devices.append(HomematicipMultiSwitch(home, device, channel)) devices.append(HomematicipMultiSwitch(hap, device, channel))
elif isinstance(device, AsyncPrintedCircuitBoardSwitch2): elif isinstance(device, AsyncPrintedCircuitBoardSwitch2):
for channel in range(1, 3): for channel in range(1, 3):
devices.append(HomematicipMultiSwitch(home, device, channel)) devices.append(HomematicipMultiSwitch(hap, device, channel))
for group in home.groups: for group in hap.home.groups:
if isinstance(group, AsyncSwitchingGroup): if isinstance(group, AsyncSwitchingGroup):
devices.append(HomematicipGroupSwitch(home, group)) devices.append(HomematicipGroupSwitch(hap, group))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -70,9 +70,9 @@ async def async_setup_entry(
class HomematicipSwitch(HomematicipGenericDevice, SwitchDevice): class HomematicipSwitch(HomematicipGenericDevice, SwitchDevice):
"""representation of a HomematicIP Cloud switch device.""" """representation of a HomematicIP Cloud switch device."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the switch device.""" """Initialize the switch device."""
super().__init__(home, device) super().__init__(hap, device)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -91,10 +91,10 @@ class HomematicipSwitch(HomematicipGenericDevice, SwitchDevice):
class HomematicipGroupSwitch(HomematicipGenericDevice, SwitchDevice): class HomematicipGroupSwitch(HomematicipGenericDevice, SwitchDevice):
"""representation of a HomematicIP switching group.""" """representation of a HomematicIP switching group."""
def __init__(self, home: AsyncHome, device, post: str = "Group") -> None: def __init__(self, hap: HomematicipHAP, device, post: str = "Group") -> None:
"""Initialize switching group.""" """Initialize switching group."""
device.modelType = f"HmIP-{post}" device.modelType = f"HmIP-{post}"
super().__init__(home, device, post) super().__init__(hap, device, post)
@property @property
def is_on(self) -> bool: def is_on(self) -> bool:
@ -148,10 +148,10 @@ class HomematicipSwitchMeasuring(HomematicipSwitch):
class HomematicipMultiSwitch(HomematicipGenericDevice, SwitchDevice): class HomematicipMultiSwitch(HomematicipGenericDevice, SwitchDevice):
"""Representation of a HomematicIP Cloud multi switch device.""" """Representation of a HomematicIP Cloud multi switch device."""
def __init__(self, home: AsyncHome, device, channel: int): def __init__(self, hap: HomematicipHAP, device, channel: int):
"""Initialize the multi switch device.""" """Initialize the multi switch device."""
self.channel = channel self.channel = channel
super().__init__(home, device, f"Channel{channel}") super().__init__(hap, device, f"Channel{channel}")
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:

View File

@ -6,7 +6,6 @@ from homematicip.aio.device import (
AsyncWeatherSensorPlus, AsyncWeatherSensorPlus,
AsyncWeatherSensorPro, AsyncWeatherSensorPro,
) )
from homematicip.aio.home import AsyncHome
from homematicip.base.enums import WeatherCondition from homematicip.base.enums import WeatherCondition
from homeassistant.components.weather import WeatherEntity from homeassistant.components.weather import WeatherEntity
@ -15,6 +14,7 @@ from homeassistant.const import TEMP_CELSIUS
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
from .hap import HomematicipHAP
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -46,15 +46,15 @@ async def async_setup_entry(
hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities
) -> None: ) -> None:
"""Set up the HomematicIP weather sensor from a config entry.""" """Set up the HomematicIP weather sensor from a config entry."""
home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home hap = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]]
devices = [] devices = []
for device in home.devices: for device in hap.home.devices:
if isinstance(device, AsyncWeatherSensorPro): if isinstance(device, AsyncWeatherSensorPro):
devices.append(HomematicipWeatherSensorPro(home, device)) devices.append(HomematicipWeatherSensorPro(hap, device))
elif isinstance(device, (AsyncWeatherSensor, AsyncWeatherSensorPlus)): elif isinstance(device, (AsyncWeatherSensor, AsyncWeatherSensorPlus)):
devices.append(HomematicipWeatherSensor(home, device)) devices.append(HomematicipWeatherSensor(hap, device))
devices.append(HomematicipHomeWeather(home)) devices.append(HomematicipHomeWeather(hap))
if devices: if devices:
async_add_entities(devices) async_add_entities(devices)
@ -63,9 +63,9 @@ async def async_setup_entry(
class HomematicipWeatherSensor(HomematicipGenericDevice, WeatherEntity): class HomematicipWeatherSensor(HomematicipGenericDevice, WeatherEntity):
"""representation of a HomematicIP Cloud weather sensor plus & basic.""" """representation of a HomematicIP Cloud weather sensor plus & basic."""
def __init__(self, home: AsyncHome, device) -> None: def __init__(self, hap: HomematicipHAP, device) -> None:
"""Initialize the weather sensor.""" """Initialize the weather sensor."""
super().__init__(home, device) super().__init__(hap, device)
@property @property
def name(self) -> str: def name(self) -> str:
@ -121,10 +121,10 @@ class HomematicipWeatherSensorPro(HomematicipWeatherSensor):
class HomematicipHomeWeather(HomematicipGenericDevice, WeatherEntity): class HomematicipHomeWeather(HomematicipGenericDevice, WeatherEntity):
"""representation of a HomematicIP Cloud home weather.""" """representation of a HomematicIP Cloud home weather."""
def __init__(self, home: AsyncHome) -> None: def __init__(self, hap: HomematicipHAP) -> None:
"""Initialize the home weather.""" """Initialize the home weather."""
home.modelType = "HmIP-Home-Weather" hap.home.modelType = "HmIP-Home-Weather"
super().__init__(home, home) super().__init__(hap, hap.home)
@property @property
def available(self) -> bool: def available(self) -> bool:

View File

@ -6,10 +6,14 @@ import pytest
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.homematicip_cloud import ( from homeassistant.components.homematicip_cloud import (
CONF_ACCESSPOINT,
CONF_AUTHTOKEN,
DOMAIN as HMIPC_DOMAIN, DOMAIN as HMIPC_DOMAIN,
async_setup as hmip_async_setup,
const as hmipc, const as hmipc,
hap as hmip_hap, hap as hmip_hap,
) )
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from .helper import AUTH_TOKEN, HAPID, HomeTemplate from .helper import AUTH_TOKEN, HAPID, HomeTemplate
@ -19,7 +23,7 @@ from tests.common import MockConfigEntry, mock_coro
@pytest.fixture(name="mock_connection") @pytest.fixture(name="mock_connection")
def mock_connection_fixture(): def mock_connection_fixture():
"""Return a mockked connection.""" """Return a mocked connection."""
connection = MagicMock(spec=AsyncConnection) connection = MagicMock(spec=AsyncConnection)
def _rest_call_side_effect(path, body=None): def _rest_call_side_effect(path, body=None):
@ -39,7 +43,7 @@ def default_mock_home_fixture(mock_connection):
@pytest.fixture(name="hmip_config_entry") @pytest.fixture(name="hmip_config_entry")
def hmip_config_entry_fixture(): def hmip_config_entry_fixture():
"""Create a fake config entriy for homematic ip cloud.""" """Create a mock config entriy for homematic ip cloud."""
entry_data = { entry_data = {
hmipc.HMIPC_HAPID: HAPID, hmipc.HMIPC_HAPID: HAPID,
hmipc.HMIPC_AUTHTOKEN: AUTH_TOKEN, hmipc.HMIPC_AUTHTOKEN: AUTH_TOKEN,
@ -67,9 +71,32 @@ async def default_mock_hap_fixture(
hap = hmip_hap.HomematicipHAP(hass, hmip_config_entry) hap = hmip_hap.HomematicipHAP(hass, hmip_config_entry)
with patch.object(hap, "get_hap", return_value=mock_coro(default_mock_home)): with patch.object(hap, "get_hap", return_value=mock_coro(default_mock_home)):
assert await hap.async_setup() is True assert await hap.async_setup() is True
default_mock_home.on_update(hap.async_update)
default_mock_home.on_create(hap.async_create_entity)
hass.data[HMIPC_DOMAIN] = {HAPID: hap} hass.data[HMIPC_DOMAIN] = {HAPID: hap}
await hass.async_block_till_done() await hass.async_block_till_done()
return hap return hap
@pytest.fixture(name="hmip_config")
def hmip_config_fixture():
"""Create a config for homematic ip cloud."""
entry_data = {CONF_ACCESSPOINT: HAPID, CONF_AUTHTOKEN: AUTH_TOKEN, CONF_NAME: ""}
return {hmipc.DOMAIN: [entry_data]}
@pytest.fixture(name="mock_hap_with_service")
async def mock_hap_with_service_fixture(
hass: HomeAssistant, default_mock_hap, hmip_config
):
"""Create a fake homematic access point with hass services."""
await hmip_async_setup(hass, hmip_config)
await hass.async_block_till_done()
hass.data[HMIPC_DOMAIN] = {HAPID: default_mock_hap}
return default_mock_hap

View File

@ -1,18 +1,25 @@
"""Helper for HomematicIP Cloud Tests.""" """Helper for HomematicIP Cloud Tests."""
import json import json
from unittest.mock import Mock from asynctest import Mock
from homematicip.aio.class_maps import ( from homematicip.aio.class_maps import (
TYPE_CLASS_MAP, TYPE_CLASS_MAP,
TYPE_GROUP_MAP, TYPE_GROUP_MAP,
TYPE_SECURITY_EVENT_MAP, TYPE_SECURITY_EVENT_MAP,
) )
from homematicip.aio.device import AsyncDevice
from homematicip.aio.group import AsyncGroup
from homematicip.aio.home import AsyncHome from homematicip.aio.home import AsyncHome
from homematicip.home import Home from homematicip.home import Home
from homeassistant.components.homematicip_cloud.device import (
ATTR_IS_GROUP,
ATTR_MODEL_TYPE,
)
from tests.common import load_fixture from tests.common import load_fixture
HAPID = "Mock_HAP" HAPID = "3014F7110000000000000001"
AUTH_TOKEN = "1234" AUTH_TOKEN = "1234"
HOME_JSON = "homematicip_cloud.json" HOME_JSON = "homematicip_cloud.json"
@ -21,28 +28,38 @@ def get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model hass, default_mock_hap, entity_id, entity_name, device_model
): ):
"""Get and test basic device.""" """Get and test basic device."""
ha_entity = hass.states.get(entity_id) ha_state = hass.states.get(entity_id)
assert ha_entity is not None assert ha_state is not None
assert ha_entity.attributes["model_type"] == device_model if device_model:
assert ha_entity.name == entity_name assert ha_state.attributes[ATTR_MODEL_TYPE] == device_model
assert ha_state.name == entity_name
hmip_device = default_mock_hap.home.template.search_mock_device_by_id( hmip_device = default_mock_hap.hmip_device_by_entity_id.get(entity_id)
ha_entity.attributes["id"] if hmip_device:
) if isinstance(hmip_device, AsyncDevice):
assert hmip_device is not None assert ha_state.attributes[ATTR_IS_GROUP] is False
return ha_entity, hmip_device elif isinstance(hmip_device, AsyncGroup):
assert ha_state.attributes[ATTR_IS_GROUP] is True
return ha_state, hmip_device
async def async_manipulate_test_data( async def async_manipulate_test_data(
hass, hmip_device, attribute, new_value, channel=1 hass, hmip_device, attribute, new_value, channel=1, fire_device=None
): ):
"""Set new value on hmip device.""" """Set new value on hmip device."""
if channel == 1: if channel == 1:
setattr(hmip_device, attribute, new_value) setattr(hmip_device, attribute, new_value)
functional_channel = hmip_device.functionalChannels[channel] if hasattr(hmip_device, "functionalChannels"):
setattr(functional_channel, attribute, new_value) functional_channel = hmip_device.functionalChannels[channel]
setattr(functional_channel, attribute, new_value)
fire_target = hmip_device if fire_device is None else fire_device
if isinstance(fire_target, AsyncHome):
fire_target.fire_update_event(fire_target._rawJSONData) # pylint: disable=W0212
else:
fire_target.fire_update_event()
hmip_device.fire_update_event()
await hass.async_block_till_done() await hass.async_block_till_done()
@ -66,8 +83,8 @@ class HomeTemplate(Home):
def __init__(self, connection=None): def __init__(self, connection=None):
"""Init template with connection.""" """Init template with connection."""
super().__init__(connection=connection) super().__init__(connection=connection)
self.mock_devices = [] self.label = "Access Point"
self.mock_groups = [] self.model_type = "HmIP-HAP"
def init_home(self, json_path=HOME_JSON): def init_home(self, json_path=HOME_JSON):
"""Init template with json.""" """Init template with json."""
@ -78,24 +95,15 @@ class HomeTemplate(Home):
def _generate_mocks(self): def _generate_mocks(self):
"""Generate mocks for groups and devices.""" """Generate mocks for groups and devices."""
mock_devices = []
for device in self.devices: for device in self.devices:
self.mock_devices.append(_get_mock(device)) mock_devices.append(_get_mock(device))
self.devices = mock_devices
mock_groups = []
for group in self.groups: for group in self.groups:
self.mock_groups.append(_get_mock(group)) mock_groups.append(_get_mock(group))
self.groups = mock_groups
def search_mock_device_by_id(self, device_id):
"""Search a device by given id."""
for device in self.mock_devices:
if device.id == device_id:
return device
return None
def search_mock_group_by_id(self, group_id):
"""Search a group by given id."""
for group in self.mock_groups:
if group.id == group_id:
return group
return None
def get_async_home_mock(self): def get_async_home_mock(self):
""" """
@ -105,19 +113,11 @@ class HomeTemplate(Home):
and sets reuired attributes. and sets reuired attributes.
""" """
mock_home = Mock( mock_home = Mock(
check_connection=self._connection, spec=AsyncHome, wraps=self, label="Access Point", modelType="HmIP-HAP"
id=HAPID,
connected=True,
dutyCycle=self.dutyCycle,
devices=self.mock_devices,
groups=self.mock_groups,
weather=self.weather,
location=self.location,
label="home label",
template=self,
spec=AsyncHome,
) )
mock_home.__dict__.update(self.__dict__)
mock_home.name = "" mock_home.name = ""
return mock_home return mock_home

View File

@ -0,0 +1,289 @@
"""Tests for HomematicIP Cloud binary sensor."""
from homematicip.base.enums import SmokeDetectorAlarmType, WindowState
from homeassistant.components.homematicip_cloud.binary_sensor import (
ATTR_ACCELERATION_SENSOR_MODE,
ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION,
ATTR_ACCELERATION_SENSOR_SENSITIVITY,
ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE,
ATTR_LOW_BATTERY,
ATTR_MOTION_DETECTED,
)
from homeassistant.const import STATE_OFF, STATE_ON
from .helper import async_manipulate_test_data, get_and_check_entity_basics
async def test_hmip_acceleration_sensor(hass, default_mock_hap):
"""Test HomematicipAccelerationSensor."""
entity_id = "binary_sensor.garagentor"
entity_name = "Garagentor"
device_model = "HmIP-SAM"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_ACCELERATION_SENSOR_MODE] == "FLAT_DECT"
assert ha_state.attributes[ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION] == "VERTICAL"
assert (
ha_state.attributes[ATTR_ACCELERATION_SENSOR_SENSITIVITY] == "SENSOR_RANGE_4G"
)
assert ha_state.attributes[ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE] == 45
service_call_counter = len(hmip_device.mock_calls)
await async_manipulate_test_data(
hass, hmip_device, "accelerationSensorTriggered", False
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
assert len(hmip_device.mock_calls) == service_call_counter + 1
await async_manipulate_test_data(
hass, hmip_device, "accelerationSensorTriggered", True
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert len(hmip_device.mock_calls) == service_call_counter + 2
async def test_hmip_contact_interface(hass, default_mock_hap):
"""Test HomematicipContactInterface."""
entity_id = "binary_sensor.kontakt_schnittstelle_unterputz_1_fach"
entity_name = "Kontakt-Schnittstelle Unterputz 1-fach"
device_model = "HmIP-FCI1"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "windowState", WindowState.OPEN)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
await async_manipulate_test_data(hass, hmip_device, "windowState", None)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_shutter_contact(hass, default_mock_hap):
"""Test HomematicipShutterContact."""
entity_id = "binary_sensor.fenstergriffsensor"
entity_name = "Fenstergriffsensor"
device_model = "HmIP-SRH"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_ON
await async_manipulate_test_data(
hass, hmip_device, "windowState", WindowState.CLOSED
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "windowState", None)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_motion_detector(hass, default_mock_hap):
"""Test HomematicipMotionDetector."""
entity_id = "binary_sensor.bewegungsmelder_fur_55er_rahmen_innen"
entity_name = "Bewegungsmelder für 55er Rahmen innen"
device_model = "HmIP-SMI55"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "motionDetected", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_presence_detector(hass, default_mock_hap):
"""Test HomematicipPresenceDetector."""
entity_id = "binary_sensor.spi_1"
entity_name = "SPI_1"
device_model = "HmIP-SPI"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "presenceDetected", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_smoke_detector(hass, default_mock_hap):
"""Test HomematicipSmokeDetector."""
entity_id = "binary_sensor.rauchwarnmelder"
entity_name = "Rauchwarnmelder"
device_model = "HmIP-SWSD"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(
hass,
hmip_device,
"smokeDetectorAlarmType",
SmokeDetectorAlarmType.PRIMARY_ALARM,
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_water_detector(hass, default_mock_hap):
"""Test HomematicipWaterDetector."""
entity_id = "binary_sensor.wassersensor"
entity_name = "Wassersensor"
device_model = "HmIP-SWD"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "waterlevelDetected", True)
await async_manipulate_test_data(hass, hmip_device, "moistureDetected", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
await async_manipulate_test_data(hass, hmip_device, "waterlevelDetected", True)
await async_manipulate_test_data(hass, hmip_device, "moistureDetected", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
await async_manipulate_test_data(hass, hmip_device, "waterlevelDetected", False)
await async_manipulate_test_data(hass, hmip_device, "moistureDetected", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
await async_manipulate_test_data(hass, hmip_device, "waterlevelDetected", False)
await async_manipulate_test_data(hass, hmip_device, "moistureDetected", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_storm_sensor(hass, default_mock_hap):
"""Test HomematicipStormSensor."""
entity_id = "binary_sensor.weather_sensor_plus_storm"
entity_name = "Weather Sensor plus Storm"
device_model = "HmIP-SWO-PL"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "storm", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_rain_sensor(hass, default_mock_hap):
"""Test HomematicipRainSensor."""
entity_id = "binary_sensor.wettersensor_pro_raining"
entity_name = "Wettersensor - pro Raining"
device_model = "HmIP-SWO-PR"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "raining", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_sunshine_sensor(hass, default_mock_hap):
"""Test HomematicipSunshineSensor."""
entity_id = "binary_sensor.wettersensor_pro_sunshine"
entity_name = "Wettersensor - pro Sunshine"
device_model = "HmIP-SWO-PR"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_ON
assert ha_state.attributes["today_sunshine_duration_in_minutes"] == 100
await async_manipulate_test_data(hass, hmip_device, "sunshine", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_battery_sensor(hass, default_mock_hap):
"""Test HomematicipSunshineSensor."""
entity_id = "binary_sensor.wohnungsture_battery"
entity_name = "Wohnungstüre Battery"
device_model = "HMIP-SWDO"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "lowBat", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_security_zone_sensor_group(hass, default_mock_hap):
"""Test HomematicipSecurityZoneSensorGroup."""
entity_id = "binary_sensor.internal_securityzone"
entity_name = "INTERNAL SecurityZone"
device_model = "HmIP-SecurityZone"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
await async_manipulate_test_data(hass, hmip_device, "motionDetected", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_MOTION_DETECTED] is True
async def test_hmip_security_sensor_group(hass, default_mock_hap):
"""Test HomematicipSecuritySensorGroup."""
entity_id = "binary_sensor.buro_sensors"
entity_name = "Büro Sensors"
device_model = None
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
assert not ha_state.attributes.get("low_bat")
await async_manipulate_test_data(hass, hmip_device, "lowBat", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_LOW_BATTERY] is True
await async_manipulate_test_data(hass, hmip_device, "lowBat", False)
await async_manipulate_test_data(
hass,
hmip_device,
"smokeDetectorAlarmType",
SmokeDetectorAlarmType.PRIMARY_ALARM,
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert (
ha_state.attributes["smoke_detector_alarm"]
== SmokeDetectorAlarmType.PRIMARY_ALARM
)

View File

@ -1,41 +0,0 @@
"""Tests for HomematicIP Cloud lights."""
import logging
from tests.components.homematicip_cloud.helper import (
async_manipulate_test_data,
get_and_check_entity_basics,
)
_LOGGER = logging.getLogger(__name__)
async def test_hmip_sam(hass, default_mock_hap):
"""Test HomematicipLight."""
entity_id = "binary_sensor.garagentor"
entity_name = "Garagentor"
device_model = "HmIP-SAM"
ha_entity, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_entity.state == "on"
assert ha_entity.attributes["acceleration_sensor_mode"] == "FLAT_DECT"
assert ha_entity.attributes["acceleration_sensor_neutral_position"] == "VERTICAL"
assert ha_entity.attributes["acceleration_sensor_sensitivity"] == "SENSOR_RANGE_4G"
assert ha_entity.attributes["acceleration_sensor_trigger_angle"] == 45
service_call_counter = len(hmip_device.mock_calls)
await async_manipulate_test_data(
hass, hmip_device, "accelerationSensorTriggered", False
)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "off"
assert len(hmip_device.mock_calls) == service_call_counter + 1
await async_manipulate_test_data(
hass, hmip_device, "accelerationSensorTriggered", True
)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "on"
assert len(hmip_device.mock_calls) == service_call_counter + 2

View File

@ -0,0 +1,196 @@
"""Tests for HomematicIP Cloud light."""
from homematicip.base.enums import RGBColorState
from homeassistant.components.homematicip_cloud.light import (
ATTR_ENERGY_COUNTER,
ATTR_POWER_CONSUMPTION,
)
from homeassistant.components.light import ATTR_BRIGHTNESS, ATTR_COLOR_NAME
from homeassistant.const import STATE_OFF, STATE_ON
from .helper import async_manipulate_test_data, get_and_check_entity_basics
async def test_hmip_light(hass, default_mock_hap):
"""Test HomematicipLight."""
entity_id = "light.treppe"
entity_name = "Treppe"
device_model = "HmIP-BSL"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_ON
service_call_counter = len(hmip_device.mock_calls)
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 1
assert hmip_device.mock_calls[-1][0] == "turn_off"
assert hmip_device.mock_calls[-1][1] == ()
await async_manipulate_test_data(hass, hmip_device, "on", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 3
assert hmip_device.mock_calls[-1][0] == "turn_on"
assert hmip_device.mock_calls[-1][1] == ()
await async_manipulate_test_data(hass, hmip_device, "on", True)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
async def test_hmip_notification_light(hass, default_mock_hap):
"""Test HomematicipNotificationLight."""
entity_id = "light.treppe_top_notification"
entity_name = "Treppe Top Notification"
device_model = "HmIP-BSL"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
service_call_counter = len(hmip_device.mock_calls)
# Send all color via service call.
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
assert hmip_device.mock_calls[-1][1] == (2, RGBColorState.RED, 1.0)
color_list = {
RGBColorState.WHITE: [0.0, 0.0],
RGBColorState.RED: [0.0, 100.0],
RGBColorState.YELLOW: [60.0, 100.0],
RGBColorState.GREEN: [120.0, 100.0],
RGBColorState.TURQUOISE: [180.0, 100.0],
RGBColorState.BLUE: [240.0, 100.0],
RGBColorState.PURPLE: [300.0, 100.0],
}
for color, hs_color in color_list.items():
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": entity_id, "hs_color": hs_color},
blocking=True,
)
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
assert hmip_device.mock_calls[-1][1] == (2, color, 0.0392156862745098)
assert len(hmip_device.mock_calls) == service_call_counter + 8
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
assert hmip_device.mock_calls[-1][1] == (
2,
RGBColorState.PURPLE,
0.0392156862745098,
)
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 1, 2)
await async_manipulate_test_data(
hass, hmip_device, "simpleRGBColorState", RGBColorState.PURPLE, 2
)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_COLOR_NAME] == RGBColorState.PURPLE
assert ha_state.attributes[ATTR_BRIGHTNESS] == 255
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 11
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
assert hmip_device.mock_calls[-1][1] == (2, RGBColorState.PURPLE, 0.0)
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 0, 2)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_dimmer(hass, default_mock_hap):
"""Test HomematicipDimmer."""
entity_id = "light.schlafzimmerlicht"
entity_name = "Schlafzimmerlicht"
device_model = "HmIP-BDT"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
service_call_counter = len(hmip_device.mock_calls)
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert hmip_device.mock_calls[-1][0] == "set_dim_level"
assert hmip_device.mock_calls[-1][1] == (1,)
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": entity_id, "brightness_pct": "100"},
blocking=True,
)
assert len(hmip_device.mock_calls) == service_call_counter + 2
assert hmip_device.mock_calls[-1][0] == "set_dim_level"
assert hmip_device.mock_calls[-1][1] == (1.0,)
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 1)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_BRIGHTNESS] == 255
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 4
assert hmip_device.mock_calls[-1][0] == "set_dim_level"
assert hmip_device.mock_calls[-1][1] == (0,)
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 0)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF
async def test_hmip_light_measuring(hass, default_mock_hap):
"""Test HomematicipLightMeasuring."""
entity_id = "light.flur_oben"
entity_name = "Flur oben"
device_model = "HmIP-BSM"
ha_state, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_state.state == STATE_OFF
service_call_counter = len(hmip_device.mock_calls)
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 1
assert hmip_device.mock_calls[-1][0] == "turn_on"
assert hmip_device.mock_calls[-1][1] == ()
await async_manipulate_test_data(hass, hmip_device, "on", True)
await async_manipulate_test_data(hass, hmip_device, "currentPowerConsumption", 50)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_ON
assert ha_state.attributes[ATTR_POWER_CONSUMPTION] == 50
assert ha_state.attributes[ATTR_ENERGY_COUNTER] == 6.33
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 4
assert hmip_device.mock_calls[-1][0] == "turn_off"
assert hmip_device.mock_calls[-1][1] == ()
await async_manipulate_test_data(hass, hmip_device, "on", False)
ha_state = hass.states.get(entity_id)
assert ha_state.state == STATE_OFF

View File

@ -1,77 +0,0 @@
"""Tests for HomematicIP Cloud lights."""
import logging
from tests.components.homematicip_cloud.helper import (
async_manipulate_test_data,
get_and_check_entity_basics,
)
_LOGGER = logging.getLogger(__name__)
async def test_hmip_light(hass, default_mock_hap):
"""Test HomematicipLight."""
entity_id = "light.treppe"
entity_name = "Treppe"
device_model = "HmIP-BSL"
ha_entity, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_entity.state == "on"
service_call_counter = len(hmip_device.mock_calls)
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 1
assert hmip_device.mock_calls[-1][0] == "turn_off"
await async_manipulate_test_data(hass, hmip_device, "on", False)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "off"
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 3
assert hmip_device.mock_calls[-1][0] == "turn_on"
await async_manipulate_test_data(hass, hmip_device, "on", True)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "on"
# HomematicipLightMeasuring
# HomematicipDimmer
async def test_hmip_notification_light(hass, default_mock_hap):
"""Test HomematicipNotificationLight."""
entity_id = "light.treppe_top_notification"
entity_name = "Treppe Top Notification"
device_model = "HmIP-BSL"
ha_entity, hmip_device = get_and_check_entity_basics(
hass, default_mock_hap, entity_id, entity_name, device_model
)
assert ha_entity.state == "off"
service_call_counter = len(hmip_device.mock_calls)
await hass.services.async_call(
"light", "turn_on", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 1
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 100, 2)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "on"
await hass.services.async_call(
"light", "turn_off", {"entity_id": entity_id}, blocking=True
)
assert len(hmip_device.mock_calls) == service_call_counter + 3
assert hmip_device.mock_calls[-1][0] == "set_rgb_dim_level"
await async_manipulate_test_data(hass, hmip_device, "dimLevel", 0, 2)
ha_entity = hass.states.get(entity_id)
assert ha_entity.state == "off"

View File

@ -2077,6 +2077,144 @@
"type": "SHUTTER_CONTACT", "type": "SHUTTER_CONTACT",
"updateState": "UP_TO_DATE" "updateState": "UP_TO_DATE"
}, },
"3014F7110000000000000108": {
"availableFirmwareVersion": "1.12.6",
"firmwareVersion": "1.12.6",
"firmwareVersionInteger": 68614,
"functionalChannels": {
"0": {
"coProFaulty": false,
"coProRestartNeeded": false,
"coProUpdateFailure": false,
"configPending": false,
"deviceId": "3014F7110000000000000108",
"deviceOverheated": false,
"deviceOverloaded": false,
"deviceUndervoltage": false,
"dutyCycle": false,
"functionalChannelType": "DEVICE_BASE",
"groupIndex": 0,
"groups": [
"00000000-0000-0000-0000-000000000009"
],
"index": 0,
"label": "",
"lowBat": null,
"routerModuleEnabled": false,
"routerModuleSupported": false,
"rssiDeviceValue": -68,
"rssiPeerValue": -63,
"supportedOptionalFeatures": {
"IFeatureDeviceCoProError": false,
"IFeatureDeviceCoProRestart": false,
"IFeatureDeviceCoProUpdate": false,
"IFeatureDeviceOverheated": true,
"IFeatureDeviceOverloaded": false,
"IFeatureDeviceTemperatureOutOfRange": false,
"IFeatureDeviceUndervoltage": false
},
"temperatureOutOfRange": false,
"unreach": false
},
"1": {
"currentPowerConsumption": 0.0,
"deviceId": "3014F7110000000000000108",
"energyCounter": 6.333200000000001,
"functionalChannelType": "SWITCH_MEASURING_CHANNEL",
"groupIndex": 1,
"groups": [
"00000000-0000-0000-0000-000000000023"
],
"index": 1,
"label": "",
"on": false,
"profileMode": "AUTOMATIC",
"userDesiredProfileMode": "AUTOMATIC"
}
},
"homeId": "00000000-0000-0000-0000-000000000001",
"id": "3014F7110000000000000108",
"label": "Flur oben",
"lastStatusUpdate": 1570365990392,
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
"manufacturerCode": 1,
"modelId": 288,
"modelType": "HmIP-BSM",
"oem": "eQ-3",
"permanentlyReachable": true,
"serializedGlobalTradeItemNumber": "3014F7110000000000000108",
"type": "BRAND_SWITCH_MEASURING",
"updateState": "UP_TO_DATE"
},
"3014F7110000000000000109": {
"availableFirmwareVersion": "1.6.2",
"firmwareVersion": "1.6.2",
"firmwareVersionInteger": 67074,
"functionalChannels": {
"0": {
"coProFaulty": false,
"coProRestartNeeded": false,
"coProUpdateFailure": false,
"configPending": false,
"deviceId": "3014F7110000000000000109",
"deviceOverheated": null,
"deviceOverloaded": false,
"deviceUndervoltage": false,
"dutyCycle": false,
"functionalChannelType": "DEVICE_BASE",
"groupIndex": 0,
"groups": [
"00000000-0000-0000-0000-000000000029"
],
"index": 0,
"label": "",
"lowBat": null,
"routerModuleEnabled": false,
"routerModuleSupported": false,
"rssiDeviceValue": -80,
"rssiPeerValue": -73,
"supportedOptionalFeatures": {
"IFeatureDeviceCoProError": false,
"IFeatureDeviceCoProRestart": false,
"IFeatureDeviceCoProUpdate": false,
"IFeatureDeviceOverheated": true,
"IFeatureDeviceOverloaded": false,
"IFeatureDeviceTemperatureOutOfRange": false,
"IFeatureDeviceUndervoltage": false
},
"temperatureOutOfRange": false,
"unreach": false
},
"1": {
"currentPowerConsumption": 0.0,
"deviceId": "3014F7110000000000000109",
"energyCounter": 0.0011,
"functionalChannelType": "SWITCH_MEASURING_CHANNEL",
"groupIndex": 1,
"groups": [
"00000000-0000-0000-0000-000000000030"
],
"index": 1,
"label": "",
"on": false,
"profileMode": "AUTOMATIC",
"userDesiredProfileMode": "AUTOMATIC"
}
},
"homeId": "00000000-0000-0000-0000-000000000001",
"id": "3014F7110000000000000011",
"label": "Ausschalter Terrasse Bewegungsmelder",
"lastStatusUpdate": 1570366291250,
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
"manufacturerCode": 1,
"modelId": 289,
"modelType": "HmIP-FSM",
"oem": "eQ-3",
"permanentlyReachable": true,
"serializedGlobalTradeItemNumber": "3014F7110000000000000109",
"type": "FULL_FLUSH_SWITCH_MEASURING",
"updateState": "UP_TO_DATE"
},
"3014F7110000000000000008": { "3014F7110000000000000008": {
"availableFirmwareVersion": "0.0.0", "availableFirmwareVersion": "0.0.0",
"firmwareVersion": "2.6.2", "firmwareVersion": "2.6.2",
@ -2236,6 +2374,57 @@
"type": "PLUGABLE_SWITCH_MEASURING", "type": "PLUGABLE_SWITCH_MEASURING",
"updateState": "UP_TO_DATE" "updateState": "UP_TO_DATE"
}, },
"3014F7110000000000000110": {
"availableFirmwareVersion": "0.0.0",
"firmwareVersion": "2.6.2",
"firmwareVersionInteger": 132610,
"functionalChannels": {
"0": {
"configPending": false,
"deviceId": "3014F7110000000000000110",
"dutyCycle": false,
"functionalChannelType": "DEVICE_BASE",
"groupIndex": 0,
"groups": [
"00000000-0000-0000-0000-000000000017"
],
"index": 0,
"label": "",
"lowBat": null,
"routerModuleEnabled": true,
"routerModuleSupported": true,
"rssiDeviceValue": -47,
"rssiPeerValue": -49,
"unreach": false
},
"1": {
"deviceId": "3014F7110000000000000110",
"functionalChannelType": "SWITCH_CHANNEL",
"groupIndex": 1,
"groups": [
"00000000-0000-0000-0000-000000000018"
],
"index": 1,
"label": "",
"on": true,
"profileMode": "AUTOMATIC",
"userDesiredProfileMode": "AUTOMATIC"
}
},
"homeId": "00000000-0000-0000-0000-000000000001",
"id": "3014F7110000000000000110",
"label": "Schrank",
"lastStatusUpdate": 1524513613922,
"liveUpdateState": "LIVE_UPDATE_NOT_SUPPORTED",
"manufacturerCode": 1,
"modelId": 262,
"modelType": "HMIP-PS",
"oem": "eQ-3",
"permanentlyReachable": true,
"serializedGlobalTradeItemNumber": "3014F7110000000000000110",
"type": "PLUGABLE_SWITCH",
"updateState": "UP_TO_DATE"
},
"3014F7110000000000000011": { "3014F7110000000000000011": {
"automaticValveAdaptionNeeded": false, "automaticValveAdaptionNeeded": false,
"availableFirmwareVersion": "2.0.2", "availableFirmwareVersion": "2.0.2",