From 9d67c9feb6d1e23e4150ae15fa0b8073073cbc22 Mon Sep 17 00:00:00 2001 From: Markus Jankowski Date: Fri, 26 Apr 2019 00:13:07 +0200 Subject: [PATCH] Add Types to Homematic IP (#23401) --- .../components/homematicip_cloud/__init__.py | 7 +- .../homematicip_cloud/alarm_control_panel.py | 10 ++- .../homematicip_cloud/binary_sensor.py | 59 +++++++++------- .../components/homematicip_cloud/climate.py | 28 ++++---- .../homematicip_cloud/config_flow.py | 6 +- .../components/homematicip_cloud/cover.py | 10 ++- .../components/homematicip_cloud/device.py | 15 ++-- .../components/homematicip_cloud/hap.py | 10 +-- .../components/homematicip_cloud/light.py | 39 ++++++----- .../components/homematicip_cloud/sensor.py | 70 ++++++++++--------- .../components/homematicip_cloud/switch.py | 26 ++++--- .../components/homematicip_cloud/weather.py | 24 ++++--- 12 files changed, 174 insertions(+), 130 deletions(-) diff --git a/homeassistant/components/homematicip_cloud/__init__.py b/homeassistant/components/homematicip_cloud/__init__.py index 4a24120be95..550ba43950b 100644 --- a/homeassistant/components/homematicip_cloud/__init__.py +++ b/homeassistant/components/homematicip_cloud/__init__.py @@ -4,9 +4,12 @@ import logging import voluptuous as vol from homeassistant import config_entries +from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_NAME +from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.typing import ConfigType from .config_flow import configured_haps from .const import ( @@ -26,7 +29,7 @@ CONFIG_SCHEMA = vol.Schema({ }, extra=vol.ALLOW_EXTRA) -async def async_setup(hass, config): +async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: """Set up the HomematicIP Cloud component.""" hass.data[DOMAIN] = {} @@ -46,7 +49,7 @@ async def async_setup(hass, config): return True -async def async_setup_entry(hass, entry): +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up an access point from a config entry.""" hap = HomematicipHAP(hass, entry) hapid = entry.data[HMIPC_HAPID].replace('-', '').upper() diff --git a/homeassistant/components/homematicip_cloud/alarm_control_panel.py b/homeassistant/components/homematicip_cloud/alarm_control_panel.py index 1326e46d7d3..c2ad23700f3 100644 --- a/homeassistant/components/homematicip_cloud/alarm_control_panel.py +++ b/homeassistant/components/homematicip_cloud/alarm_control_panel.py @@ -2,12 +2,15 @@ import logging from homematicip.aio.group import AsyncSecurityZoneGroup +from homematicip.aio.home import AsyncHome from homematicip.base.enums import WindowState from homeassistant.components.alarm_control_panel import AlarmControlPanel +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED) +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -20,7 +23,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP alrm control panel from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -35,14 +39,14 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipSecurityZone(HomematicipGenericDevice, AlarmControlPanel): """Representation of an HomematicIP Cloud security zone group.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the security zone group.""" device.modelType = 'Group-SecurityZone' device.windowState = None super().__init__(home, device) @property - def state(self): + def state(self) -> str: """Return the state of the device.""" if self._device.active: if (self._device.sabotage or self._device.motionDetected or diff --git a/homeassistant/components/homematicip_cloud/binary_sensor.py b/homeassistant/components/homematicip_cloud/binary_sensor.py index dee43e3f367..19d35c47cdb 100644 --- a/homeassistant/components/homematicip_cloud/binary_sensor.py +++ b/homeassistant/components/homematicip_cloud/binary_sensor.py @@ -7,9 +7,12 @@ from homematicip.aio.device import ( AsyncShutterContact, AsyncSmokeDetector, AsyncWaterSensor, AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro) from homematicip.aio.group import AsyncSecurityGroup, AsyncSecurityZoneGroup +from homematicip.aio.home import AsyncHome from homematicip.base.enums import SmokeDetectorAlarmType, WindowState from homeassistant.components.binary_sensor import BinarySensorDevice +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from .device import ATTR_GROUP_MEMBER_UNREACHABLE @@ -32,7 +35,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP Cloud binary sensor from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -71,12 +75,12 @@ class HomematicipShutterContact(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud shutter contact.""" @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'door' @property - def is_on(self): + def is_on(self) -> bool: """Return true if the shutter contact is on/open.""" if hasattr(self._device, 'sabotage') and self._device.sabotage: return True @@ -89,12 +93,12 @@ class HomematicipMotionDetector(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud motion detector.""" @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'motion' @property - def is_on(self): + def is_on(self) -> bool: """Return true if motion is detected.""" if hasattr(self._device, 'sabotage') and self._device.sabotage: return True @@ -105,12 +109,12 @@ class HomematicipSmokeDetector(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud smoke detector.""" @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'smoke' @property - def is_on(self): + def is_on(self) -> bool: """Return true if smoke is detected.""" return (self._device.smokeDetectorAlarmType != SmokeDetectorAlarmType.IDLE_OFF) @@ -120,12 +124,12 @@ class HomematicipWaterDetector(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud water detector.""" @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'moisture' @property - def is_on(self): + def is_on(self) -> bool: """Return true, if moisture or waterlevel is detected.""" return self._device.moistureDetected or self._device.waterlevelDetected @@ -133,17 +137,17 @@ class HomematicipWaterDetector(HomematicipGenericDevice, BinarySensorDevice): class HomematicipStormSensor(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud storm sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize storm sensor.""" super().__init__(home, device, "Storm") @property - def icon(self): + def icon(self) -> str: """Return the icon.""" return 'mdi:weather-windy' if self.is_on else 'mdi:pinwheel-outline' @property - def is_on(self): + def is_on(self) -> bool: """Return true, if storm is detected.""" return self._device.storm @@ -151,17 +155,17 @@ class HomematicipStormSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipRainSensor(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud rain sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize rain sensor.""" super().__init__(home, device, "Raining") @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'moisture' @property - def is_on(self): + def is_on(self) -> bool: """Return true, if it is raining.""" return self._device.raining @@ -169,17 +173,17 @@ class HomematicipRainSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipSunshineSensor(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud sunshine sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize sunshine sensor.""" super().__init__(home, device, 'Sunshine') @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'light' @property - def is_on(self): + def is_on(self) -> bool: """Return true if sun is shining.""" return self._device.sunshine @@ -197,17 +201,17 @@ class HomematicipSunshineSensor(HomematicipGenericDevice, BinarySensorDevice): class HomematicipBatterySensor(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud low battery sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize battery sensor.""" super().__init__(home, device, 'Battery') @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'battery' @property - def is_on(self): + def is_on(self) -> bool: """Return true if battery is low.""" return self._device.lowBat @@ -216,18 +220,19 @@ class HomematicipSecurityZoneSensorGroup(HomematicipGenericDevice, BinarySensorDevice): """Representation of a HomematicIP Cloud security zone group.""" - def __init__(self, home, device, post='SecurityZone'): + def __init__(self, home: AsyncHome, device, + post: str = 'SecurityZone') -> None: """Initialize security zone group.""" device.modelType = 'HmIP-{}'.format(post) super().__init__(home, device, post) @property - def device_class(self): + def device_class(self) -> str: """Return the class of this sensor.""" return 'safety' @property - def available(self): + def available(self) -> bool: """Security-Group available.""" # A security-group must be available, and should not be affected by # the individual availability of group members. @@ -251,7 +256,7 @@ class HomematicipSecurityZoneSensorGroup(HomematicipGenericDevice, return attr @property - def is_on(self): + def is_on(self) -> bool: """Return true if security issue detected.""" if self._device.motionDetected or \ self._device.presenceDetected or \ @@ -269,7 +274,7 @@ class HomematicipSecuritySensorGroup(HomematicipSecurityZoneSensorGroup, BinarySensorDevice): """Representation of a HomematicIP security group.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize security group.""" super().__init__(home, device, 'Sensors') @@ -294,7 +299,7 @@ class HomematicipSecuritySensorGroup(HomematicipSecurityZoneSensorGroup, return attr @property - def is_on(self): + def is_on(self) -> bool: """Return true if safety issue detected.""" parent_is_on = super().is_on if parent_is_on or \ diff --git a/homeassistant/components/homematicip_cloud/climate.py b/homeassistant/components/homematicip_cloud/climate.py index 8a2ad8738df..3170fc149d5 100644 --- a/homeassistant/components/homematicip_cloud/climate.py +++ b/homeassistant/components/homematicip_cloud/climate.py @@ -1,12 +1,15 @@ """Support for HomematicIP Cloud climate devices.""" import logging -from homematicip.group import HeatingGroup +from homematicip.aio.group import AsyncHeatingGroup +from homematicip.aio.home import AsyncHome from homeassistant.components.climate import ClimateDevice from homeassistant.components.climate.const import ( STATE_AUTO, STATE_MANUAL, SUPPORT_TARGET_TEMPERATURE) +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -26,12 +29,13 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP climate from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] for device in home.groups: - if isinstance(device, HeatingGroup): + if isinstance(device, AsyncHeatingGroup): devices.append(HomematicipHeatingGroup(home, device)) if devices: @@ -41,48 +45,48 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipHeatingGroup(HomematicipGenericDevice, ClimateDevice): """Representation of a HomematicIP heating group.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize heating group.""" device.modelType = 'Group-Heating' super().__init__(home, device) @property - def temperature_unit(self): + def temperature_unit(self) -> str: """Return the unit of measurement.""" return TEMP_CELSIUS @property - def supported_features(self): + def supported_features(self) -> int: """Return the list of supported features.""" return SUPPORT_TARGET_TEMPERATURE @property - def target_temperature(self): + def target_temperature(self) -> float: """Return the temperature we try to reach.""" return self._device.setPointTemperature @property - def current_temperature(self): + def current_temperature(self) -> float: """Return the current temperature.""" return self._device.actualTemperature @property - def current_humidity(self): + def current_humidity(self) -> int: """Return the current humidity.""" return self._device.humidity @property - def current_operation(self): + def current_operation(self) -> str: """Return current operation ie. automatic or manual.""" return HMIP_STATE_TO_HA.get(self._device.controlMode) @property - def min_temp(self): + def min_temp(self) -> float: """Return the minimum temperature.""" return self._device.minTemperature @property - def max_temp(self): + def max_temp(self) -> float: """Return the maximum temperature.""" return self._device.maxTemperature diff --git a/homeassistant/components/homematicip_cloud/config_flow.py b/homeassistant/components/homematicip_cloud/config_flow.py index 458186bcce1..696425df5b5 100644 --- a/homeassistant/components/homematicip_cloud/config_flow.py +++ b/homeassistant/components/homematicip_cloud/config_flow.py @@ -1,8 +1,10 @@ """Config flow to configure the HomematicIP Cloud component.""" +from typing import Set + import voluptuous as vol from homeassistant import config_entries -from homeassistant.core import callback +from homeassistant.core import HomeAssistant, callback from .const import ( _LOGGER, DOMAIN as HMIPC_DOMAIN, HMIPC_AUTHTOKEN, HMIPC_HAPID, HMIPC_NAME, @@ -11,7 +13,7 @@ from .hap import HomematicipAuth @callback -def configured_haps(hass): +def configured_haps(hass: HomeAssistant) -> Set[str]: """Return a set of the configured access points.""" return set(entry.data[HMIPC_HAPID] for entry in hass.config_entries.async_entries(HMIPC_DOMAIN)) diff --git a/homeassistant/components/homematicip_cloud/cover.py b/homeassistant/components/homematicip_cloud/cover.py index 381bcf1980e..fc75d78119d 100644 --- a/homeassistant/components/homematicip_cloud/cover.py +++ b/homeassistant/components/homematicip_cloud/cover.py @@ -1,9 +1,12 @@ """Support for HomematicIP Cloud cover devices.""" import logging +from typing import Optional from homematicip.aio.device import AsyncFullFlushShutter from homeassistant.components.cover import ATTR_POSITION, CoverDevice +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -19,7 +22,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP cover from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -35,7 +39,7 @@ class HomematicipCoverShutter(HomematicipGenericDevice, CoverDevice): """Representation of a HomematicIP Cloud cover device.""" @property - def current_cover_position(self): + def current_cover_position(self) -> int: """Return current position of cover.""" return int((1 - self._device.shutterLevel) * 100) @@ -47,7 +51,7 @@ class HomematicipCoverShutter(HomematicipGenericDevice, CoverDevice): await self._device.set_shutter_level(level) @property - def is_closed(self): + def is_closed(self) -> Optional[bool]: """Return if the cover is closed.""" if self._device.shutterLevel is not None: return self._device.shutterLevel == HMIP_COVER_CLOSED diff --git a/homeassistant/components/homematicip_cloud/device.py b/homeassistant/components/homematicip_cloud/device.py index f6da8b27cf7..6bbbb8b4fab 100644 --- a/homeassistant/components/homematicip_cloud/device.py +++ b/homeassistant/components/homematicip_cloud/device.py @@ -1,7 +1,9 @@ """Generic device for the HomematicIP Cloud component.""" import logging +from typing import Optional from homematicip.aio.device import AsyncDevice +from homematicip.aio.home import AsyncHome from homeassistant.components import homematicip_cloud from homeassistant.helpers.entity import Entity @@ -21,7 +23,8 @@ ATTR_GROUP_MEMBER_UNREACHABLE = 'group_member_unreachable' class HomematicipGenericDevice(Entity): """Representation of an HomematicIP generic device.""" - def __init__(self, home, device, post=None): + def __init__(self, home: AsyncHome, device, + post: Optional[str] = None) -> None: """Initialize the generic device.""" self._home = home self._device = device @@ -56,7 +59,7 @@ class HomematicipGenericDevice(Entity): self.async_schedule_update_ha_state() @property - def name(self): + def name(self) -> str: """Return the name of the generic device.""" name = self._device.label if self._home.name is not None and self._home.name != '': @@ -66,22 +69,22 @@ class HomematicipGenericDevice(Entity): return name @property - def should_poll(self): + def should_poll(self) -> bool: """No polling needed.""" return False @property - def available(self): + def available(self) -> bool: """Device available.""" return not self._device.unreach @property - def unique_id(self): + def unique_id(self) -> str: """Return a unique ID.""" return "{}_{}".format(self.__class__.__name__, self._device.id) @property - def icon(self): + def icon(self) -> Optional[str]: """Return the icon.""" if hasattr(self._device, 'lowBat') and self._device.lowBat: return 'mdi:battery-outline' diff --git a/homeassistant/components/homematicip_cloud/hap.py b/homeassistant/components/homematicip_cloud/hap.py index 99e98b5a1d2..b3731bc9f1a 100644 --- a/homeassistant/components/homematicip_cloud/hap.py +++ b/homeassistant/components/homematicip_cloud/hap.py @@ -6,7 +6,8 @@ from homematicip.aio.auth import AsyncAuth from homematicip.aio.home import AsyncHome from homematicip.base.base_connection import HmipConnectionError -from homeassistant.core import callback +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers.aiohttp_client import async_get_clientsession @@ -70,7 +71,7 @@ class HomematicipAuth: class HomematicipHAP: """Manages HomematicIP HTTP and WebSocket connection.""" - def __init__(self, hass, config_entry): + def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None: """Initialize HomematicIP Cloud connection.""" self.hass = hass self.config_entry = config_entry @@ -81,7 +82,7 @@ class HomematicipHAP: self._tries = 0 self._accesspoint_connected = True - async def async_setup(self, tries=0): + async def async_setup(self, tries: int = 0): """Initialize connection.""" try: self.home = await self.get_hap( @@ -196,7 +197,8 @@ class HomematicipHAP: self.config_entry, component) return True - async def get_hap(self, hass, hapid, authtoken, name) -> AsyncHome: + async def get_hap(self, hass: HomeAssistant, hapid: str, authtoken: str, + name: str) -> AsyncHome: """Create a HomematicIP access point object.""" home = AsyncHome(hass.loop, async_get_clientsession(hass)) diff --git a/homeassistant/components/homematicip_cloud/light.py b/homeassistant/components/homematicip_cloud/light.py index f4f73104f7c..7cfbae95a33 100644 --- a/homeassistant/components/homematicip_cloud/light.py +++ b/homeassistant/components/homematicip_cloud/light.py @@ -2,14 +2,18 @@ import logging from homematicip.aio.device import ( - AsyncBrandSwitchMeasuring, AsyncDimmer, AsyncPluggableDimmer, - AsyncBrandDimmer, AsyncFullFlushDimmer, - AsyncBrandSwitchNotificationLight) + AsyncBrandDimmer, AsyncBrandSwitchMeasuring, + AsyncBrandSwitchNotificationLight, AsyncDimmer, AsyncFullFlushDimmer, + AsyncPluggableDimmer) +from homematicip.aio.home import AsyncHome from homematicip.base.enums import RGBColorState +from homematicip.base.functionalChannels import NotificationLightChannel from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_NAME, ATTR_HS_COLOR, SUPPORT_BRIGHTNESS, SUPPORT_COLOR, Light) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -25,7 +29,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP Cloud lights from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -50,12 +55,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipLight(HomematicipGenericDevice, Light): """Representation of a HomematicIP Cloud light device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the light device.""" super().__init__(home, device) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._device.on @@ -85,25 +90,25 @@ class HomematicipLightMeasuring(HomematicipLight): class HomematicipDimmer(HomematicipGenericDevice, Light): """Representation of HomematicIP Cloud dimmer light device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the dimmer light device.""" super().__init__(home, device) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._device.dimLevel is not None and \ self._device.dimLevel > 0.0 @property - def brightness(self): + def brightness(self) -> int: """Return the brightness of this light between 0..255.""" if self._device.dimLevel: return int(self._device.dimLevel*255) return 0 @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" return SUPPORT_BRIGHTNESS @@ -122,7 +127,7 @@ class HomematicipDimmer(HomematicipGenericDevice, Light): class HomematicipNotificationLight(HomematicipGenericDevice, Light): """Representation of HomematicIP Cloud dimmer light device.""" - def __init__(self, home, device, channel): + def __init__(self, home: AsyncHome, device, channel: int) -> None: """Initialize the dimmer light device.""" self.channel = channel if self.channel == 2: @@ -141,24 +146,24 @@ class HomematicipNotificationLight(HomematicipGenericDevice, Light): } @property - def _func_channel(self): + def _func_channel(self) -> NotificationLightChannel: return self._device.functionalChannels[self.channel] @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._func_channel.dimLevel is not None and \ self._func_channel.dimLevel > 0.0 @property - def brightness(self): + def brightness(self) -> int: """Return the brightness of this light between 0..255.""" if self._func_channel.dimLevel: return int(self._func_channel.dimLevel * 255) return 0 @property - def hs_color(self): + def hs_color(self) -> tuple: """Return the hue and saturation color value [float, float].""" simple_rgb_color = self._func_channel.simpleRGBColorState return self._color_switcher.get(simple_rgb_color, [0.0, 0.0]) @@ -172,12 +177,12 @@ class HomematicipNotificationLight(HomematicipGenericDevice, Light): return attr @property - def name(self): + def name(self) -> str: """Return the name of the generic device.""" return "{} {}".format(super().name, 'Notification') @property - def supported_features(self): + def supported_features(self) -> int: """Flag supported features.""" return SUPPORT_BRIGHTNESS | SUPPORT_COLOR diff --git a/homeassistant/components/homematicip_cloud/sensor.py b/homeassistant/components/homematicip_cloud/sensor.py index 4816eacd08f..3d91b25c2bd 100644 --- a/homeassistant/components/homematicip_cloud/sensor.py +++ b/homeassistant/components/homematicip_cloud/sensor.py @@ -10,11 +10,14 @@ from homematicip.aio.device import ( AsyncTemperatureHumiditySensorOutdoor, AsyncTemperatureHumiditySensorWithoutDisplay, AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro) +from homematicip.aio.home import AsyncHome from homematicip.base.enums import ValveState +from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_POWER, DEVICE_CLASS_TEMPERATURE, POWER_WATT, TEMP_CELSIUS) +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -31,7 +34,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP Cloud sensors from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [HomematicipAccesspointStatus(home)] @@ -74,7 +78,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipAccesspointStatus(HomematicipGenericDevice): """Representation of an HomeMaticIP Cloud access point.""" - def __init__(self, home): + def __init__(self, home: AsyncHome) -> None: """Initialize access point device.""" super().__init__(home, home) @@ -90,22 +94,22 @@ class HomematicipAccesspointStatus(HomematicipGenericDevice): } @property - def icon(self): + def icon(self) -> str: """Return the icon of the access point device.""" return 'mdi:access-point-network' @property - def state(self): + def state(self) -> float: """Return the state of the access point.""" return self._home.dutyCycle @property - def available(self): + def available(self) -> bool: """Device available.""" return self._home.connected @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return '%' @@ -113,12 +117,12 @@ class HomematicipAccesspointStatus(HomematicipGenericDevice): class HomematicipHeatingThermostat(HomematicipGenericDevice): """Represenation of a HomematicIP heating thermostat device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize heating thermostat device.""" super().__init__(home, device, 'Heating') @property - def icon(self): + def icon(self) -> str: """Return the icon.""" if super().icon: return super().icon @@ -127,14 +131,14 @@ class HomematicipHeatingThermostat(HomematicipGenericDevice): return 'mdi:radiator' @property - def state(self): + def state(self) -> int: """Return the state of the radiator valve.""" if self._device.valveState != ValveState.ADAPTION_DONE: return self._device.valveState return round(self._device.valvePosition*100) @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return '%' @@ -142,22 +146,22 @@ class HomematicipHeatingThermostat(HomematicipGenericDevice): class HomematicipHumiditySensor(HomematicipGenericDevice): """Represenation of a HomematicIP Cloud humidity device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the thermometer device.""" super().__init__(home, device, 'Humidity') @property - def device_class(self): + def device_class(self) -> str: """Return the device class of the sensor.""" return DEVICE_CLASS_HUMIDITY @property - def state(self): + def state(self) -> int: """Return the state.""" return self._device.humidity @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return '%' @@ -165,17 +169,17 @@ class HomematicipHumiditySensor(HomematicipGenericDevice): class HomematicipTemperatureSensor(HomematicipGenericDevice): """Representation of a HomematicIP Cloud thermometer device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the thermometer device.""" super().__init__(home, device, 'Temperature') @property - def device_class(self): + def device_class(self) -> str: """Return the device class of the sensor.""" return DEVICE_CLASS_TEMPERATURE @property - def state(self): + def state(self) -> float: """Return the state.""" if hasattr(self._device, 'valveActualTemperature'): return self._device.valveActualTemperature @@ -183,7 +187,7 @@ class HomematicipTemperatureSensor(HomematicipGenericDevice): return self._device.actualTemperature @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return TEMP_CELSIUS @@ -200,17 +204,17 @@ class HomematicipTemperatureSensor(HomematicipGenericDevice): class HomematicipIlluminanceSensor(HomematicipGenericDevice): """Represenation of a HomematicIP Illuminance device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the device.""" super().__init__(home, device, 'Illuminance') @property - def device_class(self): + def device_class(self) -> str: """Return the device class of the sensor.""" return DEVICE_CLASS_ILLUMINANCE @property - def state(self): + def state(self) -> float: """Return the state.""" if hasattr(self._device, 'averageIllumination'): return self._device.averageIllumination @@ -218,7 +222,7 @@ class HomematicipIlluminanceSensor(HomematicipGenericDevice): return self._device.illumination @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return 'lx' @@ -226,22 +230,22 @@ class HomematicipIlluminanceSensor(HomematicipGenericDevice): class HomematicipPowerSensor(HomematicipGenericDevice): """Represenation of a HomematicIP power measuring device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the device.""" super().__init__(home, device, 'Power') @property - def device_class(self): + def device_class(self) -> str: """Return the device class of the sensor.""" return DEVICE_CLASS_POWER @property - def state(self): + def state(self) -> float: """Represenation of the HomematicIP power comsumption value.""" return self._device.currentPowerConsumption @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return POWER_WATT @@ -249,17 +253,17 @@ class HomematicipPowerSensor(HomematicipGenericDevice): class HomematicipWindspeedSensor(HomematicipGenericDevice): """Represenation of a HomematicIP wind speed sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the device.""" super().__init__(home, device, 'Windspeed') @property - def state(self): + def state(self) -> float: """Represenation of the HomematicIP wind speed value.""" return self._device.windSpeed @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return 'km/h' @@ -281,22 +285,22 @@ class HomematicipWindspeedSensor(HomematicipGenericDevice): class HomematicipTodayRainSensor(HomematicipGenericDevice): """Represenation of a HomematicIP rain counter of a day sensor.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the device.""" super().__init__(home, device, 'Today Rain') @property - def state(self): + def state(self) -> float: """Represenation of the HomematicIP todays rain value.""" return round(self._device.todayRainCounter, 2) @property - def unit_of_measurement(self): + def unit_of_measurement(self) -> str: """Return the unit this state is expressed in.""" return 'mm' -def _get_wind_direction(wind_direction_degree) -> str: +def _get_wind_direction(wind_direction_degree: float) -> str: """Convert wind direction degree to named direction.""" if 11.25 <= wind_direction_degree < 33.75: return 'NNE' diff --git a/homeassistant/components/homematicip_cloud/switch.py b/homeassistant/components/homematicip_cloud/switch.py index 9a0d48ac253..7b87f6c740e 100644 --- a/homeassistant/components/homematicip_cloud/switch.py +++ b/homeassistant/components/homematicip_cloud/switch.py @@ -6,8 +6,11 @@ from homematicip.aio.device import ( AsyncOpenCollector8Module, AsyncPlugableSwitch, AsyncPlugableSwitchMeasuring) from homematicip.aio.group import AsyncSwitchingGroup +from homematicip.aio.home import AsyncHome from homeassistant.components.switch import SwitchDevice +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice from .device import ATTR_GROUP_MEMBER_UNREACHABLE @@ -21,7 +24,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP switch from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -55,12 +59,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipSwitch(HomematicipGenericDevice, SwitchDevice): """representation of a HomematicIP Cloud switch device.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the switch device.""" super().__init__(home, device) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._device.on @@ -76,18 +80,18 @@ class HomematicipSwitch(HomematicipGenericDevice, SwitchDevice): class HomematicipGroupSwitch(HomematicipGenericDevice, SwitchDevice): """representation of a HomematicIP switching group.""" - def __init__(self, home, device, post='Group'): + def __init__(self, home: AsyncHome, device, post: str = 'Group') -> None: """Initialize switching group.""" device.modelType = 'HmIP-{}'.format(post) super().__init__(home, device, post) @property - def is_on(self): + def is_on(self) -> bool: """Return true if group is on.""" return self._device.on @property - def available(self): + def available(self) -> bool: """Switch-Group available.""" # A switch-group must be available, and should not be affected by the # individual availability of group members. @@ -116,12 +120,12 @@ class HomematicipSwitchMeasuring(HomematicipSwitch): """Representation of a HomematicIP measuring switch device.""" @property - def current_power_w(self): + def current_power_w(self) -> float: """Return the current power usage in W.""" return self._device.currentPowerConsumption @property - def today_energy_kwh(self): + def today_energy_kwh(self) -> int: """Return the today total energy usage in kWh.""" if self._device.energyCounter is None: return 0 @@ -131,19 +135,19 @@ class HomematicipSwitchMeasuring(HomematicipSwitch): class HomematicipMultiSwitch(HomematicipGenericDevice, SwitchDevice): """Representation of a HomematicIP Cloud multi switch device.""" - def __init__(self, home, device, channel): + def __init__(self, home: AsyncHome, device, channel: int): """Initialize the multi switch device.""" self.channel = channel super().__init__(home, device, 'Channel{}'.format(channel)) @property - def unique_id(self): + def unique_id(self) -> str: """Return a unique ID.""" return "{}_{}_{}".format(self.__class__.__name__, self.post, self._device.id) @property - def is_on(self): + def is_on(self) -> bool: """Return true if device is on.""" return self._device.functionalChannels[self.channel].on diff --git a/homeassistant/components/homematicip_cloud/weather.py b/homeassistant/components/homematicip_cloud/weather.py index 9c7d843b448..b97948b2d9f 100644 --- a/homeassistant/components/homematicip_cloud/weather.py +++ b/homeassistant/components/homematicip_cloud/weather.py @@ -4,9 +4,12 @@ import logging from homematicip.aio.device import ( AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro) +from homematicip.aio.home import AsyncHome from homeassistant.components.weather import WeatherEntity +from homeassistant.config_entries import ConfigEntry from homeassistant.const import TEMP_CELSIUS +from homeassistant.core import HomeAssistant from . import DOMAIN as HMIPC_DOMAIN, HMIPC_HAPID, HomematicipGenericDevice @@ -19,7 +22,8 @@ async def async_setup_platform( pass -async def async_setup_entry(hass, config_entry, async_add_entities): +async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, + async_add_entities) -> None: """Set up the HomematicIP weather sensor from a config entry.""" home = hass.data[HMIPC_DOMAIN][config_entry.data[HMIPC_HAPID]].home devices = [] @@ -36,42 +40,42 @@ async def async_setup_entry(hass, config_entry, async_add_entities): class HomematicipWeatherSensor(HomematicipGenericDevice, WeatherEntity): """representation of a HomematicIP Cloud weather sensor plus & basic.""" - def __init__(self, home, device): + def __init__(self, home: AsyncHome, device) -> None: """Initialize the weather sensor.""" super().__init__(home, device) @property - def name(self): + def name(self) -> str: """Return the name of the sensor.""" return self._device.label @property - def temperature(self): + def temperature(self) -> float: """Return the platform temperature.""" return self._device.actualTemperature @property - def temperature_unit(self): + def temperature_unit(self) -> str: """Return the unit of measurement.""" return TEMP_CELSIUS @property - def humidity(self): + def humidity(self) -> int: """Return the humidity.""" return self._device.humidity @property - def wind_speed(self): + def wind_speed(self) -> float: """Return the wind speed.""" return self._device.windSpeed @property - def attribution(self): + def attribution(self) -> str: """Return the attribution.""" return "Powered by Homematic IP" @property - def condition(self): + def condition(self) -> str: """Return the current condition.""" if hasattr(self._device, "raining") and self._device.raining: return 'rainy' @@ -86,6 +90,6 @@ class HomematicipWeatherSensorPro(HomematicipWeatherSensor): """representation of a HomematicIP weather sensor pro.""" @property - def wind_bearing(self): + def wind_bearing(self) -> float: """Return the wind bearing.""" return self._device.windDirection