Skip to content

Commit

Permalink
Add valve support (#12)
Browse files Browse the repository at this point in the history
* Update manifest.json version

* Add floor heating valves
  • Loading branch information
arjenbos authored Oct 30, 2023
1 parent 65be1ca commit b715514
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 6 deletions.
132 changes: 132 additions & 0 deletions custom_components/alpha_innotec/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
"""Platform for binary sensor integration."""
from __future__ import annotations

import logging
from datetime import timedelta

from homeassistant.components.binary_sensor import BinarySensorEntity, BinarySensorEntityDescription, \
BinarySensorDeviceClass
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.typing import UndefinedType
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)

from .const import DOMAIN, MANUFACTURER
from .gateway_api import GatewayAPI
from .structs.Valve import Valve

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, entry, async_add_entities):
"""Set up the sensor platform."""

_LOGGER.debug("Setting up binary sensors")

gateway_api = hass.data[DOMAIN][entry.entry_id]['gateway_api']

coordinator = AlphaCoordinator(hass, gateway_api)

await coordinator.async_config_entry_first_refresh()

entities = []

for valve in coordinator.data:
entities.append(AlphaHomeBinarySensor(
coordinator=coordinator,
name=valve.name,
description=BinarySensorEntityDescription(""),
valve=valve
))

async_add_entities(entities)


class AlphaCoordinator(DataUpdateCoordinator):
"""My custom coordinator."""

def __init__(self, hass: HomeAssistant, gateway_api: GatewayAPI):
"""Initialize my coordinator."""
super().__init__(
hass,
_LOGGER,
name="Alpha Innotec Binary Coordinator",
update_interval=timedelta(seconds=30),
)

self.gateway_api: GatewayAPI = gateway_api

async def _async_update_data(self) -> list[Valve]:
"""Fetch data from API endpoint.
This is the place to pre-process the data to lookup tables
so entities can quickly look up their data.
"""

db_modules: dict = await self.hass.async_add_executor_job(self.gateway_api.db_modules)

valves: list[Valve] = []

for module_id in db_modules["modules"]:
module = db_modules["modules"][module_id]

if module["productId"] != 3:
continue

for instance in module["instances"]:
valve = Valve(
identifier=module["deviceid"] + '-' + instance['instance'],
name=module["name"] + '-' + instance['instance'],
instance=instance["instance"],
device_id=module["deviceid"],
device_name=module["name"],
status=instance["status"]
)

valves.append(valve)

_LOGGER.debug("Finished getting valves from API")

return valves


class AlphaHomeBinarySensor(CoordinatorEntity, BinarySensorEntity):
"""Representation of a Sensor."""

def __init__(self, coordinator: AlphaCoordinator, name: str, description: BinarySensorEntityDescription, valve: Valve) -> None:
"""Pass coordinator to CoordinatorEntity."""
super().__init__(coordinator, context=valve.identifier)
self.entity_description = description
self._attr_name = name
self.valve = valve

@property
def device_info(self) -> DeviceInfo:
"""Return the device info."""
return DeviceInfo(
identifiers={
(DOMAIN, self.valve.device_id)
},
name=self.valve.device_name,
manufacturer=MANUFACTURER,
)

@property
def name(self) -> str | UndefinedType | None:
return self._attr_name

@property
def unique_id(self) -> str:
"""Return unique ID for this device."""
return self.valve.identifier

@property
def is_on(self) -> bool | None:
return self.valve.status

@property
def device_class(self) -> BinarySensorDeviceClass | None:
return BinarySensorDeviceClass.OPENING
10 changes: 9 additions & 1 deletion custom_components/alpha_innotec/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ def _handle_coordinator_update(self) -> None:
if not current_thermostat:
return

if current_thermostat == "unknown":
_LOGGER.warning("Current temperature not available for %s", current_thermostat.name)
return

self._current_temperature = current_thermostat.current_temperature
self._target_temperature = current_thermostat.desired_temperature

Expand All @@ -130,8 +134,12 @@ def _handle_coordinator_update(self) -> None:


@property
def current_temperature(self) -> float:
def current_temperature(self) -> float | None:
"""Return the current temperature."""
if self._current_temperature == "unknown":
_LOGGER.warning("Current temperature not available for %s", self.thermostat.name)
return

return self._current_temperature

@property
Expand Down
2 changes: 1 addition & 1 deletion custom_components/alpha_innotec/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def validate_input(data: dict) -> dict:

return system_information
except Exception as exception:
_LOGGER.info("Exception: %s", exception)
_LOGGER.debug("Exception: %s", exception)
raise CannotConnect


Expand Down
1 change: 1 addition & 0 deletions custom_components/alpha_innotec/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

PLATFORMS = [
Platform.SENSOR,
Platform.BINARY_SENSOR,
Platform.CLIMATE,
]

Expand Down
4 changes: 4 additions & 0 deletions custom_components/alpha_innotec/controller_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,11 @@ def login(self):
"hashed": base64.b64encode(self.encode_signature(self.password, device_token)).decode()
})

if "devicetoken_encrypted" not in response.json():
raise Exception("Unable to login.")

self.device_token_encrypted = response.json()['devicetoken_encrypted']

self.user_id = response.json()['userid']

self.device_token_decrypted = self.decrypt2(response.json()['devicetoken_encrypted'], self.password)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/alpha_innotec/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/arjenbos/ha_alpha_innotec/issues",
"requirements": ["backports.pbkdf2==0.1", "pycryptodome==3.17"],
"version": "1.0.0"
"version": "1.1.0"
}
4 changes: 4 additions & 0 deletions custom_components/alpha_innotec/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ async def async_setup_entry(hass, entry, async_add_entities):
entities = []

for thermostat in coordinator.data:
if thermostat.battery_percentage == "unknown":
_LOGGER.warning("Skipping %s because battery status is unknown.", thermostat.name)
continue

entities.append(AlphaHomeBatterySensor(
coordinator=coordinator,
name=thermostat.name,
Expand Down
8 changes: 5 additions & 3 deletions custom_components/alpha_innotec/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
"flow_title": "{name} ({host})",
"step": {
"user": {
"description": "Setup Alpha Innotec custom integration.",
"description": "Setup Alpha Innotec.",
"data": {
"gateway_ip": "[%key:common::config_flow::data::gateway_ip%]",
"gateway_password": "[%key:common::config_flow::data::gateway_password%]",
"controller_ip": "[%key:common::config_flow::data::controller_ip%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]"
"controller_username": "[%key:common::config_flow::data::controller_username%]",
"controller_password": "[%key:common::config_flow::data::controller_password%]"
}
}
},
Expand Down
8 changes: 8 additions & 0 deletions custom_components/alpha_innotec/structs/Valve.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Valve:
def __init__(self, identifier: str, name: str, instance: str, device_id: str, device_name: str, status: bool):
self.identifier = identifier
self.name = name
self.instance = instance
self.device_id = device_id
self.device_name = device_name
self.status = status
159 changes: 159 additions & 0 deletions tests/fixtures/controller_api_room_list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
{
"success": true,
"message": "",
"loginRejected": false,
"groups": [
{
"groupid": 1,
"name": "rooms",
"rooms": [
{
"id": 1,
"appid": "01010002",
"actualTemperature": 21,
"isComfortMode": false,
"desiredTemperature": 22,
"roomstatus": 51,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 1",
"orderindex": 1,
"originalName": "Room 1",
"status": "ok",
"groupid": 1,
"windowPosition": 0
},
{
"id": 2,
"appid": "01020002",
"actualTemperature": 20.5,
"isComfortMode": false,
"desiredTemperature": 20,
"roomstatus": 41,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 2",
"orderindex": 2,
"originalName": "Room 3",
"status": "ok",
"groupid": 1,
"windowPosition": 0
},
{
"id": 3,
"appid": "01030002",
"actualTemperature": 22,
"isComfortMode": false,
"desiredTemperature": 22.5,
"roomstatus": 51,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 3",
"orderindex": 3,
"originalName": "Room 3",
"status": "ok",
"groupid": 1,
"windowPosition": 0
},
{
"id": 4,
"appid": "01040002",
"isComfortMode": false,
"desiredTemperature": 20,
"roomstatus": 99,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 4",
"orderindex": 4,
"originalName": "Room 4",
"status": "problem",
"groupid": 1,
"windowPosition": 0
},
{
"id": 5,
"appid": "01050002",
"actualTemperature": 22,
"isComfortMode": false,
"desiredTemperature": 22.5,
"roomstatus": 51,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 5",
"orderindex": 5,
"originalName": "Room 5",
"status": "ok",
"groupid": 1,
"windowPosition": 0
},
{
"id": 6,
"appid": "01060002",
"actualTemperature": 21.5,
"isComfortMode": false,
"desiredTemperature": 20,
"roomstatus": 41,
"desiredTempDay": 20,
"desiredTempDay2": 18,
"desiredTempNight": 18,
"scheduleTempMin": 15,
"scheduleTempMax": 28,
"minTemperature": 18,
"maxTemperature": 28,
"cooling": false,
"coolingEnabled": true,
"imagepath": "/assets/images/room/default.png",
"name": "Room 6",
"orderindex": 6,
"originalName": "Room 6",
"status": "ok",
"groupid": 1,
"windowPosition": 0
}
],
"orderindex": 1
}
],
"language": "en",
"performance": 0.907
}

6 comments on commit b715514

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.701s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.610s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.651s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.691s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.620s ⏱️

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HA Alpha Innotec Coverage

HA Alpha Innotec
FileStmtsMissCoverMissing
__init__.py21957%19–20, 22, 27, 29, 34, 36–37, 39
api.py44295%48, 51
base_coordinator.py36360%2, 4, 6, 8–11, 13, 16, 18–21, 23, 25–26, 28–31, 33–34, 36–38, 40, 42–44, 46, 58–60, 62–64
binary_sensor.py58580%2, 4–5, 7, 9–12, 17–19, 21, 24, 27, 29, 31, 33, 35, 37–38, 45, 48, 51, 53, 60, 62, 69, 71, 73–74, 76–77, 79–80, 89, 91, 93, 96, 99, 101–104, 106–107, 109, 117–119, 121–122, 124, 126–128, 130–132
climate.py81810%2, 4–5, 7, 9, 13–15, 20–23, 25, 28, 31–32, 34, 36, 38, 40–41, 49, 52, 55, 57, 64–65, 67, 73, 76, 79–81, 85, 87–93, 95–96, 98, 106–107, 109, 111–112, 115, 117–119, 121–122, 124–126, 128–129, 131, 133, 136–137, 139–141, 143, 145–146, 148, 150, 152–154, 156–157, 159, 161–162, 165
config_flow.py371559%24–25, 27–30, 32–35, 57–61
const.py70100% 
controller_api.py765922%17–18, 20–21, 23–26, 28, 30–33, 35, 38, 40, 43, 45, 50, 52–55, 57, 59–60, 62, 64, 71, 73, 80–81, 83, 85, 87, 89, 91–92, 94, 97, 100–101, 103–106, 108, 111, 114, 120, 122–126, 138–140, 142
gateway_api.py624724%17–19, 21–23, 26–27, 29–30, 32–35, 37, 39–42, 44, 47, 49, 52, 54, 59, 61, 63–65, 67, 69–70, 72, 74, 77, 79, 81–82, 84, 87–88, 90, 93, 96–98, 100
sensor.py46460%2, 4–5, 7–10, 15–18, 20, 23, 26–27, 29, 31, 33, 35–38, 40, 47, 50, 53, 55, 62–63, 65, 71, 74, 77–78, 80, 82–86, 88–89, 91, 99–100, 102
structs
   Thermostat.py11918%8–16
TOTAL47936224% 

Tests Skipped Failures Errors Time
3 0 💤 0 ❌ 0 🔥 0.603s ⏱️

Please sign in to comment.