From 55ac2df54b1218ad01a9d0077247a8ce6592a855 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Sun, 12 Apr 2020 10:39:28 +0200 Subject: [PATCH 1/2] Move myStrom light and switch to async --- homeassistant/components/mystrom/const.py | 2 + homeassistant/components/mystrom/light.py | 69 +++++++++++------- .../components/mystrom/manifest.json | 2 +- homeassistant/components/mystrom/switch.py | 72 +++++++++++++------ requirements_all.txt | 2 +- 5 files changed, 98 insertions(+), 49 deletions(-) create mode 100644 homeassistant/components/mystrom/const.py diff --git a/homeassistant/components/mystrom/const.py b/homeassistant/components/mystrom/const.py new file mode 100644 index 00000000000000..87697acbe967ae --- /dev/null +++ b/homeassistant/components/mystrom/const.py @@ -0,0 +1,2 @@ +"""Constants for the myStrom integration.""" +DOMAIN = "mystrom" diff --git a/homeassistant/components/mystrom/light.py b/homeassistant/components/mystrom/light.py index 56fe369144bb71..94b3105eae2b4d 100644 --- a/homeassistant/components/mystrom/light.py +++ b/homeassistant/components/mystrom/light.py @@ -19,6 +19,8 @@ from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME import homeassistant.helpers.config_validation as cv +from .const import DOMAIN + _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = "myStrom bulb" @@ -39,28 +41,28 @@ ) -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up the myStrom Light platform.""" - +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """Set up the myStrom light integration.""" host = config.get(CONF_HOST) mac = config.get(CONF_MAC) name = config.get(CONF_NAME) bulb = MyStromBulb(host, mac) try: - if bulb.get_status()["type"] != "rgblamp": + await bulb.get_state() + if bulb.bulb_type != "rgblamp": _LOGGER.error("Device %s (%s) is not a myStrom bulb", host, mac) return except MyStromConnectionError: - _LOGGER.warning("No route to device: %s", host) + _LOGGER.warning("No route to myStrom bulb: %s", host) - add_entities([MyStromLight(bulb, name)], True) + async_add_entities([MyStromLight(bulb, name, mac)], True) class MyStromLight(Light): - """Representation of the myStrom WiFi Bulb.""" + """Representation of the myStrom WiFi bulb.""" - def __init__(self, bulb, name): + def __init__(self, bulb, name, mac): """Initialize the light.""" self._bulb = bulb self._name = name @@ -69,12 +71,31 @@ def __init__(self, bulb, name): self._brightness = 0 self._color_h = 0 self._color_s = 0 + self._mac = mac + self.bulb_type = None + self.firmware = None @property def name(self): """Return the display name of this light.""" return self._name + @property + def unique_id(self): + """Return a unique ID.""" + return self._mac + + @property + def device_info(self): + """Return device specific attributes.""" + return { + "identifiers": {(DOMAIN, self.unique_id)}, + "name": self._name, + "manufacturer": DOMAIN, + "model": self.bulb_type, + "sw_version": self.firmware, + } + @property def supported_features(self): """Flag supported features.""" @@ -103,11 +124,10 @@ def effect_list(self): @property def is_on(self): """Return true if light is on.""" - return self._state["on"] if self._state is not None else None + return self._state - def turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs): """Turn on the light.""" - brightness = kwargs.get(ATTR_BRIGHTNESS, 255) effect = kwargs.get(ATTR_EFFECT) @@ -121,33 +141,34 @@ def turn_on(self, **kwargs): try: if not self.is_on: - self._bulb.set_on() + await self._bulb.set_on() if brightness is not None: - self._bulb.set_color_hsv( + await self._bulb.set_color_hsv( int(color_h), int(color_s), round(brightness * 100 / 255) ) if effect == EFFECT_SUNRISE: - self._bulb.set_sunrise(30) + await self._bulb.set_sunrise(30) if effect == EFFECT_RAINBOW: - self._bulb.set_rainbow(30) + await self._bulb.set_rainbow(30) except MyStromConnectionError: - _LOGGER.warning("No route to device") + _LOGGER.warning("No route to myStrom bulb") - def turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Turn off the bulb.""" - try: - self._bulb.set_off() + await self._bulb.set_off() except MyStromConnectionError: _LOGGER.warning("myStrom bulb not online") - def update(self): + async def async_update(self): """Fetch new state data for this light.""" - try: - self._state = self._bulb.get_status() + await self._bulb.get_state() + self._state = self._bulb.state + self.bulb_type = self._bulb.bulb_type + self.firmware = self._bulb.firmware - colors = self._bulb.get_color()["color"] + colors = self._bulb.color try: color_h, color_s, color_v = colors.split(";") except ValueError: @@ -160,5 +181,5 @@ def update(self): self._available = True except MyStromConnectionError: - _LOGGER.warning("No route to device") + _LOGGER.warning("No route to myStrom bulb") self._available = False diff --git a/homeassistant/components/mystrom/manifest.json b/homeassistant/components/mystrom/manifest.json index 7d74fca92a2d92..71a719be92ad62 100644 --- a/homeassistant/components/mystrom/manifest.json +++ b/homeassistant/components/mystrom/manifest.json @@ -2,7 +2,7 @@ "domain": "mystrom", "name": "myStrom", "documentation": "https://www.home-assistant.io/integrations/mystrom", - "requirements": ["python-mystrom==0.5.0"], + "requirements": ["python-mystrom==1.1.2"], "dependencies": ["http"], "codeowners": ["@fabaff"] } diff --git a/homeassistant/components/mystrom/switch.py b/homeassistant/components/mystrom/switch.py index 5bfd1e45b81a7e..78b0573ebc4995 100644 --- a/homeassistant/components/mystrom/switch.py +++ b/homeassistant/components/mystrom/switch.py @@ -1,8 +1,8 @@ -"""Support for myStrom switches.""" +"""Support for myStrom switches/plugs.""" import logging from pymystrom.exceptions import MyStromConnectionError -from pymystrom.switch import MyStromPlug +from pymystrom.switch import MyStromSwitch as _MyStromSwitch import voluptuous as vol from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice @@ -10,6 +10,8 @@ from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv +from .const import DOMAIN + DEFAULT_NAME = "myStrom Switch" _LOGGER = logging.getLogger(__name__) @@ -22,30 +24,34 @@ ) -def setup_platform(hass, config, add_entities, discovery_info=None): - """Find and return myStrom switch.""" +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): + """Set up the myStrom switch/plug integration.""" name = config.get(CONF_NAME) host = config.get(CONF_HOST) try: - MyStromPlug(host).get_status() + plug = _MyStromSwitch(host) + await plug.get_state() except MyStromConnectionError: - _LOGGER.error("No route to device: %s", host) + _LOGGER.error("No route to myStrom plug: %s", host) raise PlatformNotReady() - add_entities([MyStromSwitch(name, host)]) + async_add_entities([MyStromSwitch(plug, name, plug.mac)]) class MyStromSwitch(SwitchDevice): - """Representation of a myStrom switch.""" + """Representation of a myStrom switch/plug.""" - def __init__(self, name, resource): - """Initialize the myStrom switch.""" + def __init__(self, plug, name, mac): + """Initialize the myStrom switch/plug.""" self._name = name - self._resource = resource self.data = {} - self.plug = MyStromPlug(self._resource) + self.plug = plug self._available = True + self.mac = mac + self.firmware = None + self.consumption = None + self.relay = None @property def name(self): @@ -55,38 +61,58 @@ def name(self): @property def is_on(self): """Return true if switch is on.""" - return bool(self.data["relay"]) + return bool(self.relay) + + @property + def unique_id(self): + """Return a unique ID.""" + return self.mac + + @property + def device_info(self): + """Return device specific attributes.""" + return { + "identifiers": {(DOMAIN, self.unique_id)}, + "name": self._name, + "manufacturer": DOMAIN, + "model": "plug", + "sw_version": self.firmware, + } @property def current_power_w(self): """Return the current power consumption in W.""" - return round(self.data["power"], 2) + return self.consumption @property def available(self): """Could the device be accessed during the last update call.""" return self._available - def turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs): """Turn the switch on.""" try: - self.plug.set_relay_on() + await self.plug.turn_on() except MyStromConnectionError: - _LOGGER.error("No route to device: %s", self._resource) + _LOGGER.error("No route to myStrom plug") - def turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Turn the switch off.""" try: - self.plug.set_relay_off() + await self.plug.turn_off() except MyStromConnectionError: - _LOGGER.error("No route to device: %s", self._resource) + _LOGGER.error("No route to myStrom plug") - def update(self): + async def async_update(self): """Get the latest data from the device and update the data.""" try: - self.data = self.plug.get_status() + await self.plug.get_state() + self.firmware = self.plug.firmware + self.consumption = self.plug.consumption + self.relay = self.plug.relay + self._available = True except MyStromConnectionError: self.data = {"power": 0, "relay": False} self._available = False - _LOGGER.error("No route to device: %s", self._resource) + _LOGGER.error("No route to myStrom plug") diff --git a/requirements_all.txt b/requirements_all.txt index b104ae232a0d2f..99c4fd273fe9fa 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1649,7 +1649,7 @@ python-miio==0.5.0.1 python-mpd2==1.0.0 # homeassistant.components.mystrom -python-mystrom==0.5.0 +python-mystrom==1.1.2 # homeassistant.components.nest python-nest==4.1.0 From b01f6f96c35c1bea7c34684b4f785eeb363103b4 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Thu, 23 Apr 2020 17:14:51 +0200 Subject: [PATCH 2/2] Remove device_info --- homeassistant/components/mystrom/light.py | 19 ++------------ homeassistant/components/mystrom/switch.py | 29 +++------------------- 2 files changed, 6 insertions(+), 42 deletions(-) diff --git a/homeassistant/components/mystrom/light.py b/homeassistant/components/mystrom/light.py index 94b3105eae2b4d..72ec051b120e47 100644 --- a/homeassistant/components/mystrom/light.py +++ b/homeassistant/components/mystrom/light.py @@ -17,10 +17,9 @@ Light, ) from homeassistant.const import CONF_HOST, CONF_MAC, CONF_NAME +from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv -from .const import DOMAIN - _LOGGER = logging.getLogger(__name__) DEFAULT_NAME = "myStrom bulb" @@ -55,6 +54,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= return except MyStromConnectionError: _LOGGER.warning("No route to myStrom bulb: %s", host) + raise PlatformNotReady() async_add_entities([MyStromLight(bulb, name, mac)], True) @@ -72,8 +72,6 @@ def __init__(self, bulb, name, mac): self._color_h = 0 self._color_s = 0 self._mac = mac - self.bulb_type = None - self.firmware = None @property def name(self): @@ -85,17 +83,6 @@ def unique_id(self): """Return a unique ID.""" return self._mac - @property - def device_info(self): - """Return device specific attributes.""" - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": self._name, - "manufacturer": DOMAIN, - "model": self.bulb_type, - "sw_version": self.firmware, - } - @property def supported_features(self): """Flag supported features.""" @@ -165,8 +152,6 @@ async def async_update(self): try: await self._bulb.get_state() self._state = self._bulb.state - self.bulb_type = self._bulb.bulb_type - self.firmware = self._bulb.firmware colors = self._bulb.color try: diff --git a/homeassistant/components/mystrom/switch.py b/homeassistant/components/mystrom/switch.py index 78b0573ebc4995..ea91c9ba5d7d83 100644 --- a/homeassistant/components/mystrom/switch.py +++ b/homeassistant/components/mystrom/switch.py @@ -10,8 +10,6 @@ from homeassistant.exceptions import PlatformNotReady import homeassistant.helpers.config_validation as cv -from .const import DOMAIN - DEFAULT_NAME = "myStrom Switch" _LOGGER = logging.getLogger(__name__) @@ -36,21 +34,17 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= _LOGGER.error("No route to myStrom plug: %s", host) raise PlatformNotReady() - async_add_entities([MyStromSwitch(plug, name, plug.mac)]) + async_add_entities([MyStromSwitch(plug, name)]) class MyStromSwitch(SwitchDevice): """Representation of a myStrom switch/plug.""" - def __init__(self, plug, name, mac): + def __init__(self, plug, name): """Initialize the myStrom switch/plug.""" self._name = name - self.data = {} self.plug = plug self._available = True - self.mac = mac - self.firmware = None - self.consumption = None self.relay = None @property @@ -66,23 +60,12 @@ def is_on(self): @property def unique_id(self): """Return a unique ID.""" - return self.mac - - @property - def device_info(self): - """Return device specific attributes.""" - return { - "identifiers": {(DOMAIN, self.unique_id)}, - "name": self._name, - "manufacturer": DOMAIN, - "model": "plug", - "sw_version": self.firmware, - } + return self.plug._mac # pylint: disable=protected-access @property def current_power_w(self): """Return the current power consumption in W.""" - return self.consumption + return self.plug.consumption @property def available(self): @@ -107,12 +90,8 @@ async def async_update(self): """Get the latest data from the device and update the data.""" try: await self.plug.get_state() - self.firmware = self.plug.firmware - self.consumption = self.plug.consumption self.relay = self.plug.relay - self._available = True except MyStromConnectionError: - self.data = {"power": 0, "relay": False} self._available = False _LOGGER.error("No route to myStrom plug")