Skip to content

Commit

Permalink
Added support for setting holding registers
Browse files Browse the repository at this point in the history
  • Loading branch information
CJNE committed Dec 7, 2022
1 parent 1442316 commit 8640c6d
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 11 deletions.
6 changes: 3 additions & 3 deletions custom_components/thermiagenesis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from .const import DOMAIN

PLATFORMS = ["sensor", "binary_sensor", "climate", "switch"]
PLATFORMS = ["sensor", "binary_sensor", "climate", "switch", "number"]

SCAN_INTERVAL = timedelta(seconds=30)

Expand Down Expand Up @@ -99,9 +99,9 @@ async def _async_update_data(self):
# for reg in registers:
# #await self.thermia.async_update(only_registers=[reg]) #registers)
# print(f"Got {reg}: {self.thermia.data[reg]}")
print(data)
_LOGGER.debug(data)
end_time = time.time()
print(
_LOGGER.debug(
f"{datetime.now()} Fetching heatpump data took {end_time - start_time} s"
)

Expand Down
1 change: 0 additions & 1 deletion custom_components/thermiagenesis/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def entity_registry_enabled_default(self):
return BINARY_SENSOR_TYPES[self.kind][ATTR_DEFAULT_ENABLED]

def async_write_ha_state(self):
print(f"Writing state for {self.kind}: {self.state} ")
super().async_write_ha_state()

async def async_added_to_hass(self):
Expand Down
1 change: 0 additions & 1 deletion custom_components/thermiagenesis/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,6 @@ async def async_turn_off(self):
await self.coordinator._async_set_data(self.meta[ATTR_ENABLED], False)

def async_write_ha_state(self):
print(f"Writing state for {self.kind}: {self.state} ")
super().async_write_ha_state()

async def async_added_to_hass(self):
Expand Down
36 changes: 36 additions & 0 deletions custom_components/thermiagenesis/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
ATTR_DEFAULT_ENABLED = "default_enabled"
ATTR_SCALE = "scale"
ATTR_ADDR = "address"
ATTR_MAX_VALUE = "max_value"
ATTR_MIN_VALUE = "min_value"

KEY_STATE_ATTRIBUTES = "state_attrs"
KEY_STATUS_VALUE = "status_value"
Expand Down Expand Up @@ -1670,11 +1672,17 @@
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
},
}

