Convert Hive to Async (#46117)

* Convert Hive to Async

* Update Refresh System

* Update load platform to Async

* Changes from review feedback

* Review Round 2

* Updated service

* Updated dict keys

* Convert Hive to Async

* Update Refresh System

* Update load platform to Async

* Changes from review feedback

* Review Round 2

* Updated service

* Updated dict keys

* Convert Hive to Async

* Update Refresh System

* Update load platform to Async

* Changes from review feedback

* Review Round 2

* Updated service

* Updated dict keys

* Updated Refresh System
This commit is contained in:
Khole 2021-02-09 21:03:49 +00:00 committed by GitHub
parent 6f4cb18fa8
commit 3381e2f65a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 308 additions and 244 deletions

View File

@ -2,7 +2,7 @@
from functools import wraps from functools import wraps
import logging import logging
from pyhiveapi import Pyhiveapi from pyhiveapi import Hive
import voluptuous as vol import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
@ -13,12 +13,17 @@ from homeassistant.const import (
CONF_USERNAME, CONF_USERNAME,
) )
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import load_platform from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_connect, dispatcher_send from homeassistant.helpers.dispatcher import (
async_dispatcher_connect,
async_dispatcher_send,
)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_AVAILABLE = "available"
ATTR_MODE = "mode"
DOMAIN = "hive" DOMAIN = "hive"
DATA_HIVE = "data_hive" DATA_HIVE = "data_hive"
SERVICES = ["Heating", "HotWater", "TRV"] SERVICES = ["Heating", "HotWater", "TRV"]
@ -69,28 +74,15 @@ BOOST_HOT_WATER_SCHEMA = vol.Schema(
) )
class HiveSession: async def async_setup(hass, config):
"""Initiate Hive Session Class."""
entity_lookup = {}
core = None
heating = None
hotwater = None
light = None
sensor = None
switch = None
weather = None
attributes = None
trv = None
def setup(hass, config):
"""Set up the Hive Component.""" """Set up the Hive Component."""
def heating_boost(service): async def heating_boost(service):
"""Handle the service call.""" """Handle the service call."""
node_id = HiveSession.entity_lookup.get(service.data[ATTR_ENTITY_ID])
if not node_id: entity_lookup = hass.data[DOMAIN]["entity_lookup"]
hive_id = entity_lookup.get(service.data[ATTR_ENTITY_ID])
if not hive_id:
# log or raise error # log or raise error
_LOGGER.error("Cannot boost entity id entered") _LOGGER.error("Cannot boost entity id entered")
return return
@ -98,12 +90,13 @@ def setup(hass, config):
minutes = service.data[ATTR_TIME_PERIOD] minutes = service.data[ATTR_TIME_PERIOD]
temperature = service.data[ATTR_TEMPERATURE] temperature = service.data[ATTR_TEMPERATURE]
session.heating.turn_boost_on(node_id, minutes, temperature) hive.heating.turn_boost_on(hive_id, minutes, temperature)
def hot_water_boost(service): async def hot_water_boost(service):
"""Handle the service call.""" """Handle the service call."""
node_id = HiveSession.entity_lookup.get(service.data[ATTR_ENTITY_ID]) entity_lookup = hass.data[DOMAIN]["entity_lookup"]
if not node_id: hive_id = entity_lookup.get(service.data[ATTR_ENTITY_ID])
if not hive_id:
# log or raise error # log or raise error
_LOGGER.error("Cannot boost entity id entered") _LOGGER.error("Cannot boost entity id entered")
return return
@ -111,45 +104,41 @@ def setup(hass, config):
mode = service.data[ATTR_MODE] mode = service.data[ATTR_MODE]
if mode == "on": if mode == "on":
session.hotwater.turn_boost_on(node_id, minutes) hive.hotwater.turn_boost_on(hive_id, minutes)
elif mode == "off": elif mode == "off":
session.hotwater.turn_boost_off(node_id) hive.hotwater.turn_boost_off(hive_id)
session = HiveSession() hive = Hive()
session.core = Pyhiveapi()
username = config[DOMAIN][CONF_USERNAME] config = {}
password = config[DOMAIN][CONF_PASSWORD] config["username"] = config[DOMAIN][CONF_USERNAME]
update_interval = config[DOMAIN][CONF_SCAN_INTERVAL] config["password"] = config[DOMAIN][CONF_PASSWORD]
config["update_interval"] = config[DOMAIN][CONF_SCAN_INTERVAL]
devices = session.core.initialise_api(username, password, update_interval) devices = await hive.session.startSession(config)
if devices is None: if devices is None:
_LOGGER.error("Hive API initialization failed") _LOGGER.error("Hive API initialization failed")
return False return False
session.sensor = Pyhiveapi.Sensor() hass.data[DOMAIN][DATA_HIVE] = hive
session.heating = Pyhiveapi.Heating() hass.data[DOMAIN]["entity_lookup"] = {}
session.hotwater = Pyhiveapi.Hotwater()
session.light = Pyhiveapi.Light()
session.switch = Pyhiveapi.Switch()
session.weather = Pyhiveapi.Weather()
session.attributes = Pyhiveapi.Attributes()
hass.data[DATA_HIVE] = session
for ha_type in DEVICETYPES: for ha_type in DEVICETYPES:
devicelist = devices.get(DEVICETYPES[ha_type]) devicelist = devices.get(DEVICETYPES[ha_type])
if devicelist: if devicelist:
load_platform(hass, ha_type, DOMAIN, devicelist, config) hass.async_create_task(
async_load_platform(hass, ha_type, DOMAIN, devicelist, config)
)
if ha_type == "climate": if ha_type == "climate":
hass.services.register( hass.services.async_register(
DOMAIN, DOMAIN,
SERVICE_BOOST_HEATING, SERVICE_BOOST_HEATING,
heating_boost, heating_boost,
schema=BOOST_HEATING_SCHEMA, schema=BOOST_HEATING_SCHEMA,
) )
if ha_type == "water_heater": if ha_type == "water_heater":
hass.services.register( hass.services.async_register(
DOMAIN, DOMAIN,
SERVICE_BOOST_HOT_WATER, SERVICE_BOOST_HOT_WATER,
hot_water_boost, hot_water_boost,
@ -163,9 +152,9 @@ def refresh_system(func):
"""Force update all entities after state change.""" """Force update all entities after state change."""
@wraps(func) @wraps(func)
def wrapper(self, *args, **kwargs): async def wrapper(self, *args, **kwargs):
func(self, *args, **kwargs) await func(self, *args, **kwargs)
dispatcher_send(self.hass, DOMAIN) async_dispatcher_send(self.hass, DOMAIN)
return wrapper return wrapper
@ -173,20 +162,18 @@ def refresh_system(func):
class HiveEntity(Entity): class HiveEntity(Entity):
"""Initiate Hive Base Class.""" """Initiate Hive Base Class."""
def __init__(self, session, hive_device): def __init__(self, hive, hive_device):
"""Initialize the instance.""" """Initialize the instance."""
self.node_id = hive_device["Hive_NodeID"] self.hive = hive
self.node_name = hive_device["Hive_NodeName"] self.device = hive_device
self.device_type = hive_device["HA_DeviceType"]
self.node_device_type = hive_device["Hive_DeviceType"]
self.session = session
self.attributes = {} self.attributes = {}
self._unique_id = f"{self.node_id}-{self.device_type}" self._unique_id = f'{self.device["hiveID"]}-{self.device["hiveType"]}'
async def async_added_to_hass(self): async def async_added_to_hass(self):
"""When entity is added to Home Assistant.""" """When entity is added to Home Assistant."""
self.async_on_remove( self.async_on_remove(
async_dispatcher_connect(self.hass, DOMAIN, self.async_write_ha_state) async_dispatcher_connect(self.hass, DOMAIN, self.async_write_ha_state)
) )
if self.device_type in SERVICES: if self.device["hiveType"] in SERVICES:
self.session.entity_lookup[self.entity_id] = self.node_id entity_lookup = self.hass.data[DOMAIN]["entity_lookup"]
entity_lookup[self.entity_id] = self.device["hiveID"]

View File

@ -1,28 +1,36 @@
"""Support for the Hive binary sensors.""" """Support for the Hive binary sensors."""
from datetime import timedelta
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
DEVICE_CLASS_CONNECTIVITY,
DEVICE_CLASS_MOTION, DEVICE_CLASS_MOTION,
DEVICE_CLASS_OPENING, DEVICE_CLASS_OPENING,
BinarySensorEntity, BinarySensorEntity,
) )
from . import DATA_HIVE, DOMAIN, HiveEntity from . import ATTR_AVAILABLE, ATTR_MODE, DATA_HIVE, DOMAIN, HiveEntity
DEVICETYPE_DEVICE_CLASS = { DEVICETYPE = {
"motionsensor": DEVICE_CLASS_MOTION,
"contactsensor": DEVICE_CLASS_OPENING, "contactsensor": DEVICE_CLASS_OPENING,
"motionsensor": DEVICE_CLASS_MOTION,
"Connectivity": DEVICE_CLASS_CONNECTIVITY,
} }
PARALLEL_UPDATES = 0
SCAN_INTERVAL = timedelta(seconds=15)
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Hive sensor devices.""" """Set up the Hive Binary Sensor."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("binary_sensor")
for dev in discovery_info: entities = []
devs.append(HiveBinarySensorEntity(session, dev)) if devices:
add_entities(devs) for dev in devices:
entities.append(HiveBinarySensorEntity(hive, dev))
async_add_entities(entities, True)
class HiveBinarySensorEntity(HiveEntity, BinarySensorEntity): class HiveBinarySensorEntity(HiveEntity, BinarySensorEntity):
@ -41,24 +49,35 @@ class HiveBinarySensorEntity(HiveEntity, BinarySensorEntity):
@property @property
def device_class(self): def device_class(self):
"""Return the class of this sensor.""" """Return the class of this sensor."""
return DEVICETYPE_DEVICE_CLASS.get(self.node_device_type) return DEVICETYPE.get(self.device["hiveType"])
@property @property
def name(self): def name(self):
"""Return the name of the binary sensor.""" """Return the name of the binary sensor."""
return self.node_name return self.device["haName"]
@property
def available(self):
"""Return if the device is available."""
if self.device["hiveType"] != "Connectivity":
return self.device["deviceData"]["online"]
return True
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Show Device Attributes.""" """Show Device Attributes."""
return self.attributes return {
ATTR_AVAILABLE: self.attributes.get(ATTR_AVAILABLE),
ATTR_MODE: self.attributes.get(ATTR_MODE),
}
@property @property
def is_on(self): def is_on(self):
"""Return true if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self.session.sensor.get_state(self.node_id, self.node_device_type) return self.device["status"]["state"]
def update(self): async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.attributes = self.session.attributes.state_attributes(self.node_id) self.device = await self.hive.sensor.get_sensor(self.device)
self.attributes = self.device.get("attributes", {})

