diff --git a/custom_components/hubitat/binary_sensor.py b/custom_components/hubitat/binary_sensor.py index 88f1d1b..47fc87e 100644 --- a/custom_components/hubitat/binary_sensor.py +++ b/custom_components/hubitat/binary_sensor.py @@ -156,6 +156,7 @@ async def async_setup_entry( if attr[0] in devices[i].attributes ] async_add_entities(sensors) + hub.add_entities(sensors) _LOGGER.debug(f"Added entities for binary sensors: {sensors}") diff --git a/custom_components/hubitat/climate.py b/custom_components/hubitat/climate.py index 21f9f33..7ed8eb4 100644 --- a/custom_components/hubitat/climate.py +++ b/custom_components/hubitat/climate.py @@ -302,3 +302,4 @@ async def async_setup_entry( if is_thermostat(devices[i]) ] async_add_entities(therms) + hub.add_entities(therms) diff --git a/custom_components/hubitat/config_flow.py b/custom_components/hubitat/config_flow.py index 4d0e871..c0c153f 100644 --- a/custom_components/hubitat/config_flow.py +++ b/custom_components/hubitat/config_flow.py @@ -44,6 +44,22 @@ ) +async def validate_input(data: Dict[str, Any]) -> Dict[str, Any]: + """Validate that the user input allows us to connect.""" + + # data has the keys from CONFIG_SCHEMA with values provided by the user. + host: str = data[CONF_HOST] + app_id: str = data[CONF_APP_ID] + token: str = data[CONF_ACCESS_TOKEN] + + hub = HubitatHub(host, app_id, token) + await hub.check_config() + + return { + "label": f"Hubitat ({hub.mac})", + } + + class HubitatConfigFlow(ConfigFlow, domain=DOMAIN): """Handle a config flow for Hubitat.""" @@ -63,7 +79,7 @@ async def async_step_user( if user_input is not None: try: - info = await self.async_validate_input(user_input) + info = await validate_input(user_input) entry_data = deepcopy(user_input) placeholders: Dict[str, str] = {} @@ -104,21 +120,6 @@ async def async_step_user( step_id="user", data_schema=CONFIG_SCHEMA, errors=form_errors, ) - async def async_validate_input(self, data: Dict[str, Any]) -> Dict[str, Any]: - """Validate that the user input allows us to connect.""" - - # data has the keys from CONFIG_SCHEMA with values provided by the user. - host: str = data[CONF_HOST] - app_id: str = data[CONF_APP_ID] - token: str = data[CONF_ACCESS_TOKEN] - - hub = HubitatHub(host, app_id, token) - await hub.check_config() - - return { - "label": f"Hubitat ({hub.mac})", - } - class HubitatOptionsFlow(OptionsFlow): """Handle an options flow for Hubitat.""" diff --git a/custom_components/hubitat/cover.py b/custom_components/hubitat/cover.py index f9e6946..d2a82b3 100644 --- a/custom_components/hubitat/cover.py +++ b/custom_components/hubitat/cover.py @@ -145,4 +145,5 @@ async def async_setup_entry( if cap in devices[i].capabilities ] async_add_entities(covers) + hub.add_entities(covers) _LOGGER.debug(f"Added entities for covers: {covers}") diff --git a/custom_components/hubitat/device.py b/custom_components/hubitat/device.py index 0c277d1..901cf74 100644 --- a/custom_components/hubitat/device.py +++ b/custom_components/hubitat/device.py @@ -3,7 +3,7 @@ from abc import ABC, abstractmethod from json import loads from logging import getLogger -from typing import Any, Callable, Dict, List, Mapping, Optional, Union, cast +from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Union, cast from hubitatmaker import ( CAP_COLOR_CONTROL, @@ -23,6 +23,7 @@ Hub as HubitatHub, ) +from homeassistant.components.sensor import DEVICE_CLASS_TEMPERATURE from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( ATTR_HIDDEN, @@ -66,9 +67,16 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, index: int): self.hass = hass self.config_entry = entry - self.entity_ids: List[int] = [] + self.entities: List["HubitatEntity"] = [] self.event_emitters: List["HubitatEventEmitter"] = [] + self._temperature_unit = ( + entry.options.get( + CONF_TEMPERATURE_UNIT, entry.data.get(CONF_TEMPERATURE_UNIT) + ) + or TEMP_F + ) + if index == 1: self._hub_entity_id = "hubitat.hub" else: @@ -106,23 +114,25 @@ def token(self) -> str: @property def temperature_unit(self) -> str: - entry = self.config_entry - return ( - entry.options.get( - CONF_TEMPERATURE_UNIT, entry.data.get(CONF_TEMPERATURE_UNIT) - ) - or TEMP_F - ) + return self._temperature_unit def add_device_listener(self, device_id: str, listener: Listener): return self._hub.add_device_listener(device_id, listener) - def add_event_emitter(self, emitter: "HubitatEventEmitter") -> None: - self.event_emitters.append(emitter) + def add_entities(self, entities: Sequence["HubitatEntity"]) -> None: + self.entities.extend(entities) + + def add_event_emitters(self, emitters: Sequence["HubitatEventEmitter"]) -> None: + self.event_emitters.extend(emitters) def remove_device_listeners(self, device_id: str) -> None: self._hub.remove_device_listeners(device_id) + def set_temperature_unit(self, temp_unit: str) -> None: + """Set the hub's temperature units.""" + _LOGGER.debug("Setting hub temperature unit to %s", temp_unit) + self._temperature_unit = temp_unit + def stop(self) -> None: self._hub.stop() @@ -180,13 +190,25 @@ async def async_update_device_registry(self) -> None: async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle options update.""" hub = get_hub(hass, entry.entry_id) + port = ( entry.options.get(CONF_SERVER_PORT, entry.data.get(CONF_SERVER_PORT)) or 0 ) if port != hub.port: - _LOGGER.debug("Setting event listener port to %s", port) await hub.set_port(port) + temp_unit = ( + entry.options.get( + CONF_TEMPERATURE_UNIT, entry.data.get(CONF_TEMPERATURE_UNIT) + ) + or TEMP_F + ) + if temp_unit != hub.temperature_unit: + hub.set_temperature_unit(temp_unit) + for entity in hub.entities: + if entity.device_class == DEVICE_CLASS_TEMPERATURE: + entity.async_schedule_update_ha_state() + hass.states.async_set( hub.entity_id, "connected", {CONF_TEMPERATURE_UNIT: hub.temperature_unit} ) @@ -206,7 +228,8 @@ async def send_command( async def set_port(self, port: int) -> None: """Set the port that the event listener server will listen on.""" - return await self._hub.set_port(port) + _LOGGER.debug("Setting event listener port to %s", port) + await self._hub.set_port(port) class HubitatBase(ABC): diff --git a/custom_components/hubitat/light.py b/custom_components/hubitat/light.py index cc91131..5db8ea6 100644 --- a/custom_components/hubitat/light.py +++ b/custom_components/hubitat/light.py @@ -177,4 +177,5 @@ async def async_setup_entry( if is_light(devices[i]) ] async_add_entities(lights) + hub.add_entities(lights) _LOGGER.debug(f"Added entities for lights: {lights}") diff --git a/custom_components/hubitat/lock.py b/custom_components/hubitat/lock.py index 7d1b242..9943336 100644 --- a/custom_components/hubitat/lock.py +++ b/custom_components/hubitat/lock.py @@ -118,6 +118,7 @@ async def async_setup_entry( if CAP_LOCK in devices[i].capabilities ] async_add_entities(locks) + hub.add_entities(locks) _LOGGER.debug(f"Added entities for locks: %s", locks) if len(locks) > 0: diff --git a/custom_components/hubitat/sensor.py b/custom_components/hubitat/sensor.py index 5e3ccf7..8adb133 100644 --- a/custom_components/hubitat/sensor.py +++ b/custom_components/hubitat/sensor.py @@ -161,4 +161,5 @@ async def async_setup_entry( if attr[0] in devices[i].attributes ] async_add_entities(sensors) + hub.add_entities(sensors) _LOGGER.debug(f"Added entities for sensors: {sensors}") diff --git a/custom_components/hubitat/switch.py b/custom_components/hubitat/switch.py index dc9410c..54591d6 100644 --- a/custom_components/hubitat/switch.py +++ b/custom_components/hubitat/switch.py @@ -98,6 +98,7 @@ async def async_setup_entry( else: switches.append(HubitatSwitch(hub=hub, device=s)) async_add_entities(switches) + hub.add_entities(switches) _LOGGER.debug("Added entities for switches: %s", switches) button_controllers = [ @@ -107,5 +108,5 @@ async def async_setup_entry( ] for bc in button_controllers: hass.async_create_task(bc.update_device_registry()) - hub.add_event_emitter(bc) + hub.add_event_emitters(button_controllers) _LOGGER.debug("Added entities for pushbutton controllers: %s", button_controllers)