Skip to content

Commit

Permalink
Added Circuit heat curve, limited by outside temperature, and min flo…
Browse files Browse the repository at this point in the history
…w temperature endpoints
  • Loading branch information
signalkraft committed Oct 30, 2024
1 parent 373fd30 commit 3829a99
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 50 deletions.
50 changes: 3 additions & 47 deletions custom_components/mypyllant/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from myPyllant.models import Circuit, System
from myPyllant.models import System

from . import SystemCoordinator
from .const import DOMAIN
from .utils import EntityList, ZoneCoordinatorEntity
from .utils import EntityList, ZoneCoordinatorEntity, CircuitEntity

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -242,51 +242,7 @@ def unique_id(self) -> str:
return f"{DOMAIN}_{self.id_infix}_eebus_enabled"


class CircuitEntity(CoordinatorEntity, BinarySensorEntity):
def __init__(
self,
system_index: int,
circuit_index: int,
coordinator: SystemCoordinator,
):
super().__init__(coordinator)
self.system_index = system_index
self.circuit_index = circuit_index

@property
def system(self) -> System:
return self.coordinator.data[self.system_index]

@property
def circuit(self) -> Circuit:
return self.coordinator.data[self.system_index].circuits[self.circuit_index]

@property
def name_prefix(self) -> str:
return f"{self.system.home.home_name or self.system.home.nomenclature} Circuit {self.circuit_index}"

@property
def id_infix(self) -> str:
return f"{self.system.id}_circuit_{self.circuit.index}"

@property
def device_info(self) -> DeviceInfo | None:
return DeviceInfo(
identifiers={(DOMAIN, self.id_infix)},
name=self.name_prefix,
manufacturer=self.system.brand_name,
)


class CircuitIsCoolingAllowed(CircuitEntity):
def __init__(
self,
system_index: int,
circuit_index: int,
coordinator: SystemCoordinator,
):
super().__init__(system_index, circuit_index, coordinator)

class CircuitIsCoolingAllowed(CircuitEntity, BinarySensorEntity):
@property
def is_on(self) -> bool | None:
return self.circuit.is_cooling_allowed
Expand Down
94 changes: 93 additions & 1 deletion custom_components/mypyllant/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from homeassistant.components.number import NumberEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTime
from homeassistant.const import UnitOfTime, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

Expand All @@ -16,6 +16,7 @@
SystemCoordinatorEntity,
ZoneCoordinatorEntity,
EntityList,
CircuitEntity,
)

_LOGGER = logging.getLogger(__name__)
Expand All @@ -42,6 +43,20 @@ async def async_setup_entry(
sensors.append(
lambda: ZoneQuickVetoDurationNumber(index, zone_index, coordinator)
)
for circuit_index, circuit in enumerate(system.circuits):
sensors.append(
lambda: CircuitHeatingCurve(index, circuit_index, coordinator)
)
sensors.append(
lambda: CircuitHeatDemandLimitedByOutsideTemperature(
index, circuit_index, coordinator
)
)
sensors.append(
lambda: CircuitMinFlowTemperatureSetpoint(
index, circuit_index, coordinator
)
)
async_add_entities(sensors) # type: ignore


Expand Down Expand Up @@ -180,3 +195,80 @@ def unique_id(self) -> str:
@property
def available(self) -> bool:
return self.zone.quick_veto_ongoing


class CircuitHeatingCurve(CircuitEntity, NumberEntity):
_attr_native_min_value = 0.1
_attr_native_max_value = 5.0
_attr_native_step = 0.0000001
_attr_icon = "mdi:chart-line"

@property
def native_value(self):
return self.circuit.heating_curve

async def async_set_native_value(self, value: float) -> None:
await self.coordinator.api.set_circuit_heating_curve(self.circuit, value)
await self.coordinator.async_request_refresh_delayed()

@property
def name(self) -> str:
return f"{self.name_prefix} Heating Curve"

@property
def unique_id(self) -> str:
return f"{DOMAIN} {self.id_infix}_heating_curve"


class CircuitHeatDemandLimitedByOutsideTemperature(CircuitEntity, NumberEntity):
_attr_native_min_value = 0.0
_attr_native_max_value = 100.0
_attr_native_step = 0.1
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
_attr_icon = "mdi:home-thermometer"

@property
def native_value(self):
return self.circuit.heat_demand_limited_by_outside_temperature

async def async_set_native_value(self, value: float) -> None:
await (
self.coordinator.api.set_circuit_heat_demand_limited_by_outside_temperature(
self.circuit, value
)
)
await self.coordinator.async_request_refresh_delayed()

@property
def name(self) -> str:
return f"{self.name_prefix} Heat Demand Limited by Outside Temperature"

@property
def unique_id(self) -> str:
return f"{DOMAIN} {self.id_infix}_heat_demand_limited_by_outside_temperature"


class CircuitMinFlowTemperatureSetpoint(CircuitEntity, NumberEntity):
_attr_native_min_value = 0.0
_attr_native_max_value = 100.0
_attr_native_step = 0.1
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
_attr_icon = "mdi:thermometer-water"

@property
def native_value(self):
return self.circuit.heating_flow_temperature_minimum_setpoint

async def async_set_native_value(self, value: float) -> None:
await self.coordinator.api.set_circuit_min_flow_temperature_setpoint(
self.circuit, value
)
await self.coordinator.async_request_refresh_delayed()

@property
def name(self) -> str:
return f"{self.name_prefix} Min Flow Temperature Setpoint"

@property
def unique_id(self) -> str:
return f"{DOMAIN} {self.id_infix}_min_flow_temperature_setpoint"
38 changes: 37 additions & 1 deletion custom_components/mypyllant/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

if typing.TYPE_CHECKING:
from custom_components.mypyllant.coordinator import SystemCoordinator
from myPyllant.models import System, DomesticHotWater, Zone, AmbisenseRoom
from myPyllant.models import System, DomesticHotWater, Zone, AmbisenseRoom, Circuit

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -348,3 +348,39 @@ def device_info(self):
@property
def unique_id(self) -> str:
return f"{DOMAIN}_{self.id_infix}_climate"


class CircuitEntity(CoordinatorEntity):
def __init__(
self,
system_index: int,
circuit_index: int,
coordinator: SystemCoordinator,
):
super().__init__(coordinator)
self.system_index = system_index
self.circuit_index = circuit_index

@property
def system(self) -> System:
return self.coordinator.data[self.system_index]

@property
def circuit(self) -> Circuit:
return self.coordinator.data[self.system_index].circuits[self.circuit_index]

@property
def name_prefix(self) -> str:
return f"{self.system.home.home_name or self.system.home.nomenclature} Circuit {self.circuit_index}"

@property
def id_infix(self) -> str:
return f"{self.system.id}_circuit_{self.circuit.index}"

@property
def device_info(self) -> DeviceInfo | None:
return DeviceInfo(
identifiers={(DOMAIN, self.id_infix)},
name=self.name_prefix,
manufacturer=self.system.brand_name,
)
2 changes: 1 addition & 1 deletion tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
from myPyllant.tests.utils import list_test_data, load_test_data

from custom_components.mypyllant.binary_sensor import (
CircuitEntity,
CircuitIsCoolingAllowed,
ControlError,
ControlOnline,
SystemControlEntity,
async_setup_entry,
ZoneIsManualCoolingActive,
)
from custom_components.mypyllant.utils import CircuitEntity
from custom_components.mypyllant.const import DOMAIN
from tests.conftest import MockConfigEntry, TEST_OPTIONS
from tests.test_init import test_user_input
Expand Down

0 comments on commit 3829a99

Please sign in to comment.