Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 70 additions & 18 deletions custom_components/daikinskyport/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.helpers.event import async_track_state_change_event
from homeassistant.core import HomeAssistant, ServiceCall, Event, callback
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.device_registry import DeviceInfo

Expand All @@ -50,6 +51,7 @@
DAIKIN_HVAC_MODE_AUTO,
DAIKIN_HVAC_MODE_AUXHEAT,
COORDINATOR,
CONF_TEMP_OFFSET_SENSOR,
)

WEEKDAY = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
Expand Down Expand Up @@ -233,7 +235,7 @@ async def async_setup_entry(

for index in range(len(coordinator.daikinskyport.thermostats)):
thermostat = coordinator.daikinskyport.get_thermostat(index)
entities.append(Thermostat(coordinator, index, thermostat))
entities.append(Thermostat(hass, entry, coordinator, index, thermostat))

async_add_entities(entities, True)

Expand Down Expand Up @@ -396,8 +398,10 @@ class Thermostat(ClimateEntity):
_attr_has_entity_name = True
_enable_turn_on_off_backwards_compatibility = False

def __init__(self, data, thermostat_index, thermostat):
def __init__(self, hass, entry, data, thermostat_index, thermostat):
"""Initialize the thermostat."""
self.hass = hass
self.entry = entry
self.data = data
self.thermostat_index = thermostat_index
self.thermostat = thermostat
Expand Down Expand Up @@ -437,6 +441,38 @@ def __init__(self, data, thermostat_index, thermostat):
}
self._fan_modes = [FAN_AUTO, FAN_ON, FAN_LOW, FAN_MEDIUM, FAN_HIGH, FAN_SCHEDULE]
self.update_without_throttle = False
self._offset_sensor_unsub = None

async def async_added_to_hass(self) -> None:
"""Run when entity is added to hass."""
await super().async_added_to_hass()
self._subscribe_to_offset_sensor()

def _subscribe_to_offset_sensor(self) -> None:
"""Subscribe to offset sensor state changes."""
# Unsubscribe from previous sensor if any
if self._offset_sensor_unsub is not None:
self._offset_sensor_unsub()
self._offset_sensor_unsub = None

offset_sensor_id = self.entry.options.get(CONF_TEMP_OFFSET_SENSOR)
if not offset_sensor_id:
return

@callback
def _async_offset_sensor_changed(event: Event) -> None:
"""Handle offset sensor state changes."""
self.async_write_ha_state()

self._offset_sensor_unsub = async_track_state_change_event(
self.hass, [offset_sensor_id], _async_offset_sensor_changed
)

async def async_will_remove_from_hass(self) -> None:
"""Run when entity is removed from hass."""
if self._offset_sensor_unsub is not None:
self._offset_sensor_unsub()
self._offset_sensor_unsub = None

async def async_update(self):
"""Get the latest state from the thermostat."""
Expand Down Expand Up @@ -464,6 +500,19 @@ async def async_update(self):
else:
self._preset_mode = PRESET_MANUAL

def _get_temp_offset(self) -> float:
"""Get the temperature offset from the configured sensor."""
offset_sensor_id = self.entry.options.get(CONF_TEMP_OFFSET_SENSOR)
if not offset_sensor_id:
return 0.0
state = self.hass.states.get(offset_sensor_id)
if state is None or state.state in ("unknown", "unavailable"):
return 0.0
try:
return float(state.state)
except (ValueError, TypeError):
return 0.0

@property
def device_info(self) -> DeviceInfo:
return self.data.device_info
Expand All @@ -486,20 +535,20 @@ def name(self):
@property
def current_temperature(self) -> float:
"""Return the current temperature."""
return self.thermostat["tempIndoor"]
return self.thermostat["tempIndoor"] - self._get_temp_offset()

@property
def target_temperature_low(self):
"""Return the lower bound temperature we try to reach."""
if self.hvac_mode == HVACMode.AUTO:
return self._heat_setpoint
return self._heat_setpoint - self._get_temp_offset()
return None

@property
def target_temperature_high(self):
"""Return the upper bound temperature we try to reach."""
if self.hvac_mode == HVACMode.AUTO:
return self._cool_setpoint
return self._cool_setpoint - self._get_temp_offset()
return None

@property
Expand All @@ -508,9 +557,9 @@ def target_temperature(self):
if self.hvac_mode == HVACMode.AUTO:
return None
if self.hvac_mode == HVACMode.HEAT:
return self._heat_setpoint
return self._heat_setpoint - self._get_temp_offset()
if self.hvac_mode == HVACMode.COOL:
return self._cool_setpoint
return self._cool_setpoint - self._get_temp_offset()
return None

@property
Expand Down Expand Up @@ -659,13 +708,15 @@ def preset_modes(self):

def set_auto_temp_hold(self, heat_temp, cool_temp):
"""Set temperature hold in auto mode."""
offset = self._get_temp_offset()

if cool_temp is not None:
cool_temp_setpoint = cool_temp
cool_temp_setpoint = cool_temp + offset
else:
cool_temp_setpoint = self.thermostat["cspHome"]

if heat_temp is not None:
heat_temp_setpoint = heat_temp
heat_temp_setpoint = heat_temp + offset
else:
heat_temp_setpoint = self.thermostat["hspHome"]

Expand All @@ -682,7 +733,7 @@ def set_auto_temp_hold(self, heat_temp, cool_temp):
heat_temp_setpoint,
self.hold_preference(),
)

self._cool_setpoint = cool_temp_setpoint
self._heat_setpoint = heat_temp_setpoint

Expand Down Expand Up @@ -737,16 +788,20 @@ def set_fan_mode(self, fan_mode):

def set_temp_hold(self, temp):
"""Set temperature hold in modes other than auto."""
offset = self._get_temp_offset()
if self.hvac_mode == HVACMode.HEAT:
heat_temp = temp
cool_temp = self.thermostat["cspHome"]
cool_temp = None
elif self.hvac_mode == HVACMode.COOL:
cool_temp = temp
heat_temp = self.thermostat["hspHome"]
heat_temp = None
self.set_auto_temp_hold(heat_temp, cool_temp)

self._cool_setpoint = cool_temp
self._heat_setpoint = heat_temp
# Update local setpoints with Daikin-adjusted values
if cool_temp is not None:
self._cool_setpoint = cool_temp + offset
if heat_temp is not None:
self._heat_setpoint = heat_temp + offset

def set_temperature(self, **kwargs):
"""Set new target temperature."""
Expand All @@ -763,9 +818,6 @@ def set_temperature(self, **kwargs):
else:
_LOGGER.error("Missing valid arguments for set_temperature in %s", kwargs)

self._cool_setpoint = high_temp
self._heat_setpoint = low_temp


def set_humidity(self, humidity):
"""Set the humidity level."""
Expand Down
8 changes: 8 additions & 0 deletions custom_components/daikinskyport/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.selector import EntitySelector, EntitySelectorConfig
from homeassistant.helpers.schema_config_entry_flow import (
SchemaFlowFormStep,
SchemaOptionsFlowHandler,
Expand All @@ -18,13 +19,20 @@
DOMAIN,
CONF_ACCESS_TOKEN,
CONF_REFRESH_TOKEN,
CONF_TEMP_OFFSET_SENSOR,
)
import voluptuous as vol
from .daikinskyport import DaikinSkyport

OPTIONS_SCHEMA = vol.Schema(
{
vol.Optional(CONF_NAME, default="Daikin"): str,
vol.Optional(CONF_TEMP_OFFSET_SENSOR): EntitySelector(
EntitySelectorConfig(
domain="sensor",
device_class="temperature_delta",
)
),
}
)
OPTIONS_FLOW = {
Expand Down
1 change: 1 addition & 0 deletions custom_components/daikinskyport/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,6 @@

CONF_REFRESH_TOKEN = "refresh_token"
CONF_ACCESS_TOKEN = "access_token"
CONF_TEMP_OFFSET_SENSOR = "temp_offset_sensor"

COORDINATOR = "coordinator"
6 changes: 5 additions & 1 deletion custom_components/daikinskyport/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
"init": {
"description": "Daikin Skyport Integration for DaikinOne+ Thermostat",
"data": {
"name": "Name"
"name": "Name",
"temp_offset_sensor": "Temperature Offset Sensor"
},
"data_description": {
"temp_offset_sensor": "Select a sensor that provides a temperature offset value. This offset will be applied to all temperature readings and setpoints (e.g., if the sensor shows 2, displayed temperatures will be reduced by 2°C and setpoints will be increased by 2°C when sent to the thermostat)."
}
}
}
Expand Down