Skip to content

Commit

Permalink
Update to follow latest HA Core PRs
Browse files Browse the repository at this point in the history
This includes the current HA Core dev branch plus the vicare_config_flow PR:
home-assistant/core#56691
  • Loading branch information
oischinger committed Nov 1, 2021
1 parent ac1c451 commit 812dee3
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 38 deletions.
28 changes: 14 additions & 14 deletions custom_components/vicare/__init__.py
Expand Up @@ -25,6 +25,7 @@
CONF_CIRCUIT,
CONF_HEATING_TYPE,
DEFAULT_HEATING_TYPE,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
HEATING_TYPE_TO_CREATOR_METHOD,
PLATFORMS,
Expand Down Expand Up @@ -54,16 +55,16 @@ class ViCareRequiredKeysMixin:
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=60): vol.All(
cv.time_period, lambda value: value.total_seconds()
),
vol.Optional(
CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL
): vol.All(cv.time_period, lambda value: value.total_seconds()),
vol.Optional(
CONF_CIRCUIT
): int, # Ignored: All circuits are now supported. Will be removed when switching to Setup via UI.
vol.Optional(CONF_NAME, default="ViCare"): cv.string,
vol.Optional(
CONF_HEATING_TYPE, default=DEFAULT_HEATING_TYPE
): cv.enum(HeatingType),
CONF_HEATING_TYPE, default=DEFAULT_HEATING_TYPE.value
): vol.In([e.value for e in HeatingType]),
}
),
)
Expand Down Expand Up @@ -99,15 +100,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN][entry.entry_id][VICARE_NAME] = entry.data[CONF_NAME]

if entry.data.get(CONF_HEATING_TYPE) is not None:
heating_type = entry.data.get(CONF_HEATING_TYPE)
if type(heating_type) is HeatingType:
hass.data[DOMAIN][entry.entry_id][CONF_HEATING_TYPE] = heating_type
else:
hass.data[DOMAIN][entry.entry_id][CONF_HEATING_TYPE] = HeatingType[
entry.data[CONF_HEATING_TYPE]
]
hass.data[DOMAIN][entry.entry_id][CONF_HEATING_TYPE] = entry.data.get(
CONF_HEATING_TYPE
)
else:
hass.data[DOMAIN][entry.entry_id][CONF_HEATING_TYPE] = DEFAULT_HEATING_TYPE
hass.data[DOMAIN][entry.entry_id][
CONF_HEATING_TYPE
] = DEFAULT_HEATING_TYPE.value

# For previous config entries where unique_id is None
if entry.unique_id is None:
Expand Down Expand Up @@ -148,7 +147,8 @@ def setup_vicare_api(hass, conf, entity_data):
)
entity_data[VICARE_DEVICE_CONFIG] = device
entity_data[VICARE_API] = getattr(
device, HEATING_TYPE_TO_CREATOR_METHOD[conf[CONF_HEATING_TYPE]]
device,
HEATING_TYPE_TO_CREATOR_METHOD[HeatingType(entity_data[CONF_HEATING_TYPE])],
)()

entity_data[VICARE_CIRCUITS] = entity_data[VICARE_API].circuits
Expand Down
7 changes: 3 additions & 4 deletions custom_components/vicare/binary_sensor.py
Expand Up @@ -84,7 +84,7 @@ def _build_entity(name, vicare_api, device_config, sensor):


async def _entities_from_descriptions(
hass, name, all_devices, sensor_descriptions, iterables
hass, name, all_devices, sensor_descriptions, iterables, config_entry
):
"""Create entities from descriptions and list of burners/circuits."""
for description in sensor_descriptions:
Expand All @@ -103,7 +103,6 @@ async def _entities_from_descriptions(
all_devices.append(entity)



async def async_setup_entry(hass, config_entry, async_add_devices):
"""Create the ViCare binary sensor devices."""
name = hass.data[DOMAIN][config_entry.entry_id][VICARE_NAME]
Expand All @@ -128,14 +127,14 @@ async def async_setup_entry(hass, config_entry, async_add_devices):

try:
_entities_from_descriptions(
hass, name, all_devices, BURNER_SENSORS, api.burners
hass, name, all_devices, BURNER_SENSORS, api.burners, config_entry
)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("No burners found")

try:
_entities_from_descriptions(
hass, name, all_devices, COMPRESSOR_SENSORS, api.compressors
hass, name, all_devices, COMPRESSOR_SENSORS, api.compressors, config_entry
)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("No compressors found")
Expand Down
15 changes: 7 additions & 8 deletions custom_components/vicare/climate.py
Expand Up @@ -24,6 +24,7 @@
)
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS
from homeassistant.helpers import entity_platform
import homeassistant.helpers.config_validation as cv

