Bump geniushub client, handle dead devices, handle raise_for_status (#25687)
* Initial commit * tweak error logging * bump client * correct regression * small coding tweak * debug logging to one entry * refactor for self.data['attr'] * bump client * small tidy-up
This commit is contained in:
parent
0d95ad3857
commit
b0c79c271d
7 changed files with 50 additions and 79 deletions
|
@ -2,6 +2,7 @@
|
|||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
import voluptuous as vol
|
||||
|
||||
from geniushubclient import GeniusHubClient
|
||||
|
@ -41,32 +42,23 @@ async def async_setup(hass, hass_config):
|
|||
args = (kwargs.pop(CONF_TOKEN),)
|
||||
|
||||
hass.data[DOMAIN] = {}
|
||||
data = hass.data[DOMAIN]["data"] = GeniusData(hass, args, kwargs)
|
||||
broker = GeniusBroker(hass, args, kwargs)
|
||||
|
||||
try:
|
||||
await data._client.hub.update() # pylint: disable=protected-access
|
||||
except AssertionError: # assert response.status == HTTP_OK
|
||||
_LOGGER.warning("Setup failed, check your configuration.", exc_info=True)
|
||||
await broker._client.hub.update() # pylint: disable=protected-access
|
||||
except aiohttp.ClientResponseError as err:
|
||||
_LOGGER.error("Setup failed, check your configuration, %s", err)
|
||||
return False
|
||||
broker.make_debug_log_entries()
|
||||
|
||||
_LOGGER.debug(
|
||||
# noqa; pylint: disable=protected-access
|
||||
"zones_raw = %s",
|
||||
data._client.hub._zones_raw,
|
||||
)
|
||||
_LOGGER.debug(
|
||||
# noqa; pylint: disable=protected-access
|
||||
"devices_raw = %s",
|
||||
data._client.hub._devices_raw,
|
||||
)
|
||||
|
||||
async_track_time_interval(hass, data.async_update, SCAN_INTERVAL)
|
||||
async_track_time_interval(hass, broker.async_update, SCAN_INTERVAL)
|
||||
|
||||
for platform in ["climate", "water_heater"]:
|
||||
hass.async_create_task(
|
||||
async_load_platform(hass, platform, DOMAIN, {}, hass_config)
|
||||
)
|
||||
|
||||
if data._client.api_version == 3: # pylint: disable=protected-access
|
||||
if broker._client.api_version == 3: # pylint: disable=protected-access
|
||||
for platform in ["sensor", "binary_sensor"]:
|
||||
hass.async_create_task(
|
||||
async_load_platform(hass, platform, DOMAIN, {}, hass_config)
|
||||
|
@ -75,7 +67,7 @@ async def async_setup(hass, hass_config):
|
|||
return True
|
||||
|
||||
|
||||
class GeniusData:
|
||||
class GeniusBroker:
|
||||
"""Container for geniushub client and data."""
|
||||
|
||||
def __init__(self, hass, args, kwargs):
|
||||
|
@ -89,19 +81,18 @@ class GeniusData:
|
|||
"""Update the geniushub client's data."""
|
||||
try:
|
||||
await self._client.hub.update()
|
||||
except AssertionError: # assert response.status == HTTP_OK
|
||||
_LOGGER.warning("Update failed.", exc_info=True)
|
||||
except aiohttp.ClientResponseError as err:
|
||||
_LOGGER.warning("Update failed, %s", err)
|
||||
return
|
||||
|
||||
_LOGGER.debug(
|
||||
# noqa; pylint: disable=protected-access
|
||||
"zones_raw = %s",
|
||||
self._client.hub._zones_raw,
|
||||
)
|
||||
_LOGGER.debug(
|
||||
# noqa; pylint: disable=protected-access
|
||||
"devices_raw = %s",
|
||||
self._client.hub._devices_raw,
|
||||
)
|
||||
self.make_debug_log_entries()
|
||||
|
||||
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,
|
||||
)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Support for Genius Hub binary_sensor devices."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
@ -8,8 +6,6 @@ from homeassistant.util.dt import utc_from_timestamp
|
|||
|
||||
from . import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
GH_IS_SWITCH = ["Dual Channel Receiver", "Electric Switch", "Smart Plug"]
|
||||
|
||||
|
||||
|
@ -17,9 +13,10 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
"""Set up the Genius Hub sensor entities."""
|
||||
client = hass.data[DOMAIN]["client"]
|
||||
|
||||
devices = [d for d in client.hub.device_objs if d.type is not None]
|
||||
switches = [
|
||||
GeniusBinarySensor(client, d) for d in devices if d.type[:21] in GH_IS_SWITCH
|
||||
GeniusBinarySensor(client, d)
|
||||
for d in client.hub.device_objs
|
||||
if d.type[:21] in GH_IS_SWITCH
|
||||
]
|
||||
|
||||
async_add_entities(switches)
|
||||
|
@ -59,16 +56,16 @@ class GeniusBinarySensor(BinarySensorDevice):
|
|||
@property
|
||||
def is_on(self):
|
||||
"""Return the status of the sensor."""
|
||||
return self._device.state["outputOnOff"]
|
||||
return self._device.data["state"]["outputOnOff"]
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
attrs = {}
|
||||
attrs["assigned_zone"] = self._device.assignedZones[0]["name"]
|
||||
attrs["assigned_zone"] = self._device.data["assignedZones"][0]["name"]
|
||||
|
||||
# noqa; pylint: disable=protected-access
|
||||
last_comms = self._device._raw_json["childValues"]["lastComms"]["val"]
|
||||
last_comms = self._device._raw_data["childValues"]["lastComms"]["val"]
|
||||
if last_comms != 0:
|
||||
attrs["last_comms"] = utc_from_timestamp(last_comms).isoformat()
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
"""Support for Genius Hub climate devices."""
|
||||
import logging
|
||||
from typing import Any, Awaitable, Dict, Optional, List
|
||||
|
||||
from homeassistant.components.climate import ClimateDevice
|
||||
|
@ -17,8 +16,6 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||
|
||||
from . import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTR_DURATION = "duration"
|
||||
|
||||
GH_ZONES = ["radiator"]
|
||||
|
@ -40,13 +37,10 @@ async def async_setup_platform(
|
|||
"""Set up the Genius Hub climate entities."""
|
||||
client = hass.data[DOMAIN]["client"]
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
GeniusClimateZone(client, z)
|
||||
for z in client.hub.zone_objs
|
||||
if z.type in GH_ZONES
|
||||
]
|
||||
)
|
||||
entities = [
|
||||
GeniusClimateZone(client, z) for z in client.hub.zone_objs if z.type in GH_ZONES
|
||||
]
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class GeniusClimateZone(ClimateDevice):
|
||||
|
@ -78,7 +72,7 @@ class GeniusClimateZone(ClimateDevice):
|
|||
@property
|
||||
def device_state_attributes(self) -> Dict[str, Any]:
|
||||
"""Return the device state attributes."""
|
||||
tmp = self._zone.__dict__.items()
|
||||
tmp = self._zone.data.items()
|
||||
return {"status": {k: v for k, v in tmp if k in GH_STATE_ATTRS}}
|
||||
|
||||
@property
|
||||
|
@ -94,12 +88,12 @@ class GeniusClimateZone(ClimateDevice):
|
|||
@property
|
||||
def current_temperature(self) -> Optional[float]:
|
||||
"""Return the current temperature."""
|
||||
return self._zone.temperature
|
||||
return self._zone.data["temperature"]
|
||||
|
||||
@property
|
||||
def target_temperature(self) -> Optional[float]:
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._zone.setpoint
|
||||
return self._zone.data["setpoint"]
|
||||
|
||||
@property
|
||||
def min_temp(self) -> float:
|
||||
|
@ -124,7 +118,7 @@ class GeniusClimateZone(ClimateDevice):
|
|||
@property
|
||||
def hvac_mode(self) -> str:
|
||||
"""Return hvac operation ie. heat, cool mode."""
|
||||
return GH_HVAC_TO_HA.get(self._zone.mode, HVAC_MODE_HEAT)
|
||||
return GH_HVAC_TO_HA.get(self._zone.data["mode"], HVAC_MODE_HEAT)
|
||||
|
||||
@property
|
||||
def hvac_modes(self) -> List[str]:
|
||||
|
@ -134,7 +128,7 @@ class GeniusClimateZone(ClimateDevice):
|
|||
@property
|
||||
def preset_mode(self) -> Optional[str]:
|
||||
"""Return the current preset mode, e.g., home, away, temp."""
|
||||
return GH_PRESET_TO_HA.get(self._zone.mode)
|
||||
return GH_PRESET_TO_HA.get(self._zone.data["mode"])
|
||||
|
||||
@property
|
||||
def preset_modes(self) -> Optional[List[str]]:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"name": "Genius Hub",
|
||||
"documentation": "https://www.home-assistant.io/components/geniushub",
|
||||
"requirements": [
|
||||
"geniushub-client==0.5.4"
|
||||
"geniushub-client==0.5.8"
|
||||
],
|
||||
"dependencies": [],
|
||||
"codeowners": ["@zxdavb"]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Support for Genius Hub sensor devices."""
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from homeassistant.const import DEVICE_CLASS_BATTERY
|
||||
from homeassistant.core import callback
|
||||
|
@ -10,8 +9,6 @@ from homeassistant.util.dt import utc_from_timestamp, utcnow
|
|||
|
||||
from . import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
GH_HAS_BATTERY = ["Room Thermostat", "Genius Valve", "Room Sensor", "Radiator Valve"]
|
||||
|
||||
GH_LEVEL_MAPPING = {
|
||||
|
@ -26,17 +23,16 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
|
|||
client = hass.data[DOMAIN]["client"]
|
||||
|
||||
sensors = [
|
||||
GeniusDevice(client, d)
|
||||
GeniusBattery(client, d)
|
||||
for d in client.hub.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 GeniusDevice(Entity):
|
||||
class GeniusBattery(Entity):
|
||||
"""Representation of a Genius Hub sensor."""
|
||||
|
||||
def __init__(self, client, device):
|
||||
|
@ -63,7 +59,7 @@ class GeniusDevice(Entity):
|
|||
def icon(self):
|
||||
"""Return the icon of the sensor."""
|
||||
# noqa; pylint: disable=protected-access
|
||||
values = self._device._raw_json["childValues"]
|
||||
values = self._device._raw_data["childValues"]
|
||||
|
||||
last_comms = utc_from_timestamp(values["lastComms"]["val"])
|
||||
if "WakeUp_Interval" in values:
|
||||
|
@ -74,7 +70,7 @@ class GeniusDevice(Entity):
|
|||
if last_comms < utcnow() - interval * 3:
|
||||
return "mdi:battery-unknown"
|
||||
|
||||
battery_level = self._device.state["batteryLevel"]
|
||||
battery_level = self._device.data["state"]["batteryLevel"]
|
||||
if battery_level == 255:
|
||||
return "mdi:battery-unknown"
|
||||
if battery_level < 40:
|
||||
|
@ -104,17 +100,17 @@ class GeniusDevice(Entity):
|
|||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
level = self._device.state.get("batteryLevel", 255)
|
||||
level = self._device.data["state"].get("batteryLevel", 255)
|
||||
return level if level != 255 else 0
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
attrs = {}
|
||||
attrs["assigned_zone"] = self._device.assignedZones[0]["name"]
|
||||
attrs["assigned_zone"] = self._device.data["assignedZones"][0]["name"]
|
||||
|
||||
# noqa; pylint: disable=protected-access
|
||||
last_comms = self._device._raw_json["childValues"]["lastComms"]["val"]
|
||||
last_comms = self._device._raw_data["childValues"]["lastComms"]["val"]
|
||||
attrs["last_comms"] = utc_from_timestamp(last_comms).isoformat()
|
||||
|
||||
return {**attrs}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
"""Support for Genius Hub water_heater devices."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.water_heater import (
|
||||
WaterHeaterDevice,
|
||||
SUPPORT_TARGET_TEMPERATURE,
|
||||
|
@ -15,8 +13,6 @@ from . import DOMAIN
|
|||
STATE_AUTO = "auto"
|
||||
STATE_MANUAL = "manual"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
GH_HEATERS = ["hot water temperature"]
|
||||
|
||||
GH_SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_OPERATION_MODE
|
||||
|
@ -82,7 +78,7 @@ class GeniusWaterHeater(WaterHeaterDevice):
|
|||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the device state attributes."""
|
||||
tmp = self._boiler.__dict__.items()
|
||||
tmp = self._boiler.data.items()
|
||||
return {"status": {k: v for k, v in tmp if k in GH_STATE_ATTRS}}
|
||||
|
||||
@property
|
||||
|
@ -93,15 +89,12 @@ class GeniusWaterHeater(WaterHeaterDevice):
|
|||
@property
|
||||
def current_temperature(self):
|
||||
"""Return the current temperature."""
|
||||
try:
|
||||
return self._boiler.temperature
|
||||
except AttributeError:
|
||||
return None
|
||||
return self._boiler.data.get("temperature")
|
||||
|
||||
@property
|
||||
def target_temperature(self):
|
||||
"""Return the temperature we try to reach."""
|
||||
return self._boiler.setpoint
|
||||
return self._boiler.data["setpoint"]
|
||||
|
||||
@property
|
||||
def min_temp(self):
|
||||
|
@ -131,7 +124,7 @@ class GeniusWaterHeater(WaterHeaterDevice):
|
|||
@property
|
||||
def current_operation(self):
|
||||
"""Return the current operation mode."""
|
||||
return GH_STATE_TO_HA[self._boiler.mode]
|
||||
return GH_STATE_TO_HA[self._boiler.data["mode"]]
|
||||
|
||||
async def async_set_operation_mode(self, operation_mode):
|
||||
"""Set a new operation mode for this boiler."""
|
||||
|
|
|
@ -517,7 +517,7 @@ gearbest_parser==1.0.7
|
|||
geizhals==0.0.9
|
||||
|
||||
# homeassistant.components.geniushub
|
||||
geniushub-client==0.5.4
|
||||
geniushub-client==0.5.8
|
||||
|
||||
# homeassistant.components.geo_json_events
|
||||
# homeassistant.components.nsw_rural_fire_service_feed
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue