mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Reorg and test attributes for HomematicIP Cloud (#28234)
* Reorg and test attribute for HomematicIP Cloud * Add dutyCycle check to security_group * Edit test to improve coverage * Add missing flow test * apply suggestion Co-Authored-By: Martin Hjelmare <marhje52@kth.se> * fix assert condition
This commit is contained in:
parent
6ac7796fb7
commit
75f94b9147
@ -39,7 +39,6 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice
|
||||
from .device import ATTR_GROUP_MEMBER_UNREACHABLE
|
||||
from .hap import HomematicipHAP
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -48,7 +47,6 @@ ATTR_ACCELERATION_SENSOR_MODE = "acceleration_sensor_mode"
|
||||
ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION = "acceleration_sensor_neutral_position"
|
||||
ATTR_ACCELERATION_SENSOR_SENSITIVITY = "acceleration_sensor_sensitivity"
|
||||
ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE = "acceleration_sensor_trigger_angle"
|
||||
ATTR_LOW_BATTERY = "low_battery"
|
||||
ATTR_MOISTURE_DETECTED = "moisture_detected"
|
||||
ATTR_MOTION_DETECTED = "motion_detected"
|
||||
ATTR_POWER_MAINS_FAILURE = "power_mains_failure"
|
||||
@ -59,12 +57,10 @@ ATTR_WATER_LEVEL_DETECTED = "water_level_detected"
|
||||
ATTR_WINDOW_STATE = "window_state"
|
||||
|
||||
GROUP_ATTRIBUTES = {
|
||||
"lowBat": ATTR_LOW_BATTERY,
|
||||
"moistureDetected": ATTR_MOISTURE_DETECTED,
|
||||
"motionDetected": ATTR_MOTION_DETECTED,
|
||||
"powerMainsFailure": ATTR_POWER_MAINS_FAILURE,
|
||||
"presenceDetected": ATTR_PRESENCE_DETECTED,
|
||||
"unreach": ATTR_GROUP_MEMBER_UNREACHABLE,
|
||||
"waterlevelDetected": ATTR_WATER_LEVEL_DETECTED,
|
||||
}
|
||||
|
||||
@ -408,17 +404,22 @@ class HomematicipSecuritySensorGroup(
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if safety issue detected."""
|
||||
parent_is_on = super().is_on
|
||||
if parent_is_on:
|
||||
return True
|
||||
|
||||
if (
|
||||
parent_is_on
|
||||
or self._device.powerMainsFailure
|
||||
self._device.powerMainsFailure
|
||||
or self._device.moistureDetected
|
||||
or self._device.waterlevelDetected
|
||||
or self._device.lowBat
|
||||
or self._device.dutyCycle
|
||||
):
|
||||
return True
|
||||
|
||||
if (
|
||||
self._device.smokeDetectorAlarmType is not None
|
||||
and self._device.smokeDetectorAlarmType != SmokeDetectorAlarmType.IDLE_OFF
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -15,6 +15,9 @@ from .hap import HomematicipHAP
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_MODEL_TYPE = "model_type"
|
||||
ATTR_LOW_BATTERY = "low_battery"
|
||||
ATTR_CONFIG_PENDING = "config_pending"
|
||||
ATTR_DUTY_CYCLE_REACHED = "duty_cycle_reached"
|
||||
ATTR_ID = "id"
|
||||
ATTR_IS_GROUP = "is_group"
|
||||
# RSSI HAP -> Device
|
||||
@ -26,27 +29,40 @@ ATTR_GROUP_MEMBER_UNREACHABLE = "group_member_unreachable"
|
||||
ATTR_DEVICE_OVERHEATED = "device_overheated"
|
||||
ATTR_DEVICE_OVERLOADED = "device_overloaded"
|
||||
ATTR_DEVICE_UNTERVOLTAGE = "device_undervoltage"
|
||||
ATTR_EVENT_DELAY = "event_delay"
|
||||
|
||||
DEVICE_ATTRIBUTE_ICONS = {
|
||||
"lowBat": "mdi:battery-outline",
|
||||
"sabotage": "mdi:alert",
|
||||
"sabotage": "mdi:shield-alert",
|
||||
"dutyCycle": "mdi:alert",
|
||||
"deviceOverheated": "mdi:alert",
|
||||
"deviceOverloaded": "mdi:alert",
|
||||
"deviceUndervoltage": "mdi:alert",
|
||||
"configPending": "mdi:alert-circle",
|
||||
}
|
||||
|
||||
DEVICE_ATTRIBUTES = {
|
||||
"modelType": ATTR_MODEL_TYPE,
|
||||
"sabotage": ATTR_SABOTAGE,
|
||||
"dutyCycle": ATTR_DUTY_CYCLE_REACHED,
|
||||
"rssiDeviceValue": ATTR_RSSI_DEVICE,
|
||||
"rssiPeerValue": ATTR_RSSI_PEER,
|
||||
"deviceOverheated": ATTR_DEVICE_OVERHEATED,
|
||||
"deviceOverloaded": ATTR_DEVICE_OVERLOADED,
|
||||
"deviceUndervoltage": ATTR_DEVICE_UNTERVOLTAGE,
|
||||
"configPending": ATTR_CONFIG_PENDING,
|
||||
"eventDelay": ATTR_EVENT_DELAY,
|
||||
"id": ATTR_ID,
|
||||
}
|
||||
|
||||
GROUP_ATTRIBUTES = {"modelType": ATTR_MODEL_TYPE}
|
||||
GROUP_ATTRIBUTES = {
|
||||
"modelType": ATTR_MODEL_TYPE,
|
||||
"lowBat": ATTR_LOW_BATTERY,
|
||||
"sabotage": ATTR_SABOTAGE,
|
||||
"dutyCycle": ATTR_DUTY_CYCLE_REACHED,
|
||||
"configPending": ATTR_CONFIG_PENDING,
|
||||
"unreach": ATTR_GROUP_MEMBER_UNREACHABLE,
|
||||
}
|
||||
|
||||
|
||||
class HomematicipGenericDevice(Entity):
|
||||
|
@ -39,12 +39,21 @@ from .hap import HomematicipHAP
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_CURRENT_ILLUMINATION = "current_illumination"
|
||||
ATTR_LOWEST_ILLUMINATION = "lowest_illumination"
|
||||
ATTR_HIGHEST_ILLUMINATION = "highest_illumination"
|
||||
ATTR_LEFT_COUNTER = "left_counter"
|
||||
ATTR_RIGHT_COUNTER = "right_counter"
|
||||
ATTR_TEMPERATURE_OFFSET = "temperature_offset"
|
||||
ATTR_WIND_DIRECTION = "wind_direction"
|
||||
ATTR_WIND_DIRECTION_VARIATION = "wind_direction_variation_in_degree"
|
||||
|
||||
ILLUMINATION_DEVICE_ATTRIBUTES = {
|
||||
"currentIllumination": ATTR_CURRENT_ILLUMINATION,
|
||||
"lowestIllumination": ATTR_LOWEST_ILLUMINATION,
|
||||
"highestIllumination": ATTR_HIGHEST_ILLUMINATION,
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||
"""Set up the HomematicIP Cloud sensors devices."""
|
||||
@ -273,6 +282,18 @@ class HomematicipIlluminanceSensor(HomematicipGenericDevice):
|
||||
"""Return the unit this state is expressed in."""
|
||||
return "lx"
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes of the wind speed sensor."""
|
||||
state_attr = super().device_state_attributes
|
||||
|
||||
for attr, attr_key in ILLUMINATION_DEVICE_ATTRIBUTES.items():
|
||||
attr_value = getattr(self._device, attr, None)
|
||||
if attr_value:
|
||||
state_attr[attr_key] = attr_value
|
||||
|
||||
return state_attr
|
||||
|
||||
|
||||
class HomematicipPowerSensor(HomematicipGenericDevice):
|
||||
"""Representation of a HomematicIP power measuring device."""
|
||||
|
@ -8,8 +8,19 @@ from homeassistant.components.homematicip_cloud.binary_sensor import (
|
||||
ATTR_ACCELERATION_SENSOR_NEUTRAL_POSITION,
|
||||
ATTR_ACCELERATION_SENSOR_SENSITIVITY,
|
||||
ATTR_ACCELERATION_SENSOR_TRIGGER_ANGLE,
|
||||
ATTR_LOW_BATTERY,
|
||||
ATTR_MOISTURE_DETECTED,
|
||||
ATTR_MOTION_DETECTED,
|
||||
ATTR_POWER_MAINS_FAILURE,
|
||||
ATTR_PRESENCE_DETECTED,
|
||||
ATTR_WATER_LEVEL_DETECTED,
|
||||
ATTR_WINDOW_STATE,
|
||||
)
|
||||
from homeassistant.components.homematicip_cloud.device import (
|
||||
ATTR_EVENT_DELAY,
|
||||
ATTR_GROUP_MEMBER_UNREACHABLE,
|
||||
ATTR_LOW_BATTERY,
|
||||
ATTR_RSSI_DEVICE,
|
||||
ATTR_SABOTAGE,
|
||||
)
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.setup import async_setup_component
|
||||
@ -105,6 +116,13 @@ async def test_hmip_shutter_contact(hass, default_mock_hap):
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == STATE_OFF
|
||||
|
||||
# test common attributes
|
||||
assert ha_state.attributes[ATTR_RSSI_DEVICE] == -54
|
||||
assert not ha_state.attributes.get(ATTR_SABOTAGE)
|
||||
await async_manipulate_test_data(hass, hmip_device, "sabotage", True)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.attributes[ATTR_SABOTAGE]
|
||||
|
||||
|
||||
async def test_hmip_motion_detector(hass, default_mock_hap):
|
||||
"""Test HomematicipMotionDetector."""
|
||||
@ -137,6 +155,11 @@ async def test_hmip_presence_detector(hass, default_mock_hap):
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == STATE_ON
|
||||
|
||||
assert not ha_state.attributes.get(ATTR_EVENT_DELAY)
|
||||
await async_manipulate_test_data(hass, hmip_device, "eventDelay", True)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.attributes[ATTR_EVENT_DELAY]
|
||||
|
||||
|
||||
async def test_hmip_smoke_detector(hass, default_mock_hap):
|
||||
"""Test HomematicipSmokeDetector."""
|
||||
@ -267,10 +290,25 @@ async def test_hmip_security_zone_sensor_group(hass, default_mock_hap):
|
||||
)
|
||||
|
||||
assert ha_state.state == STATE_OFF
|
||||
assert not ha_state.attributes.get(ATTR_MOTION_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_PRESENCE_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_GROUP_MEMBER_UNREACHABLE)
|
||||
assert not ha_state.attributes.get(ATTR_SABOTAGE)
|
||||
assert not ha_state.attributes.get(ATTR_WINDOW_STATE)
|
||||
|
||||
await async_manipulate_test_data(hass, hmip_device, "motionDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "presenceDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "unreach", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "sabotage", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "windowState", WindowState.OPEN)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
|
||||
assert ha_state.state == STATE_ON
|
||||
assert ha_state.attributes[ATTR_MOTION_DETECTED] is True
|
||||
assert ha_state.attributes[ATTR_MOTION_DETECTED]
|
||||
assert ha_state.attributes[ATTR_PRESENCE_DETECTED]
|
||||
assert ha_state.attributes[ATTR_GROUP_MEMBER_UNREACHABLE]
|
||||
assert ha_state.attributes[ATTR_SABOTAGE]
|
||||
assert ha_state.attributes[ATTR_WINDOW_STATE] == WindowState.OPEN
|
||||
|
||||
|
||||
async def test_hmip_security_sensor_group(hass, default_mock_hap):
|
||||
@ -283,14 +321,6 @@ async def test_hmip_security_sensor_group(hass, default_mock_hap):
|
||||
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,
|
||||
@ -299,7 +329,45 @@ async def test_hmip_security_sensor_group(hass, default_mock_hap):
|
||||
)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == STATE_ON
|
||||
|
||||
assert (
|
||||
ha_state.attributes["smoke_detector_alarm"]
|
||||
== SmokeDetectorAlarmType.PRIMARY_ALARM
|
||||
)
|
||||
await async_manipulate_test_data(
|
||||
hass, hmip_device, "smokeDetectorAlarmType", SmokeDetectorAlarmType.IDLE_OFF
|
||||
)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == STATE_OFF
|
||||
|
||||
assert not ha_state.attributes.get(ATTR_LOW_BATTERY)
|
||||
assert not ha_state.attributes.get(ATTR_MOTION_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_PRESENCE_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_POWER_MAINS_FAILURE)
|
||||
assert not ha_state.attributes.get(ATTR_MOISTURE_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_WATER_LEVEL_DETECTED)
|
||||
assert not ha_state.attributes.get(ATTR_GROUP_MEMBER_UNREACHABLE)
|
||||
assert not ha_state.attributes.get(ATTR_SABOTAGE)
|
||||
assert not ha_state.attributes.get(ATTR_WINDOW_STATE)
|
||||
|
||||
await async_manipulate_test_data(hass, hmip_device, "lowBat", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "motionDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "presenceDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "powerMainsFailure", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "moistureDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "waterlevelDetected", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "unreach", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "sabotage", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "windowState", WindowState.OPEN)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
|
||||
assert ha_state.state == STATE_ON
|
||||
assert ha_state.attributes[ATTR_LOW_BATTERY]
|
||||
assert ha_state.attributes[ATTR_MOTION_DETECTED]
|
||||
assert ha_state.attributes[ATTR_PRESENCE_DETECTED]
|
||||
assert ha_state.attributes[ATTR_POWER_MAINS_FAILURE]
|
||||
assert ha_state.attributes[ATTR_MOISTURE_DETECTED]
|
||||
assert ha_state.attributes[ATTR_WATER_LEVEL_DETECTED]
|
||||
assert ha_state.attributes[ATTR_GROUP_MEMBER_UNREACHABLE]
|
||||
assert ha_state.attributes[ATTR_SABOTAGE]
|
||||
assert ha_state.attributes[ATTR_WINDOW_STATE] == WindowState.OPEN
|
||||
|
@ -98,6 +98,15 @@ async def test_init_flow_show_form(hass):
|
||||
assert result["type"] == "form"
|
||||
|
||||
|
||||
async def test_init_flow_user_show_form(hass):
|
||||
"""Test config flow shows up with a form."""
|
||||
flow = config_flow.HomematicipCloudFlowHandler()
|
||||
flow.hass = hass
|
||||
|
||||
result = await flow.async_step_user(user_input=None)
|
||||
assert result["type"] == "form"
|
||||
|
||||
|
||||
async def test_init_already_configured(hass):
|
||||
"""Test accesspoint is already configured."""
|
||||
MockConfigEntry(
|
||||
|
@ -2,8 +2,20 @@
|
||||
from homematicip.base.enums import ValveState
|
||||
|
||||
from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN
|
||||
from homeassistant.components.homematicip_cloud.device import (
|
||||
ATTR_CONFIG_PENDING,
|
||||
ATTR_DEVICE_OVERHEATED,
|
||||
ATTR_DEVICE_OVERLOADED,
|
||||
ATTR_DEVICE_UNTERVOLTAGE,
|
||||
ATTR_DUTY_CYCLE_REACHED,
|
||||
ATTR_RSSI_DEVICE,
|
||||
ATTR_RSSI_PEER,
|
||||
)
|
||||
from homeassistant.components.homematicip_cloud.sensor import (
|
||||
ATTR_CURRENT_ILLUMINATION,
|
||||
ATTR_HIGHEST_ILLUMINATION,
|
||||
ATTR_LEFT_COUNTER,
|
||||
ATTR_LOWEST_ILLUMINATION,
|
||||
ATTR_RIGHT_COUNTER,
|
||||
ATTR_TEMPERATURE_OFFSET,
|
||||
ATTR_WIND_DIRECTION,
|
||||
@ -92,6 +104,9 @@ async def test_hmip_humidity_sensor(hass, default_mock_hap):
|
||||
await async_manipulate_test_data(hass, hmip_device, "humidity", 45)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == "45"
|
||||
# test common attributes
|
||||
assert ha_state.attributes[ATTR_RSSI_DEVICE] == -76
|
||||
assert ha_state.attributes[ATTR_RSSI_PEER] == -77
|
||||
|
||||
|
||||
async def test_hmip_temperature_sensor1(hass, default_mock_hap):
|
||||
@ -153,6 +168,23 @@ async def test_hmip_power_sensor(hass, default_mock_hap):
|
||||
await async_manipulate_test_data(hass, hmip_device, "currentPowerConsumption", 23.5)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == "23.5"
|
||||
# test common attributes
|
||||
assert not ha_state.attributes.get(ATTR_DEVICE_OVERHEATED)
|
||||
assert not ha_state.attributes.get(ATTR_DEVICE_OVERLOADED)
|
||||
assert not ha_state.attributes.get(ATTR_DEVICE_UNTERVOLTAGE)
|
||||
assert not ha_state.attributes.get(ATTR_DUTY_CYCLE_REACHED)
|
||||
assert not ha_state.attributes.get(ATTR_CONFIG_PENDING)
|
||||
await async_manipulate_test_data(hass, hmip_device, "deviceOverheated", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "deviceOverloaded", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "deviceUndervoltage", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "dutyCycle", True)
|
||||
await async_manipulate_test_data(hass, hmip_device, "configPending", True)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.attributes[ATTR_DEVICE_OVERHEATED]
|
||||
assert ha_state.attributes[ATTR_DEVICE_OVERLOADED]
|
||||
assert ha_state.attributes[ATTR_DEVICE_UNTERVOLTAGE]
|
||||
assert ha_state.attributes[ATTR_DUTY_CYCLE_REACHED]
|
||||
assert ha_state.attributes[ATTR_CONFIG_PENDING]
|
||||
|
||||
|
||||
async def test_hmip_illuminance_sensor1(hass, default_mock_hap):
|
||||
@ -187,6 +219,9 @@ async def test_hmip_illuminance_sensor2(hass, default_mock_hap):
|
||||
await async_manipulate_test_data(hass, hmip_device, "averageIllumination", 231)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.state == "231"
|
||||
assert ha_state.attributes[ATTR_CURRENT_ILLUMINATION] == 785.2
|
||||
assert ha_state.attributes[ATTR_HIGHEST_ILLUMINATION] == 837.1
|
||||
assert ha_state.attributes[ATTR_LOWEST_ILLUMINATION] == 785.2
|
||||
|
||||
|
||||
async def test_hmip_windspeed_sensor(hass, default_mock_hap):
|
||||
|
@ -136,7 +136,7 @@ async def test_hmip_group_switch(hass, default_mock_hap):
|
||||
assert not ha_state.attributes.get(ATTR_GROUP_MEMBER_UNREACHABLE)
|
||||
await async_manipulate_test_data(hass, hmip_device, "unreach", True)
|
||||
ha_state = hass.states.get(entity_id)
|
||||
assert ha_state.attributes[ATTR_GROUP_MEMBER_UNREACHABLE] is True
|
||||
assert ha_state.attributes[ATTR_GROUP_MEMBER_UNREACHABLE]
|
||||
|
||||
|
||||
async def test_hmip_multi_switch(hass, default_mock_hap):
|
||||
|
Loading…
x
Reference in New Issue
Block a user