from .const import (
CONF_HEATING_TYPE,
Expand Down Expand Up @@ -122,11 +123,7 @@ async def async_setup_entry(hass, config_entry, async_add_devices):

platform.async_register_entity_service(
SERVICE_SET_VICARE_MODE,
{
vol.Required(SERVICE_SET_VICARE_MODE_ATTR_MODE): vol.In(
VICARE_TO_HA_HVAC_HEATING
)
},
{vol.Required(SERVICE_SET_VICARE_MODE_ATTR_MODE): cv.string},
"set_vicare_mode",
)

Expand Down Expand Up @@ -154,7 +151,7 @@ def __init__(self, name, api, circuit, device_config, heating_type):
@property
def unique_id(self):
"""Return unique ID for this device."""
return f"{self._device_config.getConfig().serial}-climate-{self._circuit.id}"
return f"{self._device_config.getConfig().serial}-{self._circuit.id}"

@property
def device_info(self):
Expand Down Expand Up @@ -210,6 +207,8 @@ def update(self):
"heating_curve_shift"
] = self._circuit.getHeatingCurveShift()

self._attributes["vicare_modes"] = self._circuit.getModes()

self._current_action = False
# Update the specific device attributes
with suppress(PyViCareNotSupportedFeatureError):
Expand Down Expand Up @@ -334,7 +333,7 @@ def extra_state_attributes(self):

def set_vicare_mode(self, vicare_mode):
"""Service function to set vicare modes directly."""
if vicare_mode not in VICARE_TO_HA_HVAC_HEATING:
raise ValueError(f"Cannot set invalid vicare mode: {vicare_mode}")
if vicare_mode not in self._attributes["vicare_modes"]:
raise ValueError(f"Cannot set invalid vicare mode: {vicare_mode}.")

self._circuit.setMode(vicare_mode)
8 changes: 3 additions & 5 deletions custom_components/vicare/config_flow.py
Expand Up @@ -25,6 +25,7 @@
DEFAULT_HEATING_TYPE,
DEFAULT_SCAN_INTERVAL,
DOMAIN,
HeatingType,
)

