diff --git a/custom_components/nilan/climate.py b/custom_components/nilan/climate.py index 2c5f388..4109d28 100644 --- a/custom_components/nilan/climate.py +++ b/custom_components/nilan/climate.py @@ -55,27 +55,30 @@ async def async_setup_entry(hass, config_entry, async_add_entities): """Add climate entities for a config entry.""" - supported_features = SUPPORT_FAN_MODE | SUPPORT_TARGET_HUMIDITY + supported_features = SUPPORT_FAN_MODE hvac_basic_attributes = [ "get_run_state", "get_ventilation_step", "get_operation_mode", - "get_user_humidity_setpoint", - "get_humidity", "get_inlet_speed_step", "get_ventilation_state", "get_control_state", ] hvac_temperature_attributes = [ "get_user_temperature_setpoint", - "get_room_master_temperature", + "get_control_temperature", ] hvac_preset_attributes = [ "get_air_exchange_mode", ] + hvac_humidity_attributes = [ + "get_user_humidity_setpoint", + "get_humidity", + ] + # refine to select supported features automatically entities = [] device = hass.data[DOMAIN][config_entry.entry_id] @@ -89,6 +92,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities): attribute in device.get_attributes for attribute in hvac_preset_attributes ): supported_features |= SUPPORT_PRESET_MODE + if all( + attribute in device.get_attributes for attribute in hvac_humidity_attributes + ): + supported_features |= SUPPORT_TARGET_HUMIDITY entities.append(NilanClimate(device, supported_features)) async_add_entities(entities, True) diff --git a/custom_components/nilan/device.py b/custom_components/nilan/device.py index 8baa1c3..89df875 100644 --- a/custom_components/nilan/device.py +++ b/custom_components/nilan/device.py @@ -7,58 +7,30 @@ from .registers import CTS602InputRegisters, CTS602HoldingRegisters COMFORT_SUPPORTED_ENTITIES = { - "get_run_state": "climate", - "get_ventilation_step": "climate", - "get_operation_mode": "climate", - "get_user_humidity_setpoint": "climate", - "get_user_temperature_setpoint": "climate", - "get_room_master_temperature": "climate", - "get_control_state": "sensor", - "get_ventilation_state": "sensor", - "get_humidity": "sensor", - "get_average_humidity": "sensor", - "get_inlet_speed_step": "sensor", - "get_outlet_speed_step": "sensor", - "get_smoke_alarm": "sensor", - "get_t10_external_temperature": "sensor", - "get_t15_user_panel_temperature": "sensor", - "get_t6_evaporator_temperature": "sensor", - "get_t5_condenser_temperature": "sensor", - "get_t7_inlet_temperature_after_heater": "sensor", - "get_t1_intake_temperature": "sensor", - "get_t0_controller_temperature": "sensor", - "get_alarm_count": "sensor", - "get_time_in_control_state": "sensor", - "get_days_since_air_filter_change": "sensor", - "get_days_to_air_filter_change": "sensor", - "get_summer_state": "sensor", - "get_time": "sensor", - "get_supply_fan_level": "sensor", - "get_return_fan_level": "sensor", - "get_compressor_state": "binary_sensor", - "get_smoke_alarm_state": "binary_sensor", - "get_defrost_state": "binary_sensor", - "get_air_filter_alarm_interval": "select", - "get_air_quality_control_type": "select", + "get_bypass_flap_state": "binary_sensor", + "get_t8_outdoor_temperature": "sensor", + "get_t3_exhaust_temperature": "sensor", + "get_t4_outlet": "sensor", +} + +VP18C_SUPPORTED_ENTITIES = { + "get_air_exchange_mode": "climate", + "get_electric_water_heater_setpoint": "water_heater", + "get_electric_water_heater_state": "water_heater", + "get_compressor_water_heater_setpoint": "water_heater", + "get_t12_compressor_water_heater_temperature": "water_heater", + "get_t11_electric_water_heater_temperature": "water_heater", + "get_legionella_day": "select", + "get_hmi_language": "select", "get_compressor_priority": "select", - "get_cooling_mode_ventilation_step": "select", - "get_cooling_setpoint": "select", - "get_low_humidity_step": "select", - "get_high_humidity_step": "select", - "get_low_outdoor_temperature_ventilation_step": "select", "get_min_supply_step": "select", "get_min_return_step": "select", "get_max_return_step": "select", + "get_low_outdoor_temperature_ventilation_step": "select", "get_defrost_ventilation_level": "select", "get_scalding_protection_setpoint": "number", - "get_max_high_humidity_vent_time": "number", - "get_low_temperature_curve": "number", - "get_high_temperature_curve": "number", - "get_low_temperature_compressor_start_setpoint": "number", - "get_low_outdoor_temperature_setpoint": "number", - "get_min_supply_air_summer_setpoint": "number", - "get_min_supply_air_winter_setpoint": "number", - "get_summer_state_change_setpoint": "number", + "get_max_supply_air_summer_setpoint": "number", + "get_max_supply_air_winter_setpoint": "number", "get_supply_power_at_level_1": "number", "get_supply_power_at_level_2": "number", "get_supply_power_at_level_3": "number", @@ -68,75 +40,35 @@ "get_return_power_at_level_3": "number", "get_return_power_at_level_4": "number", "get_fan_startup_delay": "number", + "get_compressor_stop_time": "number", "get_defrost_start_setpoint": "number", "get_defrost_stop_setpoint": "number", "get_defrost_time": "number", - "get_compressor_stop_time": "number", + "get_low_temperature_compressor_start_setpoint": "number", + "get_low_outdoor_temperature_setpoint": "number", "get_low_room_temperature_setpoint": "number", -} - -VP18C_SUPPORTED_ENTITIES = { - "get_run_state": "climate", - "get_ventilation_step": "climate", - "get_operation_mode": "climate", - "get_user_humidity_setpoint": "climate", - "get_user_temperature_setpoint": "climate", - "get_room_master_temperature": "climate", - "get_air_exchange_mode": "climate", - "get_electric_water_heater_setpoint": "water_heater", - "get_electric_water_heater_state": "water_heater", - "get_compressor_water_heater_setpoint": "water_heater", - "get_compressor_water_heater_temperature": "water_heater", - "get_control_state": "sensor", - "get_ventilation_state": "sensor", - "get_humidity": "sensor", + "get_low_temperature_curve": "number", + "get_high_temperature_curve": "number", "get_average_humidity": "sensor", + "get_t7_inlet_temperature_after_heater": "sensor", "get_inlet_speed_step": "sensor", "get_outlet_speed_step": "sensor", - "get_smoke_alarm": "sensor", "get_t10_external_temperature": "sensor", - "get_t15_user_panel_temperature": "sensor", "get_t6_evaporator_temperature": "sensor", "get_t5_condenser_temperature": "sensor", - "get_t7_inlet_temperature_after_heater": "sensor", "get_t1_intake_temperature": "sensor", - "get_t0_controller_temperature": "sensor", - "get_alarm_count": "sensor", - "get_time_in_control_state": "sensor", - "get_days_since_air_filter_change": "sensor", - "get_days_to_air_filter_change": "sensor", - "get_summer_state": "sensor", - "get_time": "sensor", - "get_supply_fan_level": "sensor", - "get_return_fan_level": "sensor", "get_compressor_state": "binary_sensor", - "get_smoke_alarm_state": "binary_sensor", "get_defrost_state": "binary_sensor", - "get_air_filter_alarm_interval": "select", - "get_legionella_day": "select", - "get_air_quality_control_type": "select", - "get_compressor_priority": "select", - "get_cooling_mode_ventilation_step": "select", - "get_cooling_setpoint": "select", - "get_low_humidity_step": "select", - "get_high_humidity_step": "select", +} + +COMBI302_SUPPORTED_ENTITIES = { "get_hmi_language": "select", - "get_low_outdoor_temperature_ventilation_step": "select", "get_min_supply_step": "select", "get_min_return_step": "select", "get_max_return_step": "select", + "get_compressor_priority": "select", + "get_low_outdoor_temperature_ventilation_step": "select", "get_defrost_ventilation_level": "select", - "get_scalding_protection_setpoint": "number", - "get_max_high_humidity_vent_time": "number", - "get_low_temperature_curve": "number", - "get_high_temperature_curve": "number", - "get_low_temperature_compressor_start_setpoint": "number", - "get_low_outdoor_temperature_setpoint": "number", - "get_min_supply_air_summer_setpoint": "number", - "get_max_supply_air_summer_setpoint": "number", - "get_min_supply_air_winter_setpoint": "number", - "get_max_supply_air_winter_setpoint": "number", - "get_summer_state_change_setpoint": "number", "get_supply_power_at_level_1": "number", "get_supply_power_at_level_2": "number", "get_supply_power_at_level_3": "number", @@ -145,34 +77,44 @@ "get_return_power_at_level_2": "number", "get_return_power_at_level_3": "number", "get_return_power_at_level_4": "number", + "get_maximum_compressor_defrost_time": "number", + "get_maximum_outlet_defrost_time": "number", + "get_time_between_defrost": "number", "get_fan_startup_delay": "number", + "get_compressor_stop_time": "number", "get_defrost_start_setpoint": "number", "get_defrost_stop_setpoint": "number", "get_defrost_time": "number", - "get_compressor_stop_time": "number", + "get_low_temperature_compressor_start_setpoint": "number", + "get_low_outdoor_temperature_setpoint": "number", "get_low_room_temperature_setpoint": "number", + "get_low_temperature_curve": "number", + "get_high_temperature_curve": "number", + "get_average_humidity": "sensor", + "get_inlet_speed_step": "sensor", + "get_outlet_speed_step": "sensor", + "get_t10_external_temperature": "sensor", + "get_t7_inlet_temperature_after_heater": "sensor", + "get_t6_evaporator_temperature": "sensor", + "get_t5_condenser_temperature": "sensor", + "get_t1_intake_temperature": "sensor", + "get_compressor_state": "binary_sensor", + "get_defrost_state": "binary_sensor", + "get_bypass_flap_state": "binary_sensor", } -COMBI302_SUPPORTED_ENTITIES = { +COMMON_ENTITIES = { "get_run_state": "climate", "get_ventilation_step": "climate", "get_operation_mode": "climate", "get_user_humidity_setpoint": "climate", "get_user_temperature_setpoint": "climate", - "get_room_master_temperature": "climate", + "get_control_temperature": "climate", "get_control_state": "sensor", "get_ventilation_state": "sensor", "get_humidity": "sensor", - "get_average_humidity": "sensor", - "get_inlet_speed_step": "sensor", - "get_outlet_speed_step": "sensor", "get_smoke_alarm": "sensor", - "get_t10_external_temperature": "sensor", "get_t15_user_panel_temperature": "sensor", - "get_t6_evaporator_temperature": "sensor", - "get_t5_condenser_temperature": "sensor", - "get_t7_inlet_temperature_after_heater": "sensor", - "get_t1_intake_temperature": "sensor", "get_t0_controller_temperature": "sensor", "get_alarm_count": "sensor", "get_time_in_control_state": "sensor", @@ -182,45 +124,19 @@ "get_time": "sensor", "get_supply_fan_level": "sensor", "get_return_fan_level": "sensor", - "get_compressor_state": "binary_sensor", + "get_return_fan_speed": "sensor", + "get_supply_fan_speed": "sensor", "get_smoke_alarm_state": "binary_sensor", - "get_defrost_state": "binary_sensor", - "get_bypass_flap_state": "binary_sensor", "get_air_filter_alarm_interval": "select", "get_air_quality_control_type": "select", "get_cooling_mode_ventilation_step": "select", "get_cooling_setpoint": "select", "get_low_humidity_step": "select", "get_high_humidity_step": "select", - "get_hmi_language": "select", - "get_low_outdoor_temperature_ventilation_step": "select", - "get_min_supply_step": "select", - "get_min_return_step": "select", - "get_max_return_step": "select", - "get_defrost_ventilation_level": "select", "get_max_high_humidity_vent_time": "number", - "get_low_temperature_curve": "number", - "get_high_temperature_curve": "number", - "get_low_temperature_compressor_start_setpoint": "number", - "get_low_outdoor_temperature_setpoint": "number", - "get_summer_state_change_setpoint": "number", - "get_supply_power_at_level_1": "number", - "get_supply_power_at_level_2": "number", - "get_supply_power_at_level_3": "number", - "get_supply_power_at_level_4": "number", - "get_return_power_at_level_1": "number", - "get_return_power_at_level_2": "number", - "get_return_power_at_level_3": "number", - "get_return_power_at_level_4": "number", - "get_fan_startup_delay": "number", - "get_defrost_start_setpoint": "number", - "get_defrost_stop_setpoint": "number", - "get_defrost_time": "number", - "get_compressor_stop_time": "number", - "get_low_room_temperature_setpoint": "number", "get_min_supply_air_summer_setpoint": "number", - "get_max_supply_air_summer_setpoint": "number", - "get_external_heating_offset": "number", + "get_min_supply_air_winter_setpoint": "number", + "get_summer_state_change_setpoint": "number", } HW_VERSION_TO_DEVICE = { @@ -229,6 +145,12 @@ 35: COMBI302_SUPPORTED_ENTITIES, } +DEVICE_TYPES = { + 13: "COMFORT", + 19: "VP 18c", + 35: "COMBI 302", +} + CO2_PRESENT_TO_ATTRIBUTES = { "get_co2_sensor_value": "sensor", "get_co2_ventilation_high_step": "select", @@ -254,13 +176,6 @@ WATER_AFTER_HEATER_PRESENT_TO_ATTRIBUTES = {} -DEVICE_TYPES = { - 13: "COMFORT", - 19: "VP 18c", - 35: "COMBI 302", -} - - class Device: """Nilan Device""" @@ -295,8 +210,10 @@ async def setup(self): hw_type = await self.get_machine_type() if hw_type in HW_VERSION_TO_DEVICE: self._device_sw_ver = await self.get_controller_software_version() - self._device_hw_ver = await self.get_controller_hardware_version() - self._attributes = HW_VERSION_TO_DEVICE[hw_type] + if hw_type not in (13,): + self._device_hw_ver = await self.get_controller_hardware_version() + self._attributes = COMMON_ENTITIES + self._attributes.update(HW_VERSION_TO_DEVICE[hw_type]) self._device_type = DEVICE_TYPES[hw_type] if await self.get_co2_present(): self._attributes.update(CO2_PRESENT_TO_ATTRIBUTES) @@ -377,8 +294,8 @@ async def get_controller_software_version(self) -> str: char1 = chr(value >> 8) char2 = chr(value & 0x00FF) version += char1 + char2 + "." - version += "0" version = version.replace(" ", "") + version = version[:-1] return version async def get_controller_hardware_version(self) -> int: @@ -615,6 +532,34 @@ async def get_return_fan_level(self) -> int: ) return None + async def get_return_fan_speed(self) -> int: + """get Actual exhaust fan speed.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602HoldingRegisters.output_exhaust_speed, 1, "holding" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=False, + ) + return value / 100 + return None + + async def get_supply_fan_speed(self) -> int: + """get Actual inlet fan speed.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602HoldingRegisters.output_inlet_speed, 1, "holding" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=False, + ) + return value / 100 + return None + async def get_co2_low_limit_setpoint(self) -> int: """get co2 low limit setpoint.""" result = await self._modbus.async_pymodbus_call( @@ -661,6 +606,20 @@ async def get_room_master_temperature(self) -> float: return float(value) / 100 return None + async def get_control_temperature(self) -> float: + """get Master Room Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602InputRegisters.air_temp_temp_control, 1, "input" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + async def get_after_heating_element_capacity(self) -> float: """get After Heating Element Capacity.""" result = await self._modbus.async_pymodbus_call( @@ -797,8 +756,42 @@ async def get_t2_inlet_temperature(self) -> float: return float(value) / 100 return None + async def get_t3_exhaust_temperature(self) -> float: + """get T3 Exhaust Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t3_exhaust, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t4_outlet(self) -> float: + """get T4 Outlet Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t4_outlet, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + async def get_t5_condenser_temperature(self) -> float: - """get T1 fresh air intake Temperature.""" + """get T5 Condenser Temperature.""" result = await self._modbus.async_pymodbus_call( self._unit_id, CTS602InputRegisters.input_t5_cond, 1, "input" ) @@ -839,6 +832,34 @@ async def get_t7_inlet_temperature_after_heater(self) -> float: return float(value) / 100 return None + async def get_t8_outdoor_temperature(self) -> float: + """get T8 Outdoor Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602InputRegisters.input_t8_outdoor, 1, "input" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t9_heater_temperature(self) -> float: + """get T9 Heater Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602InputRegisters.input_t9_heater, 1, "input" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + async def get_t10_external_temperature(self) -> float: """get T10 external Temperature.""" result = await self._modbus.async_pymodbus_call( @@ -856,6 +877,74 @@ async def get_t10_external_temperature(self) -> float: return float(value) / 100 return None + async def get_t11_electric_water_heater_temperature(self) -> float: + """get T11 electric water heater temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t11_top, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t12_compressor_water_heater_temperature(self) -> float: + """get T12 compressor water heater temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t12_bottom, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t13_return_temperature(self) -> float: + """get T13 Return temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t13_return, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t14_supply_temperature(self) -> float: + """get T13 Return temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602InputRegisters.input_t14_supply, + 1, + "input", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + async def get_t15_user_panel_temperature(self) -> float: """get T15 user panel Temperature.""" result = await self._modbus.async_pymodbus_call( @@ -870,6 +959,34 @@ async def get_t15_user_panel_temperature(self) -> float: return float(value) / 100 return None + async def get_t16_sacrificial_anode_temperature(self) -> float: + """get T16 Sacrificial Anode Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602InputRegisters.input_t16, 1, "input" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + + async def get_t17_preheater_temperature(self) -> float: + """get T17 Preheater Temperature.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, CTS602InputRegisters.input_t17_pre_heat, 1, "input" + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=True, + ) + return float(value) / 100 + return None + async def get_co2_sensor_value(self) -> float: """get co2 sensor value.""" result = await self._modbus.async_pymodbus_call( @@ -1303,6 +1420,57 @@ async def get_minimum_defrost_time(self) -> int: return value return None + async def get_maximum_outlet_defrost_time(self) -> int: + """get maximum outlet defrost time in m.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_dur_max_exh, + 1, + "holding", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=False, + ) + return value + return None + + async def get_maximum_compressor_defrost_time(self) -> int: + """get maximum compressor defrost time in m.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_dur_max_cpr, + 1, + "holding", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=False, + ) + return value + return None + + async def get_time_between_defrost(self) -> int: + """get Frost protection or de-icing - Time between activations in m.""" + result = await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_block_minutes, + 1, + "holding", + ) + if result is not None: + value = int.from_bytes( + result.registers[0].to_bytes(2, "little", signed=False), + "little", + signed=False, + ) + return value + return None + async def get_compressor_stop_time(self) -> int: """get time that compressor is in stop state.""" result = await self._modbus.async_pymodbus_call( @@ -1732,40 +1900,6 @@ async def get_humidity(self) -> float: return float(value) / 100 return None - async def get_electric_water_heater_temperature(self) -> float: - """get electric water heater temperature.""" - result = await self._modbus.async_pymodbus_call( - self._unit_id, - CTS602InputRegisters.input_t11_top, - 1, - "input", - ) - if result is not None: - value = int.from_bytes( - result.registers[0].to_bytes(2, "little", signed=False), - "little", - signed=True, - ) - return float(value) / 100 - return None - - async def get_compressor_water_heater_temperature(self) -> float: - """get compressor water heater temperature.""" - result = await self._modbus.async_pymodbus_call( - self._unit_id, - CTS602InputRegisters.input_t12_bottom, - 1, - "input", - ) - if result is not None: - value = int.from_bytes( - result.registers[0].to_bytes(2, "little", signed=False), - "little", - signed=True, - ) - return float(value) / 100 - return None - async def get_central_heat_supply_curve_offset(self) -> float: """get supply curve offset temp.""" result = await self._modbus.async_pymodbus_call( @@ -2342,6 +2476,42 @@ async def set_minimum_defrost_time(self, value: int) -> bool: return True return False + async def set_maximum_outlet_defrost_time(self, value: int) -> bool: + """set maximum outlet defrost time in s.""" + if value >= 5 and value <= 60: + await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_dur_max_exh, + value, + "write_registers", + ) + return True + return False + + async def set_maximum_compressor_defrost_time(self, value: int) -> bool: + """set maximum compressor defrost time in s.""" + if value >= 2 and value <= 60: + await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_dur_max_cpr, + value, + "write_registers", + ) + return True + return False + + async def set_time_between_defrost(self, value: int) -> bool: + """set Frost protection or de-icing - Time between activations in m.""" + if value >= 15 and value <= 720: + await self._modbus.async_pymodbus_call( + self._unit_id, + CTS602HoldingRegisters.defrost_dur_max_cpr, + value, + "write_registers", + ) + return True + return False + async def set_supply_heater_delay(self, value: int) -> bool: """set supply heater delay in m.""" if value >= 0 and value <= 30: diff --git a/custom_components/nilan/manifest.json b/custom_components/nilan/manifest.json index 71df848..aa261dd 100644 --- a/custom_components/nilan/manifest.json +++ b/custom_components/nilan/manifest.json @@ -1,7 +1,7 @@ { "domain": "nilan", "name": "Nilan", - "version": "1.0.10", + "version": "1.0.11", "config_flow": true, "documentation": "https://github.com/veista/nilan", "requirements": ["pymodbus==2.5.3"], diff --git a/custom_components/nilan/number.py b/custom_components/nilan/number.py index 5320251..ceeaee1 100644 --- a/custom_components/nilan/number.py +++ b/custom_components/nilan/number.py @@ -341,6 +341,45 @@ "mdi:wrench-clock", ) ], + "get_maximum_compressor_defrost_time": [ + Map( + "Maximum Evaporator Defrost Time", + "set_maximum_compressor_defrost_time", + EntityCategory.CONFIG, + 2, + 60, + 1, + NumberMode.BOX, + TIME_MINUTES, + "mdi:wrench-clock", + ) + ], + "get_maximum_outlet_defrost_time": [ + Map( + "Maximum Outlet Defrost Time", + "set_maximum_outlet_defrost_time", + EntityCategory.CONFIG, + 5, + 60, + 1, + NumberMode.BOX, + TIME_MINUTES, + "mdi:wrench-clock", + ) + ], + "get_time_between_defrost": [ + Map( + "Time Between Defrost Cycles", + "set_time_between_defrost", + EntityCategory.CONFIG, + 15, + 720, + 1, + NumberMode.BOX, + TIME_MINUTES, + "mdi:wrench-clock", + ) + ], "get_supply_heating_pid_time": [ Map( "Supply Air PID Integration Time", @@ -473,8 +512,6 @@ ], } -# "get_supply_heater_delay": "number", - async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the number platform.""" diff --git a/custom_components/nilan/select.py b/custom_components/nilan/select.py index ac9d8a9..d9c614e 100644 --- a/custom_components/nilan/select.py +++ b/custom_components/nilan/select.py @@ -218,7 +218,7 @@ Map( "Cooling Mode Ventilation Level", "set_cooling_mode_ventilation_step", - None, + EntityCategory.CONFIG, COOLING_STEP_TO_NUMBER, NUMBER_TO_COOLING_STEP, "mdi:fan", @@ -228,7 +228,7 @@ Map( "Cooling Setpoint Offset", "set_cooling_setpoint", - None, + EntityCategory.CONFIG, COOLING_SETPOINT_TO_NUMBER, NUMBER_TO_COOLING_SETPOINT, "mdi:thermometer-lines", diff --git a/custom_components/nilan/sensor.py b/custom_components/nilan/sensor.py index ce33bda..ea13cb5 100644 --- a/custom_components/nilan/sensor.py +++ b/custom_components/nilan/sensor.py @@ -113,6 +113,28 @@ None, ) ], + "get_t3_exhaust_temperature": [ + Map( + "Return Air Temperature", + TEMP_CELSIUS, + SensorDeviceClass.TEMPERATURE, + SensorStateClass.MEASUREMENT, + None, + None, + None, + ) + ], + "get_t4_outlet": [ + Map( + "Supply Air Temperature", + TEMP_CELSIUS, + SensorDeviceClass.TEMPERATURE, + SensorStateClass.MEASUREMENT, + None, + None, + None, + ) + ], "get_t5_condenser_temperature": [ Map( "Condenser Temperature", @@ -146,6 +168,17 @@ None, ) ], + "get_t8_outdoor_temperature": [ + Map( + "Fresh Air Intake Temperature", + TEMP_CELSIUS, + SensorDeviceClass.TEMPERATURE, + SensorStateClass.MEASUREMENT, + None, + None, + None, + ) + ], "get_t10_external_temperature": [ Map( "Return Air Temperature", @@ -344,6 +377,28 @@ None, ) ], + "get_return_fan_speed": [ + Map( + "Return Fan Speed", + PERCENTAGE, + None, + SensorStateClass.MEASUREMENT, + None, + "mdi:fan", + None, + ) + ], + "get_supply_fan_speed": [ + Map( + "Supply Fan Speed", + PERCENTAGE, + None, + SensorStateClass.MEASUREMENT, + None, + "mdi:fan", + None, + ) + ], }