View File

@ -1,4 +1,6 @@
"""Support for the Hive climate devices.""" """Support for the Hive climate devices."""
from datetime import timedelta
from homeassistant.components.climate import ClimateEntity from homeassistant.components.climate import ClimateEntity
from homeassistant.components.climate.const import ( from homeassistant.components.climate.const import (
CURRENT_HVAC_HEAT, CURRENT_HVAC_HEAT,
@ -12,9 +14,9 @@ from homeassistant.components.climate.const import (
SUPPORT_PRESET_MODE, SUPPORT_PRESET_MODE,
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
) )
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
from . import DATA_HIVE, DOMAIN, HiveEntity, refresh_system from . import ATTR_AVAILABLE, DATA_HIVE, DOMAIN, HiveEntity, refresh_system
HIVE_TO_HASS_STATE = { HIVE_TO_HASS_STATE = {
"SCHEDULE": HVAC_MODE_AUTO, "SCHEDULE": HVAC_MODE_AUTO,
@ -34,21 +36,27 @@ HIVE_TO_HASS_HVAC_ACTION = {
True: CURRENT_HVAC_HEAT, True: CURRENT_HVAC_HEAT,
} }
TEMP_UNIT = {"C": TEMP_CELSIUS, "F": TEMP_FAHRENHEIT}
SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
SUPPORT_HVAC = [HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF] SUPPORT_HVAC = [HVAC_MODE_AUTO, HVAC_MODE_HEAT, HVAC_MODE_OFF]
SUPPORT_PRESET = [PRESET_NONE, PRESET_BOOST] SUPPORT_PRESET = [PRESET_NONE, PRESET_BOOST]
PARALLEL_UPDATES = 0
SCAN_INTERVAL = timedelta(seconds=15)
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Hive climate devices.""" """Set up the Hive thermostat."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("climate")
for dev in discovery_info: entities = []
devs.append(HiveClimateEntity(session, dev)) if devices:
add_entities(devs) for dev in devices:
entities.append(HiveClimateEntity(hive, dev))
async_add_entities(entities, True)
class HiveClimateEntity(HiveEntity, ClimateEntity): class HiveClimateEntity(HiveEntity, ClimateEntity):
@ -57,7 +65,8 @@ class HiveClimateEntity(HiveEntity, ClimateEntity):
def __init__(self, hive_session, hive_device): def __init__(self, hive_session, hive_device):
"""Initialize the Climate device.""" """Initialize the Climate device."""
super().__init__(hive_session, hive_device) super().__init__(hive_session, hive_device)
self.thermostat_node_id = hive_device["Thermostat_NodeID"] self.thermostat_node_id = hive_device["device_id"]
self.temperature_type = TEMP_UNIT.get(hive_device["temperatureunit"])
@property @property
def unique_id(self): def unique_id(self):
@ -77,19 +86,17 @@ class HiveClimateEntity(HiveEntity, ClimateEntity):
@property @property
def name(self): def name(self):
"""Return the name of the Climate device.""" """Return the name of the Climate device."""
friendly_name = "Heating" return self.device["haName"]
if self.node_name is not None:
if self.device_type == "TRV":
friendly_name = self.node_name
else:
friendly_name = f"{self.node_name} {friendly_name}"
return friendly_name @property
def available(self):
"""Return if the device is available."""
return self.device["deviceData"]["online"]
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Show Device Attributes.""" """Show Device Attributes."""
return self.attributes return {ATTR_AVAILABLE: self.attributes.get(ATTR_AVAILABLE)}
@property @property
def hvac_modes(self): def hvac_modes(self):
@ -105,47 +112,42 @@ class HiveClimateEntity(HiveEntity, ClimateEntity):
Need to be one of HVAC_MODE_*. Need to be one of HVAC_MODE_*.
""" """
return HIVE_TO_HASS_STATE[self.session.heating.get_mode(self.node_id)] return HIVE_TO_HASS_STATE[self.device["status"]["mode"]]
@property @property
def hvac_action(self): def hvac_action(self):
"""Return current HVAC action.""" """Return current HVAC action."""
return HIVE_TO_HASS_HVAC_ACTION[ return HIVE_TO_HASS_HVAC_ACTION[self.device["status"]["action"]]
self.session.heating.operational_status(self.node_id, self.device_type)
]
@property @property
def temperature_unit(self): def temperature_unit(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""
return TEMP_CELSIUS return self.temperature_type
@property @property
def current_temperature(self): def current_temperature(self):
"""Return the current temperature.""" """Return the current temperature."""
return self.session.heating.current_temperature(self.node_id) return self.device["status"]["current_temperature"]
@property @property
def target_temperature(self): def target_temperature(self):
"""Return the target temperature.""" """Return the target temperature."""
return self.session.heating.get_target_temperature(self.node_id) return self.device["status"]["target_temperature"]
@property @property
def min_temp(self): def min_temp(self):
"""Return minimum temperature.""" """Return minimum temperature."""
return self.session.heating.min_temperature(self.node_id) return self.device["min_temp"]
@property @property
def max_temp(self): def max_temp(self):
"""Return the maximum temperature.""" """Return the maximum temperature."""
return self.session.heating.max_temperature(self.node_id) return self.device["max_temp"]
@property @property
def preset_mode(self): def preset_mode(self):
"""Return the current preset mode, e.g., home, away, temp.""" """Return the current preset mode, e.g., home, away, temp."""
if ( if self.device["status"]["boost"] == "ON":
self.device_type == "Heating"
and self.session.heating.get_boost(self.node_id) == "ON"
):
return PRESET_BOOST return PRESET_BOOST
return None return None
@ -155,31 +157,30 @@ class HiveClimateEntity(HiveEntity, ClimateEntity):
return SUPPORT_PRESET return SUPPORT_PRESET
@refresh_system @refresh_system
def set_hvac_mode(self, hvac_mode): async def async_set_hvac_mode(self, hvac_mode):
"""Set new target hvac mode.""" """Set new target hvac mode."""
new_mode = HASS_TO_HIVE_STATE[hvac_mode] new_mode = HASS_TO_HIVE_STATE[hvac_mode]
self.session.heating.set_mode(self.node_id, new_mode) await self.hive.heating.set_mode(self.device, new_mode)
@refresh_system @refresh_system
def set_temperature(self, **kwargs): async def async_set_temperature(self, **kwargs):
"""Set new target temperature.""" """Set new target temperature."""
new_temperature = kwargs.get(ATTR_TEMPERATURE) new_temperature = kwargs.get(ATTR_TEMPERATURE)
if new_temperature is not None: if new_temperature is not None:
self.session.heating.set_target_temperature(self.node_id, new_temperature) await self.hive.heating.set_target_temperature(self.device, new_temperature)
@refresh_system @refresh_system
def set_preset_mode(self, preset_mode): async def async_set_preset_mode(self, preset_mode):
"""Set new preset mode.""" """Set new preset mode."""
if preset_mode == PRESET_NONE and self.preset_mode == PRESET_BOOST: if preset_mode == PRESET_NONE and self.preset_mode == PRESET_BOOST:
self.session.heating.turn_boost_off(self.node_id) await self.hive.heating.turn_boost_off(self.device)
elif preset_mode == PRESET_BOOST: elif preset_mode == PRESET_BOOST:
curtemp = round(self.current_temperature * 2) / 2 curtemp = round(self.current_temperature * 2) / 2
temperature = curtemp + 0.5 temperature = curtemp + 0.5
self.session.heating.turn_boost_on(self.node_id, 30, temperature) await self.hive.heating.turn_boost_on(self.device, 30, temperature)
def update(self): async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.attributes = self.session.attributes.state_attributes( self.device = await self.hive.heating.get_heating(self.device)
self.thermostat_node_id self.attributes.update(self.device.get("attributes", {}))
)

View File

@ -1,4 +1,6 @@
"""Support for the Hive lights.""" """Support for Hive light devices."""
from datetime import timedelta
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_BRIGHTNESS,
ATTR_COLOR_TEMP, ATTR_COLOR_TEMP,
@ -10,29 +12,29 @@ from homeassistant.components.light import (
) )
import homeassistant.util.color as color_util import homeassistant.util.color as color_util
from . import DATA_HIVE, DOMAIN, HiveEntity, refresh_system from . import ATTR_AVAILABLE, ATTR_MODE, DATA_HIVE, DOMAIN, HiveEntity, refresh_system
PARALLEL_UPDATES = 0
SCAN_INTERVAL = timedelta(seconds=15)
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Hive light devices.""" """Set up the Hive Light."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("light")
for dev in discovery_info: entities = []
devs.append(HiveDeviceLight(session, dev)) if devices:
add_entities(devs) for dev in devices:
entities.append(HiveDeviceLight(hive, dev))
async_add_entities(entities, True)
class HiveDeviceLight(HiveEntity, LightEntity): class HiveDeviceLight(HiveEntity, LightEntity):
"""Hive Active Light Device.""" """Hive Active Light Device."""
def __init__(self, hive_session, hive_device):
"""Initialize the Light device."""
super().__init__(hive_session, hive_device)
self.light_device_type = hive_device["Hive_Light_DeviceType"]
@property @property
def unique_id(self): def unique_id(self):
"""Return unique ID of entity.""" """Return unique ID of entity."""
@ -46,59 +48,56 @@ class HiveDeviceLight(HiveEntity, LightEntity):
@property @property
def name(self): def name(self):
"""Return the display name of this light.""" """Return the display name of this light."""
return self.node_name return self.device["haName"]
@property
def available(self):
"""Return if the device is available."""
return self.device["deviceData"]["online"]
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Show Device Attributes.""" """Show Device Attributes."""
return self.attributes return {
ATTR_AVAILABLE: self.attributes.get(ATTR_AVAILABLE),
ATTR_MODE: self.attributes.get(ATTR_MODE),
}
@property @property
def brightness(self): def brightness(self):
"""Brightness of the light (an integer in the range 1-255).""" """Brightness of the light (an integer in the range 1-255)."""
return self.session.light.get_brightness(self.node_id) return self.device["status"]["brightness"]
@property @property
def min_mireds(self): def min_mireds(self):
"""Return the coldest color_temp that this light supports.""" """Return the coldest color_temp that this light supports."""
if ( return self.device.get("min_mireds")
self.light_device_type == "tuneablelight"
or self.light_device_type == "colourtuneablelight"
):
return self.session.light.get_min_color_temp(self.node_id)
@property @property
def max_mireds(self): def max_mireds(self):
"""Return the warmest color_temp that this light supports.""" """Return the warmest color_temp that this light supports."""
if ( return self.device.get("max_mireds")
self.light_device_type == "tuneablelight"
or self.light_device_type == "colourtuneablelight"
):
return self.session.light.get_max_color_temp(self.node_id)
@property @property
def color_temp(self): def color_temp(self):
"""Return the CT color value in mireds.""" """Return the CT color value in mireds."""
if ( return self.device["status"].get("color_temp")
self.light_device_type == "tuneablelight"
or self.light_device_type == "colourtuneablelight"
):
return self.session.light.get_color_temp(self.node_id)
@property @property
def hs_color(self) -> tuple: def hs_color(self):
"""Return the hs color value.""" """Return the hs color value."""
if self.light_device_type == "colourtuneablelight": if self.device["status"]["mode"] == "COLOUR":
rgb = self.session.light.get_color(self.node_id) rgb = self.device["status"].get("hs_color")
return color_util.color_RGB_to_hs(*rgb) return color_util.color_RGB_to_hs(*rgb)
return None
@property @property
def is_on(self): def is_on(self):
"""Return true if light is on.""" """Return true if light is on."""
return self.session.light.get_state(self.node_id) return self.device["status"]["state"]
@refresh_system @refresh_system
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Instruct the light to turn on.""" """Instruct the light to turn on."""
new_brightness = None new_brightness = None
new_color_temp = None new_color_temp = None
@ -116,35 +115,32 @@ class HiveDeviceLight(HiveEntity, LightEntity):
get_new_color = kwargs.get(ATTR_HS_COLOR) get_new_color = kwargs.get(ATTR_HS_COLOR)
hue = int(get_new_color[0]) hue = int(get_new_color[0])
saturation = int(get_new_color[1]) saturation = int(get_new_color[1])
new_color = (hue, saturation, self.brightness) new_color = (hue, saturation, 100)
self.session.light.turn_on( await self.hive.light.turn_on(
self.node_id, self.device, new_brightness, new_color_temp, new_color
self.light_device_type,
new_brightness,
new_color_temp,
new_color,
) )
@refresh_system @refresh_system
def turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Instruct the light to turn off.""" """Instruct the light to turn off."""
self.session.light.turn_off(self.node_id) await self.hive.light.turn_off(self.device)
@property @property
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
supported_features = None supported_features = None
if self.light_device_type == "warmwhitelight": if self.device["hiveType"] == "warmwhitelight":
supported_features = SUPPORT_BRIGHTNESS supported_features = SUPPORT_BRIGHTNESS
elif self.light_device_type == "tuneablelight": elif self.device["hiveType"] == "tuneablelight":
supported_features = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP supported_features = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP
elif self.light_device_type == "colourtuneablelight": elif self.device["hiveType"] == "colourtuneablelight":
supported_features = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR supported_features = SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_COLOR
return supported_features return supported_features
def update(self): async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.attributes = self.session.attributes.state_attributes(self.node_id) self.device = await self.hive.light.get_light(self.device)
self.attributes.update(self.device.get("attributes", {}))

View File

@ -2,6 +2,11 @@
"domain": "hive", "domain": "hive",
"name": "Hive", "name": "Hive",
"documentation": "https://www.home-assistant.io/integrations/hive", "documentation": "https://www.home-assistant.io/integrations/hive",
"requirements": ["pyhiveapi==0.2.20.2"], "requirements": [
"codeowners": ["@Rendili", "@KJonline"] "pyhiveapi==0.3.4.4"
],
"codeowners": [
"@Rendili",
"@KJonline"
]
} }

