Skip to content

Commit

Permalink
remove country from hacs.json
Browse files Browse the repository at this point in the history
def state -> def native_value
  • Loading branch information
marq24 authored and marq24 committed Sep 5, 2024
1 parent 0ca26a3 commit b23cc55
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 61 deletions.
13 changes: 6 additions & 7 deletions custom_components/waterkotte_heatpump/const.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from dataclasses import dataclass
from typing import Final

from custom_components.waterkotte_heatpump.pywaterkotte_ha.const import SIX_STEPS_MODES
from custom_components.waterkotte_heatpump.pywaterkotte_ha.tags import WKHPTag
from homeassistant.components.binary_sensor import BinarySensorDeviceClass, BinarySensorEntityDescription
from homeassistant.components.number import NumberEntityDescription, NumberDeviceClass, NumberMode, DEFAULT_STEP
from homeassistant.components.select import SelectEntityDescription
Expand All @@ -19,9 +21,6 @@
REVOLUTIONS_PER_MINUTE
)

from custom_components.waterkotte_heatpump.pywaterkotte_ha.const import SIX_STEPS_MODES
from custom_components.waterkotte_heatpump.pywaterkotte_ha.tags import WKHPTag

# Base component constants
NAME: Final = "Waterkotte Heatpump [+2020]"
DOMAIN: Final = "waterkotte_heatpump"
Expand Down Expand Up @@ -1714,7 +1713,7 @@ class ExtSwitchEntityDescription(SwitchEntityDescription):
ExtSensorEntityDescription(
key="WATERKOTTE_BIOS_TIME",
tag=WKHPTag.WATERKOTTE_BIOS_TIME,
state_class=SensorStateClass.TOTAL_INCREASING,
state_class=None,
device_class=SensorDeviceClass.DATE,
native_unit_of_measurement=None,
icon="mdi:clock-digital",
Expand All @@ -1724,7 +1723,7 @@ class ExtSwitchEntityDescription(SwitchEntityDescription):
ExtSensorEntityDescription(
key="HOLIDAY_START_TIME",
tag=WKHPTag.HOLIDAY_START_TIME,
state_class=SensorStateClass.TOTAL_INCREASING,
state_class=None,
device_class=SensorDeviceClass.DATE,
native_unit_of_measurement=None,
icon="mdi:calendar-arrow-right",
Expand All @@ -1733,7 +1732,7 @@ class ExtSwitchEntityDescription(SwitchEntityDescription):
ExtSensorEntityDescription(
key="HOLIDAY_END_TIME",
tag=WKHPTag.HOLIDAY_END_TIME,
state_class=SensorStateClass.TOTAL_INCREASING,
state_class=None,
device_class=SensorDeviceClass.DATE,
native_unit_of_measurement=None,
icon="mdi:calendar-arrow-left",
Expand All @@ -1742,7 +1741,7 @@ class ExtSwitchEntityDescription(SwitchEntityDescription):
ExtSensorEntityDescription(
key="SCHEDULE_WATER_DISINFECTION_START_TIME",
tag=WKHPTag.SCHEDULE_WATER_DISINFECTION_START_TIME,
state_class=SensorStateClass.TOTAL_INCREASING,
state_class=None,
device_class=SensorDeviceClass.DATE,
native_unit_of_measurement=None,
icon="mdi:clock-digital",
Expand Down
2 changes: 1 addition & 1 deletion custom_components/waterkotte_heatpump/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/marq24/ha-waterkotte/issues",
"requirements": [],
"version": "2024.8.0"
"version": "2024.9.0"
}
65 changes: 36 additions & 29 deletions custom_components/waterkotte_heatpump/pywaterkotte_ha/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
import logging
import re
import xml.etree.ElementTree as ElemTree

from datetime import datetime

from typing import (
Any,
Sequence,
Expand All @@ -21,15 +19,13 @@
SIX_STEPS_MODES,
TRANSLATIONS
)

from custom_components.waterkotte_heatpump.pywaterkotte_ha.error import (
InvalidResponseException,
InvalidValueException,
StatusException,
TooManyUsersException,
Http404Exception, InvalidPasswordException
)

from custom_components.waterkotte_heatpump.pywaterkotte_ha.tags import WKHPTag

_LOGGER: logging.Logger = logging.getLogger(__package__)
Expand Down Expand Up @@ -206,37 +202,48 @@ async def read_values(self, tags: Sequence[WKHPTag]):
try:
t_values = [e_values[a_tag] for a_tag in a_wphp_tag.tags]
t_states = [e_status[a_tag] for a_tag in a_wphp_tag.tags]
if a_wphp_tag.decode_f == WKHPTag._decode_alarms:
result[a_wphp_tag] = {
"value": a_wphp_tag.decode_f(a_wphp_tag, t_values, self.lang_map),
"status": t_states[0]
}
else:
result[a_wphp_tag] = {
"value": a_wphp_tag.decode_f(a_wphp_tag, t_values),
"status": t_states[0]
}

if a_wphp_tag.translate and a_wphp_tag.tags[0] in self.lang_map:
value_map = self.lang_map[a_wphp_tag.tags[0]]
final_value = ""
temp_values = result[a_wphp_tag]["value"]
for idx in range(len(temp_values)):
if temp_values[idx]:
final_value = final_value + ", " + str(value_map[idx])

# we need to trim the firsts initial added ', '
if len(final_value) > 0:
final_value = final_value[2:]

result[a_wphp_tag]["value"] = final_value
if t_values is None or (len(t_values) > 0 and t_values[0] is None):
if t_states is not None and len(t_states)>0:
result[a_wphp_tag] = {
"value": None,
"status": t_states[0]
}
else:
result[a_wphp_tag] = None
else:
if a_wphp_tag.decode_f == WKHPTag._decode_alarms:
result[a_wphp_tag] = {
"value": a_wphp_tag.decode_f(a_wphp_tag, t_values, self.lang_map),
"status": t_states[0]
}
else:
result[a_wphp_tag] = {
"value": a_wphp_tag.decode_f(a_wphp_tag, t_values),
"status": t_states[0]
}

if a_wphp_tag.translate and a_wphp_tag.tags[0] in self.lang_map:
value_map = self.lang_map[a_wphp_tag.tags[0]]
final_value = ""
temp_values = result[a_wphp_tag]["value"]
if temp_values is not None:
for idx in range(len(temp_values)):
if temp_values[idx]:
final_value = final_value + ", " + str(value_map[idx])

# we need to trim the firsts initial added ', '
if len(final_value) > 0:
final_value = final_value[2:]

result[a_wphp_tag]["value"] = final_value

except KeyError:
_LOGGER.warning(
f"Key Error while read_values. EcoTag: {a_wphp_tag} vals: {t_values} states: {t_states}")
f"Key Error while read_values. EcoTag: {a_wphp_tag} t_values: {t_values} t_states: {t_states}")
except Exception as other_exc:
_LOGGER.error(
f"Exception {other_exc} while read_values. EcoTag: {a_wphp_tag} vals: {t_values} states: {t_states} -> {other_exc}"
f"Exception of type '{other_exc}' while read_values. EcoTag: {a_wphp_tag} t_values: {t_values} t_states: {t_states} -> {other_exc}"
)

return result
Expand Down
49 changes: 44 additions & 5 deletions custom_components/waterkotte_heatpump/pywaterkotte_ha/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def _decode_value_analog(self, str_vals: List[str]):
return self.__decode_value_default(str_vals, factor=-1.0)

def __decode_value_default(self, str_vals: List[str], factor: float):
if str_vals is None:
return None

first_val = str_vals[0]
if first_val is None:
# do not check any further if for what ever reason the first value of the str_vals is None
Expand Down Expand Up @@ -125,6 +128,9 @@ def __encode_value_default(self, value, encoded_values, factor: int):
encoded_values[ecotouch_tag] = str(int(value))

def _decode_alarms(self, str_vals: List[str], lang_map: dict):
if str_vals is None:
return None

error_tag_index = 0
final_value = ""
for a_val in str_vals:
Expand Down Expand Up @@ -153,6 +159,9 @@ def _decode_alarms(self, str_vals: List[str], lang_map: dict):
return final_value

def _decode_datetime(self, str_vals: List[str]):
if str_vals is None:
return None

int_vals = list(map(int, str_vals))
if int_vals[0] < 2000:
int_vals[0] = int_vals[0] + 2000
Expand Down Expand Up @@ -184,6 +193,9 @@ def _encode_datetime(self, value, encoded_values):
encoded_values[tags] = vals[i]

def _decode_time_hhmm(self, str_vals: List[str]):
if str_vals is None:
return None

int_vals = list(map(int, str_vals))
if int_vals[0] > 23:
int_vals[0] = 0
Expand All @@ -203,6 +215,9 @@ def _encode_time_hhmm(self, value, encoded_values):
encoded_values[tags] = vals[i]

def _decode_state(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
if str_vals[0] == "0":
return "off"
Expand All @@ -225,12 +240,15 @@ def _encode_state(self, value, encoded_values):
encoded_values[ecotouch_tag] = "2"

def _decode_six_steps_mode(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
int_val = int(str_vals[0])
if 0 <= int_val <= len(SIX_STEPS_MODES):
return SIX_STEPS_MODES[int_val]
else:
return "Error"
if str_vals[0] is not None:
int_val = int(str_vals[0])
if 0 <= int_val <= len(SIX_STEPS_MODES):
return SIX_STEPS_MODES[int_val]
return "Error"

def _encode_six_steps_mode(self, value, encoded_values):
assert len(self.tags) == 1
Expand All @@ -249,6 +267,9 @@ def _get_key_from_value(a_dict: dict, value_to_find):
return None

def _decode_status(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
if str_vals[0] == "0":
return "off"
Expand All @@ -271,6 +292,9 @@ def _encode_status(self, value, encoded_values):
encoded_values[ecotouch_tag] = "2"

def _decode_ro_series(self, str_vals: List[str]):
if str_vals is None:
return None

if str_vals[0]:
if isinstance(str_vals[0], int):
idx = int(str_vals[0])
Expand All @@ -282,6 +306,9 @@ def _decode_ro_series(self, str_vals: List[str]):
return "UNKNOWN_SERIES"

def _decode_ro_id(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
if str_vals[0]:
if isinstance(str_vals[0], int):
Expand All @@ -295,6 +322,9 @@ def _decode_ro_id(self, str_vals: List[str]):


def _decode_ro_bios(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
str_val = str_vals[0]
if len(str_val) > 2:
Expand All @@ -303,6 +333,9 @@ def _decode_ro_bios(self, str_vals: List[str]):
return str_val

def _decode_ro_fw(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 2
str_val1 = str_vals[0]
str_val2 = str_vals[1]
Expand All @@ -314,6 +347,9 @@ def _decode_ro_fw(self, str_vals: List[str]):
return f"FW_{str_val1}-{str_val2}"

def _decode_ro_sn(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 2
sn1 = int(str_vals[0])
sn2 = int(str_vals[1])
Expand All @@ -327,6 +363,9 @@ def _decode_ro_sn(self, str_vals: List[str]):
return f"Serial_{sn1}-{sn2}"

def _decode_year(self, str_vals: List[str]):
if str_vals is None:
return None

assert len(self.tags) == 1
return int(str_vals[0]) + 2000

Expand Down
47 changes: 31 additions & 16 deletions custom_components/waterkotte_heatpump/sensor.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import logging
from datetime import datetime, time

from homeassistant.components.sensor import SensorEntity, SensorDeviceClass
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.core import HomeAssistant
from homeassistant.const import EntityCategory
from homeassistant.components.sensor import SensorEntity

from . import WKHPDataUpdateCoordinator, WKHPBaseEntity
from .const import DOMAIN, SENSOR_SENSORS, ExtSensorEntityDescription
from .const_gen import SENSOR_SENSORS_GENERATED
Expand All @@ -33,6 +32,11 @@ class WKHPSensor(WKHPBaseEntity, SensorEntity, RestoreEntity):
def __init__(self, coordinator: WKHPDataUpdateCoordinator, description: ExtSensorEntityDescription):
super().__init__(coordinator=coordinator, description=description)

# if description.device_class is not None and description.device_class.SensorDeviceClass.DATE:
# if description.tag == WKHPTag.SCHEDULE_WATER_DISINFECTION_START_TIME:
# self._attr_native_value = time
# else:
# self._attr_native_value = datetime

# self._previous_float_value: float | None = None
# self._is_total_increasing: bool = description is not None and isinstance(description,
Expand All @@ -45,29 +49,40 @@ def _is_bit_field(self) -> bool:

@property
def state(self):
# for SensorDeviceClass.DATE we will use out OWN 'state' render impl!!!
if self.entity_description.device_class == SensorDeviceClass.DATE:
value = self.native_value
if value is None:
value = "unknown"
return value
else:
return SensorEntity.state.fget(self)

@property
def native_value(self):
"""Return the state of the sensor."""
try:
value = self.coordinator.data[self.wkhp_tag]["value"]
if value is None or value == "":
if value is None or len(str(value)) == 0:
if self._is_bit_field:
value = "none"
else:
value = "unknown"
value = None
else:
if isinstance(value, datetime):
return value.isoformat(sep=' ', timespec="minutes")
elif isinstance(value, time):
return value.isoformat(timespec="minutes")
elif self.entity_description.suggested_display_precision is not None:
value = round(float(value), self.entity_description.suggested_display_precision)
except KeyError:
value = "unknown"
except TypeError:
return "unknown"
if value is True:
value = "on"
elif value is False:
value = "off"
elif isinstance(value, bool):
if value is True:
value = "on"
elif value is False:
value = "off"

except (KeyError, TypeError):
value = None

# final return statement...
return value

@property
Expand Down
3 changes: 0 additions & 3 deletions hacs.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{
"name": "Waterkotte Heatpump [+2020]",
"country": [
"ALL"
],
"homeassistant": "2023.7.0",
"hacs": "1.18.0",
"render_readme": true
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
homeassistant>=2024.8.2
1 change: 1 addition & 0 deletions requirements_dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest-homeassistant-custom-component>=0.13.154

0 comments on commit b23cc55

Please sign in to comment.