_LOGGER = logging.getLogger(__name__)
Expand All @@ -44,8 +45,8 @@ async def async_step_user(self, user_input: dict[str, Any] | None = None):
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Optional(CONF_HEATING_TYPE, default=DEFAULT_HEATING_TYPE): vol.In(
[DEFAULT_HEATING_TYPE, "gas", "heatpump", "fuelcell"]
vol.Optional(CONF_HEATING_TYPE, default=DEFAULT_HEATING_TYPE.value): vol.In(
[e.value for e in HeatingType]
),
vol.Optional(CONF_NAME, default="ViCare"): cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): vol.All(
Expand Down Expand Up @@ -88,9 +89,6 @@ async def async_step_dhcp(self, discovery_info):
async def async_step_import(self, import_info):
"""Handle a flow initiated by a YAML config import."""

# Convert existing setups to autodetected heating type
import_info[CONF_HEATING_TYPE] = DEFAULT_HEATING_TYPE

await self.async_set_unique_id("Configuration.yaml")
self._abort_if_unique_id_configured()

Expand Down
20 changes: 20 additions & 0 deletions custom_components/vicare/const.py
@@ -1,6 +1,13 @@
"""Constants for the ViCare integration."""
import enum

from homeassistant.const import (
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_GAS,
ENERGY_KILO_WATT_HOUR,
VOLUME_CUBIC_METERS,
)

DOMAIN = "vicare"

PLATFORMS = ["climate", "sensor", "binary_sensor", "water_heater"]
Expand All @@ -15,6 +22,19 @@

DEFAULT_SCAN_INTERVAL = 60

VICARE_CUBIC_METER = "cubicMeter"
VICARE_KWH = "kilowattHour"

VICARE_UNIT_TO_DEVICE_CLASS = {
VICARE_KWH: DEVICE_CLASS_ENERGY,
VICARE_CUBIC_METER: DEVICE_CLASS_GAS,
}

VICARE_UNIT_TO_UNIT_OF_MEASUREMENT = {
VICARE_KWH: ENERGY_KILO_WATT_HOUR,
VICARE_CUBIC_METER: VOLUME_CUBIC_METERS,
}


class HeatingType(enum.Enum):
"""Possible options for heating type."""
Expand Down
41 changes: 35 additions & 6 deletions custom_components/vicare/sensor.py
Expand Up @@ -4,7 +4,9 @@
from contextlib import suppress
from dataclasses import dataclass
import logging
from typing import Callable

from PyViCare.PyViCareDevice import Device
from PyViCare.PyViCareUtils import (
PyViCareInvalidDataError,
PyViCareNotSupportedFeatureError,
Expand All @@ -13,6 +15,7 @@
import requests

from homeassistant.components.sensor import (
STATE_CLASS_MEASUREMENT,
STATE_CLASS_TOTAL_INCREASING,
SensorEntity,
SensorEntityDescription,
Expand All @@ -30,7 +33,14 @@
import homeassistant.util.dt as dt_util

from . import ViCareRequiredKeysMixin
from .const import DOMAIN, VICARE_API, VICARE_DEVICE_CONFIG, VICARE_NAME
from .const import (
DOMAIN,
VICARE_API,
VICARE_DEVICE_CONFIG,
VICARE_NAME,
VICARE_UNIT_TO_DEVICE_CLASS,
VICARE_UNIT_TO_UNIT_OF_MEASUREMENT,
)

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -74,6 +84,8 @@
class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysMixin):
"""Describes ViCare sensor entity."""

unit_getter: Callable[[Device], str | None] | None = None


GLOBAL_SENSORS: tuple[ViCareSensorEntityDescription, ...] = (
ViCareSensorEntityDescription(
Expand Down Expand Up @@ -102,6 +114,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Hot water gas consumption today",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionDomesticHotWaterToday(),
unit_getter=lambda api: api.getGasConsumptionDomesticHotWaterUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -110,6 +123,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Hot water gas consumption this week",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionDomesticHotWaterThisWeek(),
unit_getter=lambda api: api.getGasConsumptionDomesticHotWaterUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -118,6 +132,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Hot water gas consumption this month",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionDomesticHotWaterThisMonth(),
unit_getter=lambda api: api.getGasConsumptionDomesticHotWaterUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -126,6 +141,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Hot water gas consumption this year",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionDomesticHotWaterThisYear(),
unit_getter=lambda api: api.getGasConsumptionDomesticHotWaterUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -134,6 +150,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Heating gas consumption today",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionHeatingToday(),
unit_getter=lambda api: api.getGasConsumptionHeatingUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -142,6 +159,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Heating gas consumption this week",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionHeatingThisWeek(),
unit_getter=lambda api: api.getGasConsumptionHeatingUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -150,6 +168,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Heating gas consumption this month",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionHeatingThisMonth(),
unit_getter=lambda api: api.getGasConsumptionHeatingUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -158,6 +177,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
name="Heating gas consumption this year",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
value_getter=lambda api: api.getGasConsumptionHeatingThisYear(),
unit_getter=lambda api: api.getGasConsumptionHeatingUnit(),
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
Expand All @@ -167,7 +187,7 @@ class ViCareSensorEntityDescription(SensorEntityDescription, ViCareRequiredKeysM
native_unit_of_measurement=POWER_WATT,
value_getter=lambda api: api.getPowerProductionCurrent(),
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_TOTAL_INCREASING,
state_class=STATE_CLASS_MEASUREMENT,
),
ViCareSensorEntityDescription(
key=SENSOR_POWER_PRODUCTION_TODAY,
Expand Down Expand Up @@ -292,6 +312,15 @@ def _build_entity(name, vicare_api, device_config, sensor):
_LOGGER.debug("Found device %s", name)
try:
sensor.value_getter(vicare_api)

if sensor.unit_getter:
with suppress(PyViCareNotSupportedFeatureError):
vicare_unit = sensor.unit_getter(vicare_api)
if vicare_unit is not None:
sensor.device_class = VICARE_UNIT_TO_DEVICE_CLASS.get(vicare_unit)
sensor.native_unit_of_measurement = (
VICARE_UNIT_TO_UNIT_OF_MEASUREMENT.get(vicare_unit)
)
_LOGGER.debug("Found entity %s", name)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("Feature not supported %s", name)
Expand All @@ -309,7 +338,7 @@ def _build_entity(name, vicare_api, device_config, sensor):


async def _entities_from_descriptions(
hass, name, all_devices, sensor_descriptions, iterables
hass, name, all_devices, sensor_descriptions, iterables, config_entry
):
"""Create entities from descriptions and list of burners/circuits."""
for description in sensor_descriptions:
Expand All @@ -321,7 +350,7 @@ async def _entities_from_descriptions(
_build_entity,
f"{name} {description.name}{suffix}",
current,
hass.data[DOMAIN][VICARE_DEVICE_CONFIG],
hass.data[DOMAIN][config_entry.entry_id][VICARE_DEVICE_CONFIG],
description,
)
if entity is not None:
Expand Down Expand Up @@ -362,14 +391,14 @@ async def async_setup_entry(hass, config_entry, async_add_devices):

try:
_entities_from_descriptions(
hass, name, all_devices, BURNER_SENSORS, api.burners
hass, name, all_devices, BURNER_SENSORS, api.burners, config_entry
)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("No burners found")

try:
_entities_from_descriptions(
hass, name, all_devices, COMPRESSOR_SENSORS, api.compressors
hass, name, all_devices, COMPRESSOR_SENSORS, api.compressors, config_entry
)
except PyViCareNotSupportedFeatureError:
_LOGGER.info("No compressors found")
Expand Down
2 changes: 1 addition & 1 deletion custom_components/vicare/water_heater.py
Expand Up @@ -132,7 +132,7 @@ def update(self):
@property
def unique_id(self):
"""Return unique ID for this device."""
return f"{self._device_config.getConfig().serial}-water-{self._circuit.id}"
return f"{self._device_config.getConfig().serial}-{self._circuit.id}"

@property
def device_info(self):
Expand Down

0 comments on commit 812dee3

Please sign in to comment.