View File

@ -1,31 +1,32 @@
"""Support for the Hive sensors.""" """Support for the Hive sesnors."""
from homeassistant.const import TEMP_CELSIUS
from datetime import timedelta
from homeassistant.components.sensor import DEVICE_CLASS_BATTERY
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from . import DATA_HIVE, DOMAIN, HiveEntity from . import ATTR_AVAILABLE, DATA_HIVE, DOMAIN, HiveEntity
FRIENDLY_NAMES = { PARALLEL_UPDATES = 0
"Hub_OnlineStatus": "Hive Hub Status", SCAN_INTERVAL = timedelta(seconds=15)
"Hive_OutsideTemperature": "Outside Temperature", DEVICETYPE = {
} "Battery": {"unit": " % ", "type": DEVICE_CLASS_BATTERY},
DEVICETYPE_ICONS = {
"Hub_OnlineStatus": "mdi:switch",
"Hive_OutsideTemperature": "mdi:thermometer",
} }
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Hive sensor devices.""" """Set up the Hive Sensor."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("sensor")
for dev in discovery_info: entities = []
if dev["HA_DeviceType"] in FRIENDLY_NAMES: if devices:
devs.append(HiveSensorEntity(session, dev)) for dev in devices:
add_entities(devs) if dev["hiveType"] in DEVICETYPE:
entities.append(HiveSensorEntity(hive, dev))
async_add_entities(entities, True)
class HiveSensorEntity(HiveEntity, Entity): class HiveSensorEntity(HiveEntity, Entity):
@ -42,29 +43,36 @@ class HiveSensorEntity(HiveEntity, Entity):
return {"identifiers": {(DOMAIN, self.unique_id)}, "name": self.name} return {"identifiers": {(DOMAIN, self.unique_id)}, "name": self.name}
@property @property
def name(self): def available(self):
"""Return the name of the sensor.""" """Return if sensor is available."""
return FRIENDLY_NAMES.get(self.device_type) return self.device.get("deviceData", {}).get("online")
@property @property
def state(self): def device_class(self):
"""Return the state of the sensor.""" """Device class of the entity."""
if self.device_type == "Hub_OnlineStatus": return DEVICETYPE[self.device["hiveType"]].get("type")
return self.session.sensor.hub_online_status(self.node_id)
if self.device_type == "Hive_OutsideTemperature":
return self.session.weather.temperature()
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""
if self.device_type == "Hive_OutsideTemperature": return DEVICETYPE[self.device["hiveType"]].get("unit")
return TEMP_CELSIUS
@property @property
def icon(self): def name(self):
"""Return the icon to use.""" """Return the name of the sensor."""
return DEVICETYPE_ICONS.get(self.device_type) return self.device["haName"]
def update(self): @property
def state(self):
"""Return the state of the sensor."""
return self.device["status"]["state"]
@property
def device_state_attributes(self):
"""Return the state attributes."""
return {ATTR_AVAILABLE: self.attributes.get(ATTR_AVAILABLE)}
async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.device = await self.hive.sensor.get_sensor(self.device)