NUMBER_TYPES = {
thermiaconst.ATTR_HOLDING_OPERATIONAL_MODE: {
# 1: OFF, 2: Standby, 3: ON/Auto
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Operational Mode",
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 3,
},
thermiaconst.ATTR_HOLDING_MAX_LIMITATION: {
ATTR_ICON: ICON_INPUT,
Expand Down Expand Up @@ -1758,24 +1766,32 @@
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Minimum Allowed Gear In Heating",
ATTR_UNIT: None,
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MAXIMUM_ALLOWED_GEAR_IN_HEATING: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Maximum Allowed Gear In Heating",
ATTR_UNIT: None,
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MAXIMUM_ALLOWED_GEAR_IN_TAP_WATER: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Maximum Allowed Gear In Tap Water",
ATTR_UNIT: None,
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MINIMUM_ALLOWED_GEAR_IN_TAP_WATER: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Minimum Allowed Gear In Tap Water",
ATTR_UNIT: None,
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_COOLING_MIX_VALVE_SET_POINT: {
Expand Down Expand Up @@ -2069,24 +2085,32 @@
thermiaconst.ATTR_HOLDING_MINIMUM_ALLOWED_GEAR_IN_POOL: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Minimum Allowed Gear In Pool",
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MAXIMUM_ALLOWED_GEAR_IN_POOL: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Maximum Allowed Gear In Pool",
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MINIMUM_ALLOWED_GEAR_IN_COOLING: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Minimum Allowed Gear In Cooling",
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_MAXIMUM_ALLOWED_GEAR_IN_COOLING: {
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Maximum Allowed Gear In Cooling",
ATTR_MIN_VALUE: 1,
ATTR_MAX_VALUE: 9,
ATTR_UNIT: None,
ATTR_DEFAULT_ENABLED: False,
},
Expand Down Expand Up @@ -2409,6 +2433,9 @@
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_SELECTED_MODE_FOR_MIXING_VALVE_2: {
# 0:Heat, 1:Cool, 2:Auto
ATTR_MIN_VALUE: 0,
ATTR_MAX_VALUE: 2,
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Selected Mode For Mixing Valve 2",
ATTR_UNIT: None,
Expand All @@ -2433,6 +2460,9 @@
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_SELECTED_MODE_FOR_MIXING_VALVE_3: {
# 0:Heat, 1:Cool, 2:Auto
ATTR_MIN_VALUE: 0,
ATTR_MAX_VALUE: 2,
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Selected Mode For Mixing Valve 3",
ATTR_UNIT: None,
Expand All @@ -2457,6 +2487,9 @@
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_SELECTED_MODE_FOR_MIXING_VALVE_4: {
# 0:Heat, 1:Cool, 2:Auto
ATTR_MIN_VALUE: 0,
ATTR_MAX_VALUE: 2,
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Selected Mode For Mixing Valve 4",
ATTR_UNIT: None,
Expand All @@ -2481,6 +2514,9 @@
ATTR_DEFAULT_ENABLED: False,
},
thermiaconst.ATTR_HOLDING_SELECTED_MODE_FOR_MIXING_VALVE_5: {
# 0:Heat, 1:Cool, 2:Auto
ATTR_MIN_VALUE: 0,
ATTR_MAX_VALUE: 2,
ATTR_ICON: ICON_INPUT,
ATTR_LABEL: "Selected Mode For Mixing Valve 5",
ATTR_UNIT: None,
Expand Down
2 changes: 1 addition & 1 deletion custom_components/thermiagenesis/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"issue_tracker": "https://github.com/CJNE/thermiagenesis/issues",
"documentation": "https://github.com/CJNE/thermiagenesis",
"iot_class": "local_polling",
"version": "0.0.9"
"version": "0.0.10"
}
148 changes: 148 additions & 0 deletions custom_components/thermiagenesis/number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import logging

from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
from homeassistant.components.number import NumberEntity
from homeassistant.const import PERCENTAGE
from homeassistant.const import TEMP_CELSIUS

from homeassistant.helpers.entity import Entity
from pythermiagenesis.const import REGISTERS

from .const import ATTR_CLASS
from .const import ATTR_DEFAULT_ENABLED
from .const import ATTR_ICON
from .const import ATTR_LABEL
from .const import ATTR_MANUFACTURER
from .const import ATTR_STATE_CLASS
from .const import ATTR_UNIT
from .const import ATTR_MIN_VALUE
from .const import ATTR_MAX_VALUE
from .const import DOMAIN
from .const import HEATPUMP_ALARMS
from .const import HEATPUMP_ATTRIBUTES
from .const import HEATPUMP_SENSOR
from .const import NUMBER_TYPES

ATTR_COUNTER = "counter"
ATTR_FIRMWARE = "firmware"
ATTR_MODEL = "Diplomat Inverter Duo"

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Add Thermia entities from a config_entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id]

numbers = []

device_info = {
"identifiers": {(DOMAIN, ATTR_MODEL)},
"name": ATTR_MODEL,
"manufacturer": ATTR_MANUFACTURER,
"model": ATTR_MODEL,
"sw_version": coordinator.data.get(ATTR_FIRMWARE),
}

for number in NUMBER_TYPES:
if REGISTERS[number][coordinator.kind]:
numbers.append(ThermiaGenericNumber(coordinator, number, device_info))
async_add_entities(numbers, False)


def range_for_unit(unit):
if unit == PERCENTAGE:
return [0, 100]
if unit == TEMP_CELSIUS:
return [-40, 100]
return [0, 100]


class ThermiaGenericNumber(NumberEntity):
"""Define a Thermia generic sensor."""

def __init__(self, coordinator, kind, device_info):
"""Initialize."""
self._name = f"{NUMBER_TYPES[kind][ATTR_LABEL]}"
# self._name = f"{coordinator.data[ATTR_MODEL]} {SENSOR_TYPES[kind][ATTR_LABEL]}"
self._unique_id = f"thermiagenesis_{kind}"
self._device_info = device_info
self.coordinator = coordinator
self.kind = kind
meta = NUMBER_TYPES[kind]
range = range_for_unit(meta.get(ATTR_UNIT, None))
self.min = meta.get(ATTR_MIN_VALUE, range[0])
self.max = meta.get(ATTR_MAX_VALUE, range[1])
self._attrs = {}

@property
def name(self):
"""Return the name."""
return self._name

@property
def native_value(self):
"""Return the state of the sensor."""
return self.coordinator.data.get(self.kind)

@property
def native_min_value(self):
"""Return the state of the sensor."""
return self.min

@property
def native_max_value(self):
"""Return the state of the sensor."""
return self.max

@property
def native_step(self):
"""Return the state of the sensor."""
return 1

async def async_set_native_value(self, value: float) -> None:
"""Change the selected option."""
_LOGGER.info("Writing holding register %s value %s", self.kind, value)
await self.coordinator._async_set_data(self.kind, value)
_LOGGER.debug("Done writing")
self.async_schedule_update_ha_state()

@property
def native_unit_of_measurement(self):
"""Return the unit the value is expressed in."""
return NUMBER_TYPES[self.kind].get(ATTR_UNIT, None)

@property
def icon(self):
"""Return the icon."""
return NUMBER_TYPES[self.kind][ATTR_ICON]

@property
def unique_id(self):
"""Return a unique_id for this entity."""
return self._unique_id

@property
def device_info(self):
"""Return the device info."""
return self._device_info

def async_write_ha_state(self):
super().async_write_ha_state()

@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""
return NUMBER_TYPES[self.kind][ATTR_DEFAULT_ENABLED]

async def async_added_to_hass(self):
await super().async_added_to_hass()
"""Connect to dispatcher listening for entity data notifications."""
self.coordinator.registerAttribute(self.kind)
self.async_on_remove(
self.coordinator.async_add_listener(self.async_write_ha_state)
)

async def async_update(self):
"""Update Thermia entity."""
await self.coordinator.async_request_refresh()
2 changes: 0 additions & 2 deletions custom_components/thermiagenesis/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ def has_alarm(self):
return False

def async_write_ha_state(self):
print(f"Writing state for {self.kind}: {self.state} ")
super().async_write_ha_state()

async def async_added_to_hass(self):
Expand Down Expand Up @@ -214,7 +213,6 @@ def device_info(self):
return self._device_info

def async_write_ha_state(self):
print(f"Writing state for {self.kind}: {self.state} ")
super().async_write_ha_state()

@property
Expand Down
1 change: 0 additions & 1 deletion custom_components/thermiagenesis/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ def entity_registry_enabled_default(self):
return SWITCH_TYPES[self.kind][ATTR_DEFAULT_ENABLED]

def async_write_ha_state(self):
print(f"Writing state for {self.kind}: {self.state} ")
super().async_write_ha_state()

async def async_added_to_hass(self):
Expand Down
2 changes: 1 addition & 1 deletion hacs.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Thermia Genesis",
"hacs": "1.6.0",
"domains": ["binary_sensor", "sensor", "switch"],
"domains": ["binary_sensor", "sensor", "switch", "number", "climate"],
"iot_class": "Local Polling",
"render_readme": true,
"homeassistant": "0.118.0"
Expand Down
2 changes: 1 addition & 1 deletion requirements_test.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
-r requirements_dev.txt
pytest-homeassistant-custom-component==0.12.28
pytest-homeassistant-custom-component

0 comments on commit 8640c6d

Please sign in to comment.