code correction

This commit is contained in:
2024-02-20 15:54:22 +01:00
parent 93d8b339ec
commit 6c6b035cf5
7 changed files with 245 additions and 238 deletions
+11 -44
View File
@@ -133,7 +133,9 @@ class AreaClimateEntity(CoordinatorEntity, ClimateEntity):
return ret return ret
async def async_set_temperature(self, **kwargs) -> None: async def async_set_temperature(self,
**kwargs,
) -> None:
""" set new target temperature """ """ set new target temperature """
_LOGGER.debug("[Climate {}] set target temp - kwargs: {}".format(self._area.id_zone, kwargs)) _LOGGER.debug("[Climate {}] set target temp - kwargs: {}".format(self._area.id_zone, kwargs))
if "temperature" in kwargs: if "temperature" in kwargs:
@@ -143,8 +145,11 @@ class AreaClimateEntity(CoordinatorEntity, ClimateEntity):
_LOGGER.error("Error sending target temperature for area id {}".format(self._area.id_zone)) _LOGGER.error("Error sending target temperature for area id {}".format(self._area.id_zone))
else: else:
_LOGGER.warning("Target temperature not defined for climate id {}".format(self._area.id_zone)) _LOGGER.warning("Target temperature not defined for climate id {}".format(self._area.id_zone))
await self.coordinator.async_request_refresh()
async def async_set_fan_mode(self, fan_mode:str) -> None: async def async_set_fan_mode(self,
fan_mode:str,
) -> None:
""" set new target fan mode """ """ set new target fan mode """
_LOGGER.debug("[Climate {}] set new fan mode: {}".format(self._area.id_zone, fan_mode)) _LOGGER.debug("[Climate {}] set new fan mode: {}".format(self._area.id_zone, fan_mode))
for k,v in FAN_TRANSLATION.items(): for k,v in FAN_TRANSLATION.items():
@@ -157,7 +162,9 @@ class AreaClimateEntity(CoordinatorEntity, ClimateEntity):
_LOGGER.exception("Error setting new fan value for area id {}".format(self._area.id_zone)) _LOGGER.exception("Error setting new fan value for area id {}".format(self._area.id_zone))
await self.coordinator.async_request_refresh() await self.coordinator.async_request_refresh()
async def async_set_hvac_mode(self, hvac_mode:HVACMode) -> None: async def async_set_hvac_mode(self,
hvac_mode:HVACMode,
) -> None:
""" set new target hvac mode """ """ set new target hvac mode """
_LOGGER.debug("[Climate {}] set new hvac mode: {}".format(self._area.id_zone, hvac_mode)) _LOGGER.debug("[Climate {}] set new hvac mode: {}".format(self._area.id_zone, hvac_mode))
opt = 0 opt = 0
@@ -190,44 +197,4 @@ class AreaClimateEntity(CoordinatorEntity, ClimateEntity):
else: else:
self._attr_hvac_mode = HVAC_TRANSLATION[int(_cur_area.clim_mode)] self._attr_hvac_mode = HVAC_TRANSLATION[int(_cur_area.clim_mode)]
self._attr_fan_mode = FAN_TRANSLATION[int(_cur_area.fan_mode)] self._attr_fan_mode = FAN_TRANSLATION[int(_cur_area.fan_mode)]
self.async_write_ha_state() self.async_write_ha_state()
# async def async_turn_on(self) -> None:
# """ turn the entity on """
# _LOGGER.debug("[Climate {}] turn on the entity".format(self._area.id_zone))
# #await self._update_state()
# async def async_turn_off(self) -> None:
# """ turn the entity off """
# _LOGGER.debug("[Climate {}] turn off the entity".format(self._area.id_zone))
# #await self._update_state()
# async def _update_state(self) -> None:
# """ Private update attributes """
# _LOGGER.debug("[Climate {}] _update_state".format(self._area.id_zone))
# # retreive current temperature from specific area
# ret, up_area = await self._device.update_area(self._area.id_zone)
# if not ret:
# _LOGGER.error("[Climate {}] Cannot update area values")
# return
# self._area = up_area
# _LOGGER.debug("[Climate {}] temp:{} - target:{} - state: {} - hvac:{} - fan:{}".format(self._area.id_zone,
# self._area.real_temp,
# self._area.order_temp,
# self._area.state,
# self._area.clim_mode,
# self._area.fan_mode))
# self._attr_current_temperature = self._area.real_temp
# self._attr_target_temperature = self._area.order_temp
# self._attr_hvac_mode = self._translate_to_hvac_mode()
# self._attr_fan_mode = FAN_TRANSLATION[int(self._area.fan_mode)]
# @Throttle(MIN_TIME_BETWEEN_UPDATES)
# async def async_update(self):
# """ Retreive latest values """
# await self._update_state()
# @property
# def should_poll(self) -> bool:
# """ Do not poll for those entities """
# return False
+5 -5
View File
@@ -57,11 +57,11 @@ GLOBAL_MODES = [
GLOBAL_MODE_POS_5, GLOBAL_MODE_POS_5,
] ]
EFF_POS_1 = "lower efficiency" EFF_POS_1 = "lower"
EFF_POS_2 = "low efficiency" EFF_POS_2 = "low"
EFF_POS_3 = "Medium efficiency" EFF_POS_3 = "Medium"
EFF_POS_4 = "High efficiency" EFF_POS_4 = "High"
EFF_POS_5 = "Higher efficiency" EFF_POS_5 = "Higher"
EFF_TRANSLATION = { EFF_TRANSLATION = {
int(Efficiency.LOWER_EFF): EFF_POS_1, int(Efficiency.LOWER_EFF): EFF_POS_1,
+94 -94
View File
@@ -1,4 +1,4 @@
""" local API to manage system, units and zones """ """ local API to manage system, engines and areas """
import re, sys, os import re, sys, os
import logging as log import logging as log
@@ -138,6 +138,84 @@ class Area:
self._real_temp, self._real_temp,
self._order_temp)) self._order_temp))
class Engine:
''' koolnova Engine class '''
def __init__(self,
engine_id:int = 0,
throughput:int = 0,
state:const.FlowEngine = const.FlowEngine.AUTO,
order_temp:float = 0
) -> None:
''' Constructor class '''
self._engine_id = engine_id
self._throughput = throughput
self._state = state
self._order_temp = order_temp
@property
def engine_id(self) -> int:
''' Get Engine ID '''
return self._engine_id
@engine_id.setter
def engine_id(self, val:int) -> None:
''' Set Engine ID '''
if not isinstance(val, int):
raise AssertionError('Input variable must be Int')
if val > const.NUM_OF_ENGINES:
raise NumUnitError('Engine ID must be lower than {}'.format(const.NUM_OF_ENGINES))
self._engine_id = val
@property
def throughput(self) -> int:
''' Get throughput Engine '''
return self._throughput
@throughput.setter
def throughput(self, val:int) -> None:
''' Set throughput Engine '''
if not isinstance(val, int):
raise AssertionError('Input variable must be Int')
if val > const.FLOW_ENGINE_VAL_MAX or val < const.FLOW_ENGINE_VAL_MIN:
raise FlowEngineError('throughput engine value ({}) must be between {} and {}'.format(val,
const.FLOW_ENGINE_VAL_MIN,
const.FLOW_ENGINE_VAL_MAX))
self._throughput = val
@property
def state(self) -> const.FlowEngine:
''' Get Engine state '''
return self._state
@state.setter
def state(self, val:const.FlowEngine) -> None:
''' Set Engine state '''
if not isinstance(val, const.FlowEngine):
raise AssertionError('Input variable must be Enum FlowEngine')
self._state = val
@property
def order_temp(self) -> float:
''' Get Order Temp '''
return self._order_temp
@order_temp.setter
def order_temp(self, val:float = 0.0) -> None:
''' Set order temp engine '''
if not isinstance(val, float):
raise AssertionError('Input variable must be Int')
if val > 0 and (val > 30.0 or val < 15.0):
raise OrderTempError('Flow Engine value ({}) must be between 15 and 30'.format(val))
self._order_temp = val
def __repr__(self) -> str:
''' repr method '''
return repr('Unit(Id:{}, Throughput:{}, State:{}, Order Temp:{})'.format(self._engine_id,
self._throughput,
self._state,
self._order_temp))
class Koolnova: class Koolnova:
''' koolnova Device class ''' ''' koolnova Device class '''
@@ -162,7 +240,7 @@ class Koolnova:
self._global_mode = const.GlobalMode.COLD self._global_mode = const.GlobalMode.COLD
self._efficiency = const.Efficiency.LOWER_EFF self._efficiency = const.Efficiency.LOWER_EFF
self._sys_state = const.SysState.SYS_STATE_OFF self._sys_state = const.SysState.SYS_STATE_OFF
self._units = [] self._engines = []
self._areas = [] self._areas = []
def _area_defined(self, def _area_defined(self,
@@ -202,18 +280,17 @@ class Koolnova:
_LOGGER.error("Error retreiving efficiency") _LOGGER.error("Error retreiving efficiency")
self._efficiency = const.Efficiency.LOWER_EFF self._efficiency = const.Efficiency.LOWER_EFF
#await asyncio.sleep(0.1) await asyncio.sleep(0.1)
#_LOGGER.debug("Retreive units ...") _LOGGER.debug("Retreive engines ...")
#for idx in range(1, const.NUM_OF_ENGINES + 1): for idx in range(1, const.NUM_OF_ENGINES + 1):
# _LOGGER.debug("Unit id: {}".format(idx)) _LOGGER.debug("Engine id: {}".format(idx))
# unit = Unit(unit_id = idx) engine = Engine(engine_id = idx)
# ret, unit.flow_engine = await self._client.flow_engine(unit_id = idx) ret, engine.throughput = await self._client.engine_throughput(engine_id = idx)
# ret, unit.flow_state = await self._client.flow_state_engine(unit_id = idx) ret, engine.state = await self._client.engine_state(engine_id = idx)
# ret, unit.order_temp = await self._client.order_temp_engine(unit_id = idx) ret, engine.order_temp = await self._client.engine_order_temp(engine_id = idx)
# self._units.append(unit) self._engines.append(engine)
# await asyncio.sleep(0.1) await asyncio.sleep(0.1)
return True return True
async def connect(self) -> bool: async def connect(self) -> bool:
@@ -329,9 +406,10 @@ class Koolnova:
return self._areas return self._areas
def get_units(self) -> list: @property
''' get units ''' def engines(self) -> list:
return self._units ''' get engines '''
return self._engines
@property @property
def device_info(self) -> DeviceInfo: def device_info(self) -> DeviceInfo:
@@ -512,84 +590,6 @@ class Koolnova:
self._efficiency, self._efficiency,
self._sys_state)) self._sys_state))
class Unit:
''' koolnova Unit class '''
def __init__(self,
unit_id:int = 0,
flow_engine:int = 0,
flow_state:const.FlowEngine = const.FlowEngine.AUTO,
order_temp:float = 0
) -> None:
''' Constructor class '''
self._unit_id = unit_id
self._flow_engine = flow_engine
self._flow_state = flow_state
self._order_temp = order_temp
@property
def unit_id(self) -> int:
''' Get Unit ID '''
return self._unit_id
@unit_id.setter
def unit_id(self, val:int) -> None:
''' Set Unit ID '''
if not isinstance(val, int):
raise AssertionError('Input variable must be Int')
if val > const.NUM_OF_ENGINES:
raise NumUnitError('Unit ID must be lower than {}'.format(const.NUM_OF_ENGINES))
self._unit_id = val
@property
def flow_engine(self) -> int:
''' Get Flow Engine '''
return self._flow_engine
@flow_engine.setter
def flow_engine(self, val:int) -> None:
''' Set Flow Engine '''
if not isinstance(val, int):
raise AssertionError('Input variable must be Int')
if val > const.FLOW_ENGINE_VAL_MAX or val < const.FLOW_ENGINE_VAL_MIN:
raise FlowEngineError('Flow Engine value ({}) must be between {} and {}'.format(val,
const.FLOW_ENGINE_VAL_MIN,
const.FLOW_ENGINE_VAL_MAX))
self._flow_engine = val
@property
def flow_state(self) -> const.FlowEngine:
''' Get Flow State '''
return self._flow_state
@flow_state.setter
def flow_state(self, val:const.FlowEngine) -> None:
''' Set Flow State '''
if not isinstance(val, const.FlowEngine):
raise AssertionError('Input variable must be Enum FlowEngine')
self._flow_state = val
@property
def order_temp(self) -> float:
''' Get Order Temp '''
return self._order_temp
@order_temp.setter
def order_temp(self, val:float = 0.0) -> None:
''' Set Flow Engine '''
if not isinstance(val, float):
raise AssertionError('Input variable must be Int')
if val > 0 and (val > 30.0 or val < 15.0):
raise OrderTempError('Flow Engine value ({}) must be between 15 and 30'.format(val))
self._flow_engine = val
def __repr__(self) -> str:
''' repr method '''
return repr('Unit(Id:{}, Flow Engine:{}, Flow State:{}, Order Temp:{})'.format(self._unit_id,
self._flow_engine,
self._flow_state,
self._order_temp))
class NumUnitError(Exception): class NumUnitError(Exception):
''' user defined exception ''' ''' user defined exception '''
+29 -27
View File
@@ -197,6 +197,7 @@ class Operations:
async def areas_registered(self) -> (bool, dict): async def areas_registered(self) -> (bool, dict):
""" Get all areas values """ """ Get all areas values """
_areas_dict:dict = {} _areas_dict:dict = {}
# retreive all areas (registered and unregistered)
regs, ret = await self.__read_registers(start_reg = const.REG_START_ZONE, regs, ret = await self.__read_registers(start_reg = const.REG_START_ZONE,
count = const.NUM_REG_PER_ZONE * const.NB_ZONE_MAX) count = const.NUM_REG_PER_ZONE * const.NB_ZONE_MAX)
if not ret: if not ret:
@@ -204,6 +205,7 @@ class Operations:
for area_idx in range(const.NB_ZONE_MAX): for area_idx in range(const.NB_ZONE_MAX):
_idx:int = 4 * area_idx _idx:int = 4 * area_idx
_area_dict:dict = {} _area_dict:dict = {}
# test if area is registered or not
if const.ZoneRegister(regs[_idx + const.REG_LOCK_ZONE] >> 1) == const.ZoneRegister.REGISTER_OFF: if const.ZoneRegister(regs[_idx + const.REG_LOCK_ZONE] >> 1) == const.ZoneRegister.REGISTER_OFF:
continue continue
@@ -267,8 +269,8 @@ class Operations:
_LOGGER.error('Error writing efficiency') _LOGGER.error('Error writing efficiency')
return ret return ret
async def flow_engines(self) -> (bool, list): async def engines_throughput(self) -> (bool, list):
''' read flow engines AC1, AC2, AC3, AC4 ''' ''' read engines throughput AC1, AC2, AC3, AC4 '''
engines_lst = [] engines_lst = []
regs, ret = await self.__read_registers(const.REG_START_FLOW_ENGINE, regs, ret = await self.__read_registers(const.REG_START_FLOW_ENGINE,
const.NUM_OF_ENGINES) const.NUM_OF_ENGINES)
@@ -276,52 +278,52 @@ class Operations:
for idx, reg in enumerate(regs): for idx, reg in enumerate(regs):
engines_lst.append(const.FlowEngine(reg)) engines_lst.append(const.FlowEngine(reg))
else: else:
_LOGGER.error('Error retreive flow engines') _LOGGER.error('Error retreive engines throughput')
return ret, engines_lst return ret, engines_lst
async def flow_engine(self, async def engine_throughput(self,
unit_id:int = 0, engine_id:int = 0,
) -> (bool, int): ) -> (bool, int):
''' read flow unit specified by unit id ''' ''' read engine throughput specified by id '''
if unit_id < 1 or unit_id > 4: if engine_id < 1 or engine_id > 4:
raise UnitIdError("Unit Id must be between 1 and 4") raise UnitIdError("engine Id must be between 1 and 4")
reg, ret = await self.__read_register(const.REG_START_FLOW_ENGINE + (unit_id - 1)) reg, ret = await self.__read_register(const.REG_START_FLOW_ENGINE + (engine_id - 1))
if not ret: if not ret:
_LOGGER.error('Error retreive flow engine for id:{}'.format(unit_id)) _LOGGER.error('Error retreive engine throughput for id:{}'.format(engine_id))
reg = 0 reg = 0
return ret, reg return ret, reg
async def flow_state_engine(self, async def engine_state(self,
unit_id:int = 0, engine_id:int = 0,
) -> (bool, const.FlowEngine): ) -> (bool, const.FlowEngine):
if unit_id < 1 or unit_id > 4: if engine_id < 1 or engine_id > 4:
raise UnitIdError("Unit Id must be between 1 and 4") raise UnitIdError("Engine id must be between 1 and 4")
reg, ret = await self.__read_register(const.REG_START_FLOW_STATE_ENGINE + (unit_id - 1)) reg, ret = await self.__read_register(const.REG_START_FLOW_STATE_ENGINE + (engine_id - 1))
if not ret: if not ret:
_LOGGER.error('Error retreive flow state for id:{}'.format(unit_id)) _LOGGER.error('Error retreive engine state for id:{}'.format(engine_id))
reg = 0 reg = 0
return ret, const.FlowEngine(reg) return ret, const.FlowEngine(reg)
async def order_temp_engine(self, async def engine_order_temp(self,
unit_id:int = 0, engine_id:int = 0,
) -> (bool, float): ) -> (bool, float):
if unit_id < 1 or unit_id > 4: if engine_id < 1 or engine_id > 4:
raise UnitIdError("Unit Id must be between 1 and 4") raise UnitIdError("Engine id must be between 1 and 4")
reg, ret = await self.__read_register(const.REG_START_ORDER_TEMP + (unit_id - 1)) reg, ret = await self.__read_register(const.REG_START_ORDER_TEMP + (engine_id - 1))
if not ret: if not ret:
_LOGGER.error('Error retreive order temp for id:{}'.format(unit_id)) _LOGGER.error('Error retreive engine order temp for id:{}'.format(engine_id))
reg = 0 reg = 0
return ret, reg / 2 return ret, reg / 2
async def orders_temp(self) -> (bool, list): async def engine_orders_temp(self) -> (bool, list):
''' read orders temperature AC1, AC2, AC3, AC4 ''' ''' read orders temperature for engines : AC1, AC2, AC3, AC4 '''
engines_lst = [] engines_lst = []
regs, ret = await self.__read_registers(const.REG_START_ORDER_TEMP, const.NUM_OF_ENGINES) regs, ret = await self.__read_registers(const.REG_START_ORDER_TEMP, const.NUM_OF_ENGINES)
if ret: if ret:
for idx, reg in enumerate(regs): for idx, reg in enumerate(regs):
engines_lst.append(reg/2) engines_lst.append(reg/2)
else: else:
_LOGGER.error('error reading flow engines registers') _LOGGER.error('error reading engines order temp registers')
return ret, engines_lst return ret, engines_lst
async def set_area_target_temp(self, async def set_area_target_temp(self,
+29 -41
View File
@@ -28,8 +28,9 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, async def async_setup_entry(hass: HomeAssistant,
entry: ConfigEntry, entry: ConfigEntry,
async_add_entities: AddEntitiesCallback): async_add_entities: AddEntitiesCallback,
"""Setup select entries""" ):
""" Setup select entries """
for device in hass.data[DOMAIN]: for device in hass.data[DOMAIN]:
_LOGGER.debug("Device: {}".format(device)) _LOGGER.debug("Device: {}".format(device))
@@ -40,37 +41,28 @@ async def async_setup_entry(hass: HomeAssistant,
async_add_entities(entities) async_add_entities(entities)
class GlobalModeSelect(SelectEntity): class GlobalModeSelect(SelectEntity):
"""Select component to set Global Mode """ """ Select component to set global HVAC mode """
def __init__(self, def __init__(self,
device: Koolnova, device: Koolnova, # pylint: disable=unused-argument,
) -> None: ) -> None:
super().__init__() super().__init__()
self._attr_options = GLOBAL_MODES self._attr_options = GLOBAL_MODES
self._device = device self._device = device
self._attr_name = f"{device.name} Global Mode" self._attr_name = f"{device.name} Global HVAC Mode"
self._attr_device_info = device.device_info self._attr_device_info = device.device_info
self._attr_icon = "mdi:cog-clockwise" self._attr_icon = "mdi:cog-clockwise"
self._attr_unique_id = f"{DOMAIN}-GlobalMode-select" self._attr_unique_id = f"{DOMAIN}-Global-HVACMode-select"
self.select_option(
GLOBAL_MODE_TRANSLATION[int(self._device.global_mode)]
)
def _update_state(self) -> None:
""" update global mode """
_LOGGER.debug("[GLOBAL MODE] _update_state")
self.select_option( self.select_option(
GLOBAL_MODE_TRANSLATION[int(self._device.global_mode)] GLOBAL_MODE_TRANSLATION[int(self._device.global_mode)]
) )
def select_option(self, option: str) -> None: def select_option(self, option: str) -> None:
"""Change the selected option.""" """ Change the selected option. """
_LOGGER.debug("[GLOBAL MODE] select_option: {}".format(option))
self._attr_current_option = option self._attr_current_option = option
async def async_select_option(self, option: str) -> None: async def async_select_option(self, option: str) -> None:
"""Change the selected option.""" """ Change the selected option. """
_LOGGER.debug("[GLOBAL_MODE] async_select_option: {}".format(option))
opt = 0 opt = 0
for k,v in GLOBAL_MODE_TRANSLATION.items(): for k,v in GLOBAL_MODE_TRANSLATION.items():
if v == option: if v == option:
@@ -81,42 +73,38 @@ class GlobalModeSelect(SelectEntity):
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self): async def async_update(self):
"""Retrieve latest state.""" """ Retrieve latest state of global mode """
_LOGGER.debug("[GLOBAL MODE] async_update") self.select_option(
#await self._device.update() GLOBAL_MODE_TRANSLATION[int(self._device.global_mode)]
self._update_state() )
class EfficiencySelect(SelectEntity): class EfficiencySelect(SelectEntity):
"""Select component to set Efficiency """ """Select component to set global efficiency """
def __init__(self, def __init__(self,
device: Koolnova, device: Koolnova, # pylint: disable=unused-argument,
) -> None: ) -> None:
super().__init__() super().__init__()
self._attr_options = EFF_MODES self._attr_options = EFF_MODES
self._device = device self._device = device
self._attr_name = f"{device.name} Efficiency" self._attr_name = f"{device.name} Global HVAC Efficiency"
self._attr_device_info = device.device_info self._attr_device_info = device.device_info
self._attr_icon = "mdi:wind-power-outline" self._attr_icon = "mdi:wind-power-outline"
self._attr_unique_id = f"{DOMAIN}-Efficiency-select" self._attr_unique_id = f"{DOMAIN}-Global-HVACEff-select"
self.select_option( self.select_option(
EFF_TRANSLATION[int(self._device.efficiency)] EFF_TRANSLATION[int(self._device.efficiency)]
) )
def _update_state(self) -> None: def select_option(self,
""" update efficiency """ option: str,
_LOGGER.debug("[EFF] _update_state") ) -> None:
self.select_option( """ Change the selected option. """
EFF_TRANSLATION[int(self._device.efficiency)]
)
def select_option(self, option: str) -> None:
"""Change the selected option."""
_LOGGER.debug("[EFF] select_option: {}".format(option))
self._attr_current_option = option self._attr_current_option = option
async def async_select_option(self, option: str) -> None: async def async_select_option(self,
"""Change the selected option.""" option: str,
) -> None:
""" Change the selected option. """
_LOGGER.debug("[EFF] async_select_option: {}".format(option)) _LOGGER.debug("[EFF] async_select_option: {}".format(option))
opt = 0 opt = 0
for k,v in EFF_TRANSLATION.items(): for k,v in EFF_TRANSLATION.items():
@@ -128,7 +116,7 @@ class EfficiencySelect(SelectEntity):
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self): async def async_update(self):
"""Retrieve latest state.""" """ Retrieve latest state of global efficiency """
_LOGGER.debug("[EFF] async_update") self.select_option(
#await self._device.update() EFF_TRANSLATION[int(self._device.efficiency)]
self._update_state() )
+65 -9
View File
@@ -19,7 +19,10 @@ from .const import (
DOMAIN DOMAIN
) )
from homeassistant.const import UnitOfTime from homeassistant.const import UnitOfTime
from .koolnova.device import Koolnova from .koolnova.device import (
Koolnova,
Engine,
)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -36,12 +39,11 @@ async def async_setup_entry(hass: HomeAssistant,
entities = [ entities = [
DiagnosticsSensor(device, "Device", entry.data), DiagnosticsSensor(device, "Device", entry.data),
DiagnosticsSensor(device, "Address", entry.data), DiagnosticsSensor(device, "Address", entry.data),
DiagnosticsSensor(device, "Baudrate", entry.data), DiagModbusSensor(device, entry.data),
DiagnosticsSensor(device, "Sizebyte", entry.data),
DiagnosticsSensor(device, "Parity", entry.data),
DiagnosticsSensor(device, "Stopbits", entry.data),
DiagnosticsSensor(device, "Timeout", entry.data),
] ]
for engine in device.engines:
_LOGGER.debug("Engine: {}".format(engine))
entities.append(DiagEngineSensor(device, engine))
async_add_entities(entities) async_add_entities(entities)
class DiagnosticsSensor(SensorEntity): class DiagnosticsSensor(SensorEntity):
@@ -63,9 +65,63 @@ class DiagnosticsSensor(SensorEntity):
self._attr_unique_id = f"{DOMAIN}-{name}-sensor" self._attr_unique_id = f"{DOMAIN}-{name}-sensor"
self._attr_native_value = entry_infos.get(name) self._attr_native_value = entry_infos.get(name)
async def async_update(self): @property
""" Retreive latest state. """ def icon(self) -> str | None:
_LOGGER.debug("[DIAG SENSOR] call async_update") return "mdi:monitor"
@property
def should_poll(self) -> bool:
""" Do not poll for those entities """
return False
class DiagModbusSensor(SensorEntity):
# pylint: disable = too-many-instance-attributes
""" Representation of a Sensor """
_attr_entity_category: EntityCategory | None = EntityCategory.DIAGNOSTIC
def __init__(self,
device: Koolnova, # pylint: disable=unused-argument,
entry_infos, # pylint: disable=unused-argument
) -> None:
""" Class constructor """
self._device = device
self._attr_name = f"{device.name} Modbus RTU"
self._attr_entity_registry_enabled_default = True
self._attr_device_info = self._device.device_info
self._attr_unique_id = f"{DOMAIN}-Modbus-RTU-sensor"
self._attr_native_value = "{} {}{}{}".format(entry_infos.get("Baudrate"),
entry_infos.get("Sizebyte"),
entry_infos.get("Parity")[0],
entry_infos.get("Stopbits"))
@property
def icon(self) -> str | None:
return "mdi:monitor"
@property
def should_poll(self) -> bool:
""" Do not poll for those entities """
return False
class DiagEngineSensor(SensorEntity):
# pylint: disable = too-many-instance-attributes
""" Representation of a Sensor """
_attr_entity_category: EntityCategory | None = EntityCategory.DIAGNOSTIC
def __init__(self,
device: Koolnova, # pylint: disable=unused-argument
engine: Engine, # pylint: disable=unused-argument
) -> None:
""" Class constructor """
self._device = device
self._engine = engine
self._attr_name = f"{device.name} Engine AC{engine.engine_id} Throughput"
self._attr_entity_registry_enabled_default = True
self._attr_device_info = self._device.device_info
self._attr_unique_id = f"{DOMAIN}-Engine-AC{engine.engine_id}-throughput-sensor"
self._attr_native_value = f"TEST"
@property @property
def icon(self) -> str | None: def icon(self) -> str | None:
+12 -18
View File
@@ -23,8 +23,9 @@ _LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, async def async_setup_entry(hass: HomeAssistant,
entry: ConfigEntry, entry: ConfigEntry,
async_add_entities: AddEntitiesCallback): async_add_entities: AddEntitiesCallback,
"""Setup switch entries""" ):
""" Setup switch entries """
for device in hass.data[DOMAIN]: for device in hass.data[DOMAIN]:
_LOGGER.debug("Device: {}".format(device)) _LOGGER.debug("Device: {}".format(device))
@@ -38,40 +39,33 @@ class SystemStateSwitch(SwitchEntity):
_attr_has_entity_name = True _attr_has_entity_name = True
def __init__(self, def __init__(self,
device: Koolnova, device: Koolnova, # pylint: disable=unused-argument,
) -> None: ) -> None:
super().__init__() super().__init__()
self._device = device self._device = device
self._attr_name = f"{device.name} System State" self._attr_name = f"{device.name} Global HVAC State"
self._attr_device_info = device.device_info self._attr_device_info = device.device_info
self._attr_unique_id = f"{DOMAIN}-SystemState-switch" self._attr_unique_id = f"{DOMAIN}-Global-HVACState-switch"
_LOGGER.debug("[SYS STATE] State: {}".format(bool(int(self._device.sys_state))))
self._is_on = bool(int(self._device.sys_state)) self._is_on = bool(int(self._device.sys_state))
async def async_turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
"""Turn the entity on.""" """ Turn the entity on. """
_LOGGER.debug("[SYS STATE] turn on")
self._is_on = True self._is_on = True
await self._device.set_sys_state(SysState.SYS_STATE_ON) await self._device.set_sys_state(SysState.SYS_STATE_ON)
async def async_turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn the entity off.""" """ Turn the entity off. """
_LOGGER.debug("[SYS STATE] turn off")
self._is_on = False self._is_on = False
await self._device.set_sys_state(SysState.SYS_STATE_OFF) await self._device.set_sys_state(SysState.SYS_STATE_OFF)
def _update_state(self) -> None:
""" update system state """
self._is_on = bool(int(self._device.sys_state))
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self): async def async_update(self):
"""Retrieve latest state.""" """ Retrieve latest state. """
self._update_state() self._is_on = bool(int(self._device.sys_state))
@property @property
def is_on(self): def is_on(self):
"""If the switch is currently on or off.""" """ If the switch is currently on or off. """
return self._is_on return self._is_on
@property @property
@@ -81,5 +75,5 @@ class SystemStateSwitch(SwitchEntity):
@property @property
def should_poll(self) -> bool: def should_poll(self) -> bool:
""" Do not poll for those entities """ """ Do not poll for this entity """
return False return False