View File

@ -1,19 +1,26 @@
"""Support for the Hive switches.""" """Support for the Hive switches."""
from datetime import timedelta
from homeassistant.components.switch import SwitchEntity from homeassistant.components.switch import SwitchEntity
from . import DATA_HIVE, DOMAIN, HiveEntity, refresh_system from . import ATTR_AVAILABLE, ATTR_MODE, DATA_HIVE, DOMAIN, HiveEntity, refresh_system
PARALLEL_UPDATES = 0
SCAN_INTERVAL = timedelta(seconds=15)
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up Hive switches.""" """Set up the Hive Switch."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("switch")
for dev in discovery_info: entities = []
devs.append(HiveDevicePlug(session, dev)) if devices:
add_entities(devs) for dev in devices:
entities.append(HiveDevicePlug(hive, dev))
async_add_entities(entities, True)
class HiveDevicePlug(HiveEntity, SwitchEntity): class HiveDevicePlug(HiveEntity, SwitchEntity):
@ -32,34 +39,44 @@ class HiveDevicePlug(HiveEntity, SwitchEntity):
@property @property
def name(self): def name(self):
"""Return the name of this Switch device if any.""" """Return the name of this Switch device if any."""
return self.node_name return self.device["haName"]
@property
def available(self):
"""Return if the device is available."""
return self.device["deviceData"].get("online")
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Show Device Attributes.""" """Show Device Attributes."""
return self.attributes return {
ATTR_AVAILABLE: self.attributes.get(ATTR_AVAILABLE),
ATTR_MODE: self.attributes.get(ATTR_MODE),
}
@property @property
def current_power_w(self): def current_power_w(self):
"""Return the current power usage in W.""" """Return the current power usage in W."""
return self.session.switch.get_power_usage(self.node_id) return self.device["status"]["power_usage"]
@property @property
def is_on(self): def is_on(self):
"""Return true if switch is on.""" """Return true if switch is on."""
return self.session.switch.get_state(self.node_id) return self.device["status"]["state"]
@refresh_system @refresh_system
def turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the switch on.""" """Turn the switch on."""
self.session.switch.turn_on(self.node_id) if self.device["hiveType"] == "activeplug":
await self.hive.switch.turn_on(self.device)
@refresh_system @refresh_system
def turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn the device off.""" """Turn the device off."""
self.session.switch.turn_off(self.node_id) if self.device["hiveType"] == "activeplug":
await self.hive.switch.turn_off(self.device)
def update(self): async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.attributes = self.session.attributes.state_attributes(self.node_id) self.device = await self.hive.switch.get_plug(self.device)

View File

@ -1,4 +1,7 @@
"""Support for hive water heaters.""" """Support for hive water heaters."""
from datetime import timedelta
from homeassistant.components.water_heater import ( from homeassistant.components.water_heater import (
STATE_ECO, STATE_ECO,
STATE_OFF, STATE_OFF,
@ -11,22 +14,36 @@ from homeassistant.const import TEMP_CELSIUS
from . import DATA_HIVE, DOMAIN, HiveEntity, refresh_system from . import DATA_HIVE, DOMAIN, HiveEntity, refresh_system
SUPPORT_FLAGS_HEATER = SUPPORT_OPERATION_MODE SUPPORT_FLAGS_HEATER = SUPPORT_OPERATION_MODE
HOTWATER_NAME = "Hot Water"
PARALLEL_UPDATES = 0
SCAN_INTERVAL = timedelta(seconds=15)
HIVE_TO_HASS_STATE = {
"SCHEDULE": STATE_ECO,
"ON": STATE_ON,
"OFF": STATE_OFF,
}
HASS_TO_HIVE_STATE = {
STATE_ECO: "SCHEDULE",
STATE_ON: "MANUAL",
STATE_OFF: "OFF",
}
HIVE_TO_HASS_STATE = {"SCHEDULE": STATE_ECO, "ON": STATE_ON, "OFF": STATE_OFF}
HASS_TO_HIVE_STATE = {STATE_ECO: "SCHEDULE", STATE_ON: "ON", STATE_OFF: "OFF"}
SUPPORT_WATER_HEATER = [STATE_ECO, STATE_ON, STATE_OFF] SUPPORT_WATER_HEATER = [STATE_ECO, STATE_ON, STATE_OFF]
def setup_platform(hass, config, add_entities, discovery_info=None): async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
"""Set up the Hive water heater devices.""" """Set up the Hive Hotwater."""
if discovery_info is None: if discovery_info is None:
return return
session = hass.data.get(DATA_HIVE) hive = hass.data[DOMAIN].get(DATA_HIVE)
devs = [] devices = hive.devices.get("water_heater")
for dev in discovery_info: entities = []
devs.append(HiveWaterHeater(session, dev)) if devices:
add_entities(devs) for dev in devices:
entities.append(HiveWaterHeater(hive, dev))
async_add_entities(entities, True)
class HiveWaterHeater(HiveEntity, WaterHeaterEntity): class HiveWaterHeater(HiveEntity, WaterHeaterEntity):
@ -50,9 +67,12 @@ class HiveWaterHeater(HiveEntity, WaterHeaterEntity):
@property @property
def name(self): def name(self):
"""Return the name of the water heater.""" """Return the name of the water heater."""
if self.node_name is None: return HOTWATER_NAME
self.node_name = "Hot Water"
return self.node_name @property
def available(self):
"""Return if the device is available."""
return self.device["deviceData"]["online"]
@property @property
def temperature_unit(self): def temperature_unit(self):
@ -62,7 +82,7 @@ class HiveWaterHeater(HiveEntity, WaterHeaterEntity):
@property @property
def current_operation(self): def current_operation(self):
"""Return current operation.""" """Return current operation."""
return HIVE_TO_HASS_STATE[self.session.hotwater.get_mode(self.node_id)] return HIVE_TO_HASS_STATE[self.device["status"]["current_operation"]]
@property @property
def operation_list(self): def operation_list(self):
@ -70,11 +90,22 @@ class HiveWaterHeater(HiveEntity, WaterHeaterEntity):
return SUPPORT_WATER_HEATER return SUPPORT_WATER_HEATER
@refresh_system @refresh_system
def set_operation_mode(self, operation_mode): async def async_turn_on(self, **kwargs):
"""Turn on hotwater."""
await self.hive.hotwater.set_mode(self.device, "MANUAL")
@refresh_system
async def async_turn_off(self, **kwargs):
"""Turn on hotwater."""
await self.hive.hotwater.set_mode(self.device, "OFF")
@refresh_system
async def async_set_operation_mode(self, operation_mode):
"""Set operation mode.""" """Set operation mode."""
new_mode = HASS_TO_HIVE_STATE[operation_mode] new_mode = HASS_TO_HIVE_STATE[operation_mode]
self.session.hotwater.set_mode(self.node_id, new_mode) await self.hive.hotwater.set_mode(self.device, new_mode)
def update(self): async def async_update(self):
"""Update all Node data from Hive.""" """Update all Node data from Hive."""
self.session.core.update_data(self.node_id) await self.hive.session.updateData(self.device)
self.device = await self.hive.hotwater.get_hotwater(self.device)

View File

@ -1434,7 +1434,7 @@ pyheos==0.7.2
pyhik==0.2.8 pyhik==0.2.8
# homeassistant.components.hive # homeassistant.components.hive
pyhiveapi==0.2.20.2 pyhiveapi==0.3.4.4
# homeassistant.components.homematic # homeassistant.components.homematic
pyhomematic==0.1.71 pyhomematic==0.1.71