Bump geniushub client (#26084)

* bump geniushub client

* delint

* remove unsused lint hints
This commit is contained in:
David Bonnes 2019-08-20 19:43:39 +02:00 committed by Paulus Schoutsen
parent 97d3f49bb8
commit 33c35a6c3c
7 changed files with 113 additions and 168 deletions

View File

@ -1,17 +1,23 @@
"""Support for a Genius Hub system."""
from datetime import timedelta
import logging
from typing import Awaitable
import aiohttp
import voluptuous as vol
from geniushubclient import GeniusHubClient
from geniushubclient import GeniusHub
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.dispatcher import (
async_dispatcher_send,
async_dispatcher_connect,
)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_time_interval
_LOGGER = logging.getLogger(__name__)
@ -45,7 +51,7 @@ async def async_setup(hass, hass_config):
broker = GeniusBroker(hass, args, kwargs)
try:
await broker._client.hub.update() # pylint: disable=protected-access
await broker.client.update()
except aiohttp.ClientResponseError as err:
_LOGGER.error("Setup failed, check your configuration, %s", err)
return False
@ -58,7 +64,7 @@ async def async_setup(hass, hass_config):
async_load_platform(hass, platform, DOMAIN, {}, hass_config)
)
if broker._client.api_version == 3: # pylint: disable=protected-access
if broker.client.api_version == 3: # pylint: disable=no-member
for platform in ["sensor", "binary_sensor"]:
hass.async_create_task(
async_load_platform(hass, platform, DOMAIN, {}, hass_config)
@ -72,27 +78,53 @@ class GeniusBroker:
def __init__(self, hass, args, kwargs):
"""Initialize the geniushub client."""
self._hass = hass
self._client = hass.data[DOMAIN]["client"] = GeniusHubClient(
self.hass = hass
self.client = hass.data[DOMAIN]["client"] = GeniusHub(
*args, **kwargs, session=async_get_clientsession(hass)
)
async def async_update(self, now, **kwargs):
"""Update the geniushub client's data."""
try:
await self._client.hub.update()
await self.client.update()
except aiohttp.ClientResponseError as err:
_LOGGER.warning("Update failed, %s", err)
return
self.make_debug_log_entries()
async_dispatcher_send(self._hass, DOMAIN)
async_dispatcher_send(self.hass, DOMAIN)
def make_debug_log_entries(self):
"""Make any useful debug log entries."""
# pylint: disable=protected-access
_LOGGER.debug(
"Raw JSON: \n\nhub._raw_zones = %s \n\nhub._raw_devices = %s",
self._client.hub._raw_zones,
self._client.hub._raw_devices,
"Raw JSON: \n\nclient._zones = %s \n\nclient._devices = %s",
self.client._zones,
self.client._devices,
)
class GeniusEntity(Entity):
"""Base for all Genius Hub endtities."""
def __init__(self):
"""Initialize the entity."""
self._name = None
async def async_added_to_hass(self) -> Awaitable[None]:
"""Set up a listener when this entity is added to HA."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self) -> None:
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self) -> str:
"""Return the name of the geniushub entity."""
return self._name
@property
def should_poll(self) -> bool:
"""Return False as geniushub entities should not be polled."""
return False

View File

@ -1,10 +1,10 @@
"""Support for Genius Hub binary_sensor devices."""
from typing import Any, Dict
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.util.dt import utc_from_timestamp
from . import DOMAIN
from . import DOMAIN, GeniusEntity
GH_IS_SWITCH = ["Dual Channel Receiver", "Electric Switch", "Smart Plug"]
@ -14,58 +14,38 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
client = hass.data[DOMAIN]["client"]
switches = [
GeniusBinarySensor(client, d)
for d in client.hub.device_objs
if d.type[:21] in GH_IS_SWITCH
GeniusBinarySensor(d) for d in client.device_objs if d.type[:21] in GH_IS_SWITCH
]
async_add_entities(switches)
class GeniusBinarySensor(BinarySensorDevice):
class GeniusBinarySensor(GeniusEntity, BinarySensorDevice):
"""Representation of a Genius Hub binary_sensor."""
def __init__(self, client, device):
def __init__(self, device) -> None:
"""Initialize the binary sensor."""
self._client = client
self._device = device
super().__init__()
self._device = device
if device.type[:21] == "Dual Channel Receiver":
self._name = "Dual Channel Receiver {}".format(device.id)
else:
self._name = "{} {}".format(device.type, device.id)
async def async_added_to_hass(self):
"""Set up a listener when this entity is added to HA."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self):
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def should_poll(self) -> bool:
"""Return False as the geniushub devices should not be polled."""
return False
@property
def is_on(self):
def is_on(self) -> bool:
"""Return the status of the sensor."""
return self._device.data["state"]["outputOnOff"]
@property
def device_state_attributes(self):
def device_state_attributes(self) -> Dict[str, Any]:
"""Return the device state attributes."""
attrs = {}
attrs["assigned_zone"] = self._device.data["assignedZones"][0]["name"]
# noqa; pylint: disable=protected-access
last_comms = self._device._raw_data["childValues"]["lastComms"]["val"]
# pylint: disable=protected-access
last_comms = self._device._raw["childValues"]["lastComms"]["val"]
if last_comms != 0:
attrs["last_comms"] = utc_from_timestamp(last_comms).isoformat()

View File

@ -11,10 +11,8 @@ from homeassistant.components.climate.const import (
SUPPORT_PRESET_MODE,
)
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import DOMAIN
from . import DOMAIN, GeniusEntity
ATTR_DURATION = "duration"
@ -38,32 +36,24 @@ async def async_setup_platform(
client = hass.data[DOMAIN]["client"]
entities = [
GeniusClimateZone(client, z) for z in client.hub.zone_objs if z.type in GH_ZONES
GeniusClimateZone(z) for z in client.zone_objs if z.data["type"] in GH_ZONES
]
async_add_entities(entities)
class GeniusClimateZone(ClimateDevice):
class GeniusClimateZone(GeniusEntity, ClimateDevice):
"""Representation of a Genius Hub climate device."""
def __init__(self, client, zone):
def __init__(self, zone) -> None:
"""Initialize the climate device."""
self._client = client
self._zone = zone
super().__init__()
self._zone = zone
if hasattr(self._zone, "occupied"): # has a movement sensor
self._preset_modes = list(HA_PRESET_TO_GH)
else:
self._preset_modes = [PRESET_BOOST]
async def async_added_to_hass(self) -> Awaitable[None]:
"""Run when entity about to be added."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self) -> None:
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self) -> str:
"""Return the name of the climate device."""
@ -75,11 +65,6 @@ class GeniusClimateZone(ClimateDevice):
tmp = self._zone.data.items()
return {"status": {k: v for k, v in tmp if k in GH_STATE_ATTRS}}
@property
def should_poll(self) -> bool:
"""Return False as the geniushub devices should not be polled."""
return False
@property
def icon(self) -> str:
"""Return the icon to use in the frontend UI."""
@ -91,7 +76,7 @@ class GeniusClimateZone(ClimateDevice):
return self._zone.data["temperature"]
@property
def target_temperature(self) -> Optional[float]:
def target_temperature(self) -> float:
"""Return the temperature we try to reach."""
return self._zone.data["setpoint"]

View File

@ -3,7 +3,7 @@
"name": "Genius Hub",
"documentation": "https://www.home-assistant.io/components/geniushub",
"requirements": [
"geniushub-client==0.5.8"
"geniushub-client==0.6.5"
],
"dependencies": [],
"codeowners": ["@zxdavb"]

View File

@ -1,13 +1,11 @@
"""Support for Genius Hub sensor devices."""
from datetime import timedelta
from typing import Any, Awaitable, Dict
from homeassistant.const import DEVICE_CLASS_BATTERY
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from homeassistant.util.dt import utc_from_timestamp, utcnow
from . import DOMAIN
from . import DOMAIN, GeniusEntity
GH_HAS_BATTERY = ["Room Thermostat", "Genius Valve", "Room Sensor", "Radiator Valve"]
@ -22,44 +20,27 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
"""Set up the Genius Hub sensor entities."""
client = hass.data[DOMAIN]["client"]
sensors = [
GeniusBattery(client, d)
for d in client.hub.device_objs
if d.type in GH_HAS_BATTERY
]
sensors = [GeniusBattery(d) for d in client.device_objs if d.type in GH_HAS_BATTERY]
issues = [GeniusIssue(client, i) for i in list(GH_LEVEL_MAPPING)]
async_add_entities(sensors + issues, update_before_add=True)
class GeniusBattery(Entity):
class GeniusBattery(GeniusEntity):
"""Representation of a Genius Hub sensor."""
def __init__(self, client, device):
def __init__(self, device) -> None:
"""Initialize the sensor."""
self._client = client
self._device = device
super().__init__()
self._device = device
self._name = "{} {}".format(device.type, device.id)
async def async_added_to_hass(self):
"""Set up a listener when this entity is added to HA."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self):
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def icon(self):
def icon(self) -> str:
"""Return the icon of the sensor."""
# noqa; pylint: disable=protected-access
values = self._device._raw_data["childValues"]
values = self._device._raw["childValues"] # pylint: disable=protected-access
last_comms = utc_from_timestamp(values["lastComms"]["val"])
if "WakeUp_Interval" in values:
@ -83,78 +64,57 @@ class GeniusBattery(Entity):
return icon
@property
def device_class(self):
def device_class(self) -> str:
"""Return the device class of the sensor."""
return DEVICE_CLASS_BATTERY
@property
def unit_of_measurement(self):
def unit_of_measurement(self) -> str:
"""Return the unit of measurement of the sensor."""
return "%"
@property
def should_poll(self) -> bool:
"""Return False as the geniushub devices should not be polled."""
return False
@property
def state(self):
def state(self) -> str:
"""Return the state of the sensor."""
level = self._device.data["state"].get("batteryLevel", 255)
return level if level != 255 else 0
@property
def device_state_attributes(self):
def device_state_attributes(self) -> Dict[str, Any]:
"""Return the device state attributes."""
attrs = {}
attrs["assigned_zone"] = self._device.data["assignedZones"][0]["name"]
# noqa; pylint: disable=protected-access
last_comms = self._device._raw_data["childValues"]["lastComms"]["val"]
# pylint: disable=protected-access
last_comms = self._device._raw["childValues"]["lastComms"]["val"]
attrs["last_comms"] = utc_from_timestamp(last_comms).isoformat()
return {**attrs}
class GeniusIssue(Entity):
class GeniusIssue(GeniusEntity):
"""Representation of a Genius Hub sensor."""
def __init__(self, client, level):
def __init__(self, hub, level) -> None:
"""Initialize the sensor."""
self._hub = client.hub
super().__init__()
self._hub = hub
self._name = GH_LEVEL_MAPPING[level]
self._level = level
self._issues = []
async def async_added_to_hass(self):
"""Set up a listener when this entity is added to HA."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self):
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def should_poll(self) -> bool:
"""Return False as the geniushub devices should not be polled."""
return False
@property
def state(self):
def state(self) -> str:
"""Return the number of issues."""
return len(self._issues)
@property
def device_state_attributes(self):
def device_state_attributes(self) -> Dict[str, Any]:
"""Return the device state attributes."""
return {"{}_list".format(self._level): self._issues}
async def async_update(self):
async def async_update(self) -> Awaitable[None]:
"""Process the sensor's state data."""
self._issues = [
i["description"] for i in self._hub.issues if i["level"] == self._level

View File

@ -1,14 +1,14 @@
"""Support for Genius Hub water_heater devices."""
from typing import Any, Awaitable, Dict, Optional, List
from homeassistant.components.water_heater import (
WaterHeaterDevice,
SUPPORT_TARGET_TEMPERATURE,
SUPPORT_OPERATION_MODE,
)
from homeassistant.const import ATTR_TEMPERATURE, STATE_OFF, TEMP_CELSIUS
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import DOMAIN
from . import DOMAIN, GeniusEntity
STATE_AUTO = "auto"
STATE_MANUAL = "manual"
@ -44,93 +44,81 @@ async def async_setup_platform(
client = hass.data[DOMAIN]["client"]
entities = [
GeniusWaterHeater(client, z)
for z in client.hub.zone_objs
if z.type in GH_HEATERS
GeniusWaterHeater(z) for z in client.zone_objs if z.data["type"] in GH_HEATERS
]
async_add_entities(entities)
class GeniusWaterHeater(WaterHeaterDevice):
class GeniusWaterHeater(GeniusEntity, WaterHeaterDevice):
"""Representation of a Genius Hub water_heater device."""
def __init__(self, client, boiler):
def __init__(self, boiler) -> None:
"""Initialize the water_heater device."""
self._client = client
self._boiler = boiler
super().__init__()
self._boiler = boiler
self._operation_list = list(HA_OPMODE_TO_GH)
async def async_added_to_hass(self):
"""Run when entity about to be added."""
async_dispatcher_connect(self.hass, DOMAIN, self._refresh)
@callback
def _refresh(self):
self.async_schedule_update_ha_state(force_refresh=True)
@property
def name(self):
def name(self) -> str:
"""Return the name of the water_heater device."""
return self._boiler.name
@property
def device_state_attributes(self):
def device_state_attributes(self) -> Dict[str, Any]:
"""Return the device state attributes."""
tmp = self._boiler.data.items()
return {"status": {k: v for k, v in tmp if k in GH_STATE_ATTRS}}
return {
"status": {
k: v for k, v in self._boiler.data.items() if k in GH_STATE_ATTRS
}
}
@property
def should_poll(self) -> bool:
"""Return False as the geniushub devices should not be polled."""
return False
@property
def current_temperature(self):
def current_temperature(self) -> Optional[float]:
"""Return the current temperature."""
return self._boiler.data.get("temperature")
@property
def target_temperature(self):
def target_temperature(self) -> float:
"""Return the temperature we try to reach."""
return self._boiler.data["setpoint"]
@property
def min_temp(self):
def min_temp(self) -> float:
"""Return max valid temperature that can be set."""
return GH_MIN_TEMP
@property
def max_temp(self):
def max_temp(self) -> float:
"""Return max valid temperature that can be set."""
return GH_MAX_TEMP
@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 GH_SUPPORT_FLAGS
@property
def operation_list(self):
def operation_list(self) -> List[str]:
"""Return the list of available operation modes."""
return self._operation_list
@property
def current_operation(self):
def current_operation(self) -> str:
"""Return the current operation mode."""
return GH_STATE_TO_HA[self._boiler.data["mode"]]
async def async_set_operation_mode(self, operation_mode):
async def async_set_operation_mode(self, operation_mode) -> Awaitable[None]:
"""Set a new operation mode for this boiler."""
await self._boiler.set_mode(HA_OPMODE_TO_GH[operation_mode])
async def async_set_temperature(self, **kwargs):
async def async_set_temperature(self, **kwargs) -> Awaitable[None]:
"""Set a new target temperature for this boiler."""
temperature = kwargs[ATTR_TEMPERATURE]
await self._boiler.set_override(temperature, 3600) # 1 hour

View File

@ -518,7 +518,7 @@ gearbest_parser==1.0.7
geizhals==0.0.9
# homeassistant.components.geniushub
geniushub-client==0.5.8
geniushub-client==0.6.5
# homeassistant.components.geo_json_events
# homeassistant.components.nsw_rural_fire_service_feed