forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Komfovent (home-assistant#95722)
* komfovent integration V1 * add dependency * integrate komfovent api * fix errors found in testing * tests for form handling * update deps * update coverage rc * add correct naming * minor feedback * pre-commit fixes * feedback fixes part 1 of 2 * feedback fixes part 2 of 2 * add hvac mode support * fix tests * address feedback * fix code coverage + PR feedback * PR feedback * use device name --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
- Loading branch information
Showing
15 changed files
with
454 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Validating CODEOWNERS rules …
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
"""The Komfovent integration.""" | ||
from __future__ import annotations | ||
|
||
import komfovent_api | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.exceptions import ConfigEntryNotReady | ||
|
||
from .const import DOMAIN | ||
|
||
PLATFORMS: list[Platform] = [Platform.CLIMATE] | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up Komfovent from a config entry.""" | ||
host = entry.data[CONF_HOST] | ||
username = entry.data[CONF_USERNAME] | ||
password = entry.data[CONF_PASSWORD] | ||
_, credentials = komfovent_api.get_credentials(host, username, password) | ||
result, settings = await komfovent_api.get_settings(credentials) | ||
if result != komfovent_api.KomfoventConnectionResult.SUCCESS: | ||
raise ConfigEntryNotReady(f"Unable to connect to {host}: {result}") | ||
|
||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = (credentials, settings) | ||
|
||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) | ||
return True | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
"""Ventilation Units from Komfovent integration.""" | ||
from __future__ import annotations | ||
|
||
import komfovent_api | ||
|
||
from homeassistant.components.climate import ( | ||
ClimateEntity, | ||
ClimateEntityFeature, | ||
HVACMode, | ||
) | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.const import UnitOfTemperature | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.device_registry import DeviceInfo | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
|
||
from .const import DOMAIN | ||
|
||
HASS_TO_KOMFOVENT_MODES = { | ||
HVACMode.COOL: komfovent_api.KomfoventModes.COOL, | ||
HVACMode.HEAT_COOL: komfovent_api.KomfoventModes.HEAT_COOL, | ||
HVACMode.OFF: komfovent_api.KomfoventModes.OFF, | ||
HVACMode.AUTO: komfovent_api.KomfoventModes.AUTO, | ||
} | ||
KOMFOVENT_TO_HASS_MODES = {v: k for k, v in HASS_TO_KOMFOVENT_MODES.items()} | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
entry: ConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Set up the Komfovent unit control.""" | ||
credentials, settings = hass.data[DOMAIN][entry.entry_id] | ||
async_add_entities([KomfoventDevice(credentials, settings)], True) | ||
|
||
|
||
class KomfoventDevice(ClimateEntity): | ||
"""Representation of a ventilation unit.""" | ||
|
||
_attr_hvac_modes = list(HASS_TO_KOMFOVENT_MODES.keys()) | ||
_attr_preset_modes = [mode.name for mode in komfovent_api.KomfoventPresets] | ||
_attr_supported_features = ClimateEntityFeature.PRESET_MODE | ||
_attr_temperature_unit = UnitOfTemperature.CELSIUS | ||
_attr_has_entity_name = True | ||
_attr_name = None | ||
|
||
def __init__( | ||
self, | ||
credentials: komfovent_api.KomfoventCredentials, | ||
settings: komfovent_api.KomfoventSettings, | ||
) -> None: | ||
"""Initialize the ventilation unit.""" | ||
self._komfovent_credentials = credentials | ||
self._komfovent_settings = settings | ||
|
||
self._attr_unique_id = settings.serial_number | ||
self._attr_device_info = DeviceInfo( | ||
identifiers={(DOMAIN, settings.serial_number)}, | ||
model=settings.model, | ||
name=settings.name, | ||
serial_number=settings.serial_number, | ||
sw_version=settings.version, | ||
manufacturer="Komfovent", | ||
) | ||
|
||
async def async_set_preset_mode(self, preset_mode: str) -> None: | ||
"""Set new target preset mode.""" | ||
await komfovent_api.set_preset( | ||
self._komfovent_credentials, | ||
komfovent_api.KomfoventPresets[preset_mode], | ||
) | ||
|
||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: | ||
"""Set new target hvac mode.""" | ||
await komfovent_api.set_mode( | ||
self._komfovent_credentials, HASS_TO_KOMFOVENT_MODES[hvac_mode] | ||
) | ||
|
||
async def async_update(self) -> None: | ||
"""Get the latest data.""" | ||
result, status = await komfovent_api.get_unit_status( | ||
self._komfovent_credentials | ||
) | ||
if result != komfovent_api.KomfoventConnectionResult.SUCCESS or not status: | ||
self._attr_available = False | ||
return | ||
self._attr_available = True | ||
self._attr_preset_mode = status.preset | ||
self._attr_current_temperature = status.temp_extract | ||
self._attr_hvac_mode = KOMFOVENT_TO_HASS_MODES[status.mode] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
"""Config flow for Komfovent integration.""" | ||
from __future__ import annotations | ||
|
||
import logging | ||
from typing import Any | ||
|
||
import komfovent_api | ||
import voluptuous as vol | ||
|
||
from homeassistant import config_entries | ||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME | ||
from homeassistant.data_entry_flow import FlowResult | ||
|
||
from .const import DOMAIN | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
STEP_USER = "user" | ||
STEP_USER_DATA_SCHEMA = vol.Schema( | ||
{ | ||
vol.Required(CONF_HOST): str, | ||
vol.Optional(CONF_USERNAME, default="user"): str, | ||
vol.Required(CONF_PASSWORD): str, | ||
} | ||
) | ||
|
||
ERRORS_MAP = { | ||
komfovent_api.KomfoventConnectionResult.NOT_FOUND: "cannot_connect", | ||
komfovent_api.KomfoventConnectionResult.UNAUTHORISED: "invalid_auth", | ||
komfovent_api.KomfoventConnectionResult.INVALID_INPUT: "invalid_input", | ||
} | ||
|
||
|
||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): | ||
"""Handle a config flow for Komfovent.""" | ||
|
||
VERSION = 1 | ||
|
||
def __return_error( | ||
self, result: komfovent_api.KomfoventConnectionResult | ||
) -> FlowResult: | ||
return self.async_show_form( | ||
step_id=STEP_USER, | ||
data_schema=STEP_USER_DATA_SCHEMA, | ||
errors={"base": ERRORS_MAP.get(result, "unknown")}, | ||
) | ||
|
||
async def async_step_user( | ||
self, user_input: dict[str, Any] | None = None | ||
) -> FlowResult: | ||
"""Handle the initial step.""" | ||
if user_input is None: | ||
return self.async_show_form( | ||
step_id=STEP_USER, data_schema=STEP_USER_DATA_SCHEMA | ||
) | ||
|
||
conf_host = user_input[CONF_HOST] | ||
conf_username = user_input[CONF_USERNAME] | ||
conf_password = user_input[CONF_PASSWORD] | ||
|
||
result, credentials = komfovent_api.get_credentials( | ||
conf_host, conf_username, conf_password | ||
) | ||
if result != komfovent_api.KomfoventConnectionResult.SUCCESS: | ||
return self.__return_error(result) | ||
|
||
result, settings = await komfovent_api.get_settings(credentials) | ||
if result != komfovent_api.KomfoventConnectionResult.SUCCESS: | ||
return self.__return_error(result) | ||
|
||
await self.async_set_unique_id(settings.serial_number) | ||
self._abort_if_unique_id_configured() | ||
|
||
return self.async_create_entry(title=settings.name, data=user_input) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
"""Constants for the Komfovent integration.""" | ||
|
||
DOMAIN = "komfovent" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"domain": "komfovent", | ||
"name": "Komfovent", | ||
"codeowners": ["@ProstoSanja"], | ||
"config_flow": true, | ||
"documentation": "https://www.home-assistant.io/integrations/komfovent", | ||
"iot_class": "local_polling", | ||
"requirements": ["komfovent-api==0.0.3"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"config": { | ||
"step": { | ||
"user": { | ||
"data": { | ||
"host": "[%key:common::config_flow::data::host%]", | ||
"username": "[%key:common::config_flow::data::username%]", | ||
"password": "[%key:common::config_flow::data::password%]" | ||
} | ||
} | ||
}, | ||
"error": { | ||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]", | ||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]", | ||
"invalid_input": "Failed to parse provided hostname", | ||
"unknown": "[%key:common::config_flow::error::unknown%]" | ||
}, | ||
"abort": { | ||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -244,6 +244,7 @@ | |
"kmtronic", | ||
"knx", | ||
"kodi", | ||
"komfovent", | ||
"konnected", | ||
"kostal_plenticore", | ||
"kraken", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Tests for the Komfovent integration.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
"""Common fixtures for the Komfovent tests.""" | ||
from collections.abc import Generator | ||
from unittest.mock import AsyncMock, patch | ||
|
||
import pytest | ||
|
||
|
||
@pytest.fixture | ||
def mock_setup_entry() -> Generator[AsyncMock, None, None]: | ||
"""Override async_setup_entry.""" | ||
with patch( | ||
"homeassistant.components.komfovent.async_setup_entry", return_value=True | ||
) as mock_setup_entry: | ||
yield mock_setup_entry |
Oops, something went wrong.