Skip to content

Commit

Permalink
Added claim entity for firmware and other controller info, updated un…
Browse files Browse the repository at this point in the history
…derlying library, increased test coverage
  • Loading branch information
signalkraft committed Oct 15, 2023
1 parent 2abb26e commit 4ae0e4b
Show file tree
Hide file tree
Showing 25 changed files with 388 additions and 199 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ repos:
- aioresponses
- pytest
- types-requests
- myPyllant==0.5.9
- myPyllant==0.5.10
- polyfactory
- repo: local
hooks:
Expand Down
106 changes: 41 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![License](https://img.shields.io/github/license/signalkraft/mypyllant-component.svg)](LICENSE)
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/signalkraft/mypyllant-component/build-test.yaml)

Home Assistant component that interfaces with the myVAILLANT API (and branded versions of it, such as the MiGo Link app from Saunier Duval).
Home Assistant component that interfaces with the myVAILLANT API (and branded versions of it, such as the MiGo Link app from Saunier Duval & Bulex).

![myPyllant](https://raw.githubusercontent.com/signalkraft/myPyllant/main/logo.png)

Expand All @@ -18,18 +18,19 @@ Home Assistant component that interfaces with the myVAILLANT API (and branded ve
* Vaillant ECOTEC PLUS boiler + VR940F + sensoCOMFORT
* Vaillant ECOTEC PLUS boiler + VRT380f + sensoNET
* Saunier Duval DUOMAX F30 90 + MISET Radio + MiLink V3
* [More are documented here](https://signalkraft.com/mypyllant-component/#tested-setups)

Not affiliated with Vaillant, the developers take no responsibility for anything that happens to your devices
because of this library.

## Features

![Screenshot](https://raw.githubusercontent.com/signalkraft/mypyllant-component/main/screenshot.png)
![Default Dashboard Screenshot](docs/docs/assets/default-dashboard.png)

* Supports climate & hot water controls, as well as sensor information
* Control operating modes, target temperature, and presets such as holiday more or quick veto
* Track sensor information of devices, such as temperature, humidity, operating mode, energy usage, or energy efficiency
* See diagnostic information, such as the current heating curve, flow temperature, or water pressure
* See diagnostic information, such as the current heating curve, flow temperature, firmware versions, or water pressure
* Custom services to set holiday mode or quick veto temperature overrides, and their duration

## Installation
Expand All @@ -48,7 +49,7 @@ because of this library.
2. Extract the `custom_components` folder to your Home Assistant's config folder, the resulting folder structure should be `config/custom_components/mypyllant`
3. Restart Home Assistant
4. [Add myVaillant integration](https://my.home-assistant.io/redirect/config_flow_start/?domain=mypyllant), or go to Settings > Integrations and add myVAILLANT
5. Sign in with the email & password you used in the myVAILLANT app (or MiGo app for Saunier Duval)
5. Sign in with the email & password you used in the myVAILLANT app (or MiGo app for Saunier Duval & Bulex)

## Options

Expand Down Expand Up @@ -90,40 +91,40 @@ With debugging enabled, there's a chance to find the culprit in the data returne
You can expect these entities, although names may vary based on your installed devices (in this example "aroTHERM plus"
and "Hydraulic Station") or the naming of your heating zones (in this case "Zone 1"):

| Entity | Unit | Class | Sample |
|------------------------------|--------|---------|----------|
| Cooling Allowed in Circuit 0 | | | off |
| Error sensoCOMFORT | | problem | off |
| Online Status sensoCOMFORT | | connectivity | on |
| Cooling Allowed in Circuit 0 | | | off |
| Zone 1 | | | auto |
| aroTHERM plus Consumed Electrical Energy Domestic Hot Water | Wh | energy | 0 |
| aroTHERM plus Consumed Electrical Energy Heating | Wh | energy | 0 |
| aroTHERM plus Earned Environment Energy Domestic Hot Water | Wh | energy | 0 |
| aroTHERM plus Earned Environment Energy Heating | Wh | energy | 334.5 |
| aroTHERM plus Heat Generated Heating | Wh | energy | 334.5 |
| aroTHERM plus Heat Generated Domestic Hot Water | Wh | energy | 0 |
| Hydraulic Station Consumed Electrical Energy Domestic Hot Water | Wh | energy | 0 |
| Heating Energy Efficiency | | | 4 |
| Cooling Allowed in Circuit 0 | | | off |
| Current Flow Temperature in Circuit 0 | °C | temperature | 22.0 |
| Heating Curve in Circuit 0 | | | 0.8 |
| Min Flow Temperature Setpoint in Circuit 0 | °C | temperature | 35.0 |
| State in Circuit 0 | | | STANDBY |
| Desired Temperature in Zone 1 | °C | temperature | 0.0 |
| Current Temperature in Zone 1 | °C | temperature | 18.5 |
| Humidity in Zone 1 | % | humidity | 60.0 |
| Heating Operating Mode in Zone 1 | | | Time Controlled |
| Heating State in Zone 1 | | | Idle |
| Current Special Function in Zone 1 | | | None |
| Tank Temperature Domestic Hot Water 255 | °C | temperature | 47.0 |
| Setpoint Domestic Hot Water 255 | °C | temperature | 49.0 |
| Operation Mode Domestic Hot Water 255 | | | Time Controlled |
| Current Special Function Domestic Hot Water 255 | | | Regular |
| Domestic Hot Water 0 | | | Time Controlled |
| Outdoor Temperature | °C | temperature | 2.29 |
| System Mode | | | REGULAR |
| Water Pressure | bar | pressure | 1.4 |
| Entity | Unit | Class | Sample |
|-----------------------------------------------------------------|--------|--------------|---------------------------|
| Outdoor Temperature | °C | temperature | 16.7 |
| System Water Pressure | bar | pressure | 1.0 |
| My Home VR 921 | | | 0357.40.30 |
| Desired Temperature in Zone 1 | °C | temperature | 5.0 |
| Current Temperature in Zone 1 | °C | temperature | 20.9 |
| Humidity in Zone 1 | % | humidity | 60.0 |
| Heating Operating Mode in Zone 1 | | | Off |
| Heating State in Zone 1 | | | Idle |
| Current Special Function in Zone 1 | | | None |
| State in Circuit 0 | | | STANDBY |
| Current Flow Temperature in Circuit 0 | °C | temperature | 35.5 |
| Heating Curve in Circuit 0 | | | 0.68 |
| Tank Temperature Domestic Hot Water 255 | °C | temperature | 48.5 |
| Setpoint Domestic Hot Water 255 | °C | temperature | 50.0 |
| Operation Mode Domestic Hot Water 255 | | | Time Controlled |
| Current Special Function Domestic Hot Water 255 | | | Regular |
| Heating Energy Efficiency | | | 3.0 |
| aroTHERM plus Consumed Electrical Energy Domestic Hot Water | Wh | energy | 2000.0 |
| aroTHERM plus Consumed Electrical Energy Heating | Wh | energy | 1000.0 |
| aroTHERM plus Earned Environment Energy Domestic Hot Water | Wh | energy | 6000.0 |
| aroTHERM plus Earned Environment Energy Heating | Wh | energy | 0.0 |
| aroTHERM plus Heat Generated Heating | Wh | energy | 1000.0 |
| aroTHERM plus Heat Generated Domestic Hot Water | Wh | energy | 8000.0 |
| hydraulic station Consumed Electrical Energy Domestic Hot Water | Wh | energy | 0.0 |
| hydraulic station Consumed Electrical Energy Heating | Wh | energy | 0.0 |
| Domestic Hot Water 0 | | | Time Controlled |
| Zone 1 | | | off |
| Trouble Codes on aroTHERM plus | | problem | off |
| Online Status aroTHERM plus | | connectivity | on |
| Firmware Update Required My Home VR 921 | | update | off |
| Firmware Update Enabled My Home VR 921 | | | on |
| Cooling Allowed in Circuit 0 | | | off |

## Services

Expand All @@ -134,32 +135,7 @@ Search for "myvaillant" in Developer Tools > Services in your Home Assistant ins

## Contributing

> **Warning**
>
> You need at least Python 3.10.
Fork and clone this repo, then from the root directory run:

```shell
python3 -m venv .venv
source .venv/bin/activate
pip install -r dev-requirements.txt
pre-commit install
# Make your changes
pytest
git commit ...
```

If you also need to modify the underlying [myPyllant library](https://github.com/signalkraft/mypyllant),
clone & install it in editable mode in `mypyllant-component`:

```shell
# From the root of this repository
git clone https://github.com/signalkraft/myPyllant.git ../myPyllant
pip install -e ../myPyllant
```

Now you can modify `myPyllant/src` and directly develop against these changes in `mypyllant-component`.
See [the docs on contributing](https://signalkraft.com/mypyllant-component/3-contributing/).

### Debugging

Expand All @@ -176,4 +152,4 @@ logger:
### Contributing to the underlying mypyllant library
See https://github.com/signalkraft/mypyllant#contributing
See [this section on the contributing docs](https://signalkraft.com/mypyllant-component/3-contributing/#contributing-to-the-underlying-mypyllant-library).
20 changes: 16 additions & 4 deletions custom_components/mypyllant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if _LOGGER.isEnabledFor(logging.DEBUG):
from importlib.metadata import version

_LOGGER.debug(
"Starting mypyllant component %s (library %s) with homeassistant %s, dacite %s, and aiohttp %s",
hass.data["integrations"][DOMAIN].version,
version("myPyllant"),
version("homeassistant"),
version("dacite"),
version("aiohttp"),
)
username = entry.data.get("username")
password = entry.data.get("password")
update_interval = entry.options.get(OPTION_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL)
Expand Down Expand Up @@ -96,7 +107,7 @@ def __init__(
hass: HomeAssistant,
api: MyPyllantAPI,
entry: ConfigEntry,
update_interval: timedelta,
update_interval: timedelta | None,
) -> None:
self.api = api
self.hass = hass
Expand Down Expand Up @@ -158,14 +169,15 @@ async def async_request_refresh_delayed(self):
This function waits for a few second and then refreshes
"""
delay = self.entry.options.get(OPTION_REFRESH_DELAY, DEFAULT_REFRESH_DELAY)
await asyncio.sleep(delay)
if delay:
await asyncio.sleep(delay)
await self.async_request_refresh()


class SystemCoordinator(MyPyllantCoordinator):
data: list[System]

async def _async_update_data(self) -> list[System] | None:
async def _async_update_data(self) -> list[System]:
self._raise_if_quota_hit()
_LOGGER.debug("Starting async update data for SystemCoordinator")
try:
Expand All @@ -179,7 +191,7 @@ async def _async_update_data(self) -> list[System] | None:
return data
except ClientResponseError as e:
self._set_quota(e)
return None
return []


class DailyDataCoordinator(MyPyllantCoordinator):
Expand Down
73 changes: 32 additions & 41 deletions custom_components/mypyllant/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,55 +35,16 @@ async def async_setup_entry(

sensors: list[BinarySensorEntity] = []
for index, system in enumerate(coordinator.data):
sensors.append(ClaimEntity(index, coordinator))
sensors.append(ControlError(index, coordinator))
sensors.append(ControlOnline(index, coordinator))
sensors.append(FirmwareUpdateRequired(index, coordinator))
sensors.append(FirmwareUpdateEnabled(index, coordinator))
for circuit_index, circuit in enumerate(system.circuits):
sensors.append(CircuitIsCoolingAllowed(index, circuit_index, coordinator))

async_add_entities(sensors)


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

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

@property
def entity_category(self) -> EntityCategory | None:
return EntityCategory.DIAGNOSTIC

@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
attr = {
"firmware": self.system.claim.firmware,
}
return attr

@property
def device_info(self):
return DeviceInfo(
identifiers={(DOMAIN, f"claim{self.system.id}")},
name=self.system.claim.nomenclature,
manufacturer=self.system.brand_name,
model=self.system.claim.nomenclature,
sw_version=self.system.claim.firmware_version,
)

@property
def name(self) -> str:
return self.system.claim.name


class SystemControlEntity(CoordinatorEntity, BinarySensorEntity):
def __init__(
self,
Expand Down Expand Up @@ -216,7 +177,7 @@ def is_on(self) -> bool | None:

@property
def name(self) -> str:
return f"Firmware Update Required {self.system.system_name}"
return f"Firmware Update Required {self.system.claim.name}"

@property
def unique_id(self) -> str:
Expand All @@ -226,6 +187,36 @@ def unique_id(self) -> str:
def device_class(self) -> BinarySensorDeviceClass | None:
return BinarySensorDeviceClass.UPDATE

@property
def device_info(self) -> DeviceInfo | None:
return {"identifiers": {(DOMAIN, f"claim{self.system.id}")}}


class FirmwareUpdateEnabled(SystemControlEntity):
def __init__(
self,
system_index: int,
coordinator: SystemCoordinator,
):
super().__init__(system_index, coordinator)
self.entity_id = f"{DOMAIN}.firmware_update_enabled_{system_index}"

@property
def is_on(self) -> bool | None:
return self.system.claim.firmware.get("update_enabled", None)

@property
def name(self) -> str:
return f"Firmware Update Enabled {self.system.claim.name}"

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

@property
def device_info(self) -> DeviceInfo | None:
return {"identifiers": {(DOMAIN, f"claim{self.system.id}")}}


class CircuitIsCoolingAllowed(CircuitEntity):
def __init__(
Expand Down
2 changes: 1 addition & 1 deletion custom_components/mypyllant/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/signalkraft/issues",
"requirements": ["myPyllant==0.5.9"],
"requirements": ["myPyllant==0.5.10"],
"version": "0.5.2b0"
}
Loading

0 comments on commit 4ae0e4b

Please sign in to comment.