""" MySensors platform that offers a Climate (MySensors-HVAC) component. For more details about this platform, please refer to the documentation https://home-assistant.io/components/climate.mysensors/ """ import logging from homeassistant.components import mysensors from homeassistant.components.climate import ( STATE_COOL, STATE_HEAT, STATE_OFF, STATE_AUTO, ClimateDevice, ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW) from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE _LOGGER = logging.getLogger(__name__) DICT_HA_TO_MYS = { STATE_AUTO: 'AutoChangeOver', STATE_COOL: 'CoolOn', STATE_HEAT: 'HeatOn', STATE_OFF: 'Off', } DICT_MYS_TO_HA = { 'AutoChangeOver': STATE_AUTO, 'CoolOn': STATE_COOL, 'HeatOn': STATE_HEAT, 'Off': STATE_OFF, } def setup_platform(hass, config, add_devices, discovery_info=None): """Set up the mysensors climate.""" if discovery_info is None: return gateways = hass.data.get(mysensors.MYSENSORS_GATEWAYS) if not gateways: return for gateway in gateways: if float(gateway.protocol_version) < 1.5: continue pres = gateway.const.Presentation set_req = gateway.const.SetReq map_sv_types = { pres.S_HVAC: [set_req.V_HVAC_FLOW_STATE], } devices = {} gateway.platform_callbacks.append(mysensors.pf_callback_factory( map_sv_types, devices, MySensorsHVAC, add_devices)) class MySensorsHVAC(mysensors.MySensorsDeviceEntity, ClimateDevice): """Representation of a MySensors HVAC.""" @property def assumed_state(self): """Return True if unable to access real state of entity.""" return self.gateway.optimistic @property def temperature_unit(self): """Return the unit of measurement.""" return (TEMP_CELSIUS if self.gateway.metric else TEMP_FAHRENHEIT) @property def current_temperature(self): """Return the current temperature.""" return float(self._values.get(self.gateway.const.SetReq.V_TEMP)) @property def target_temperature(self): """Return the temperature we try to reach.""" set_req = self.gateway.const.SetReq if set_req.V_HVAC_SETPOINT_COOL in self._values and \ set_req.V_HVAC_SETPOINT_HEAT in self._values: return None temp = self._values.get(set_req.V_HVAC_SETPOINT_COOL) if temp is None: temp = self._values.get(set_req.V_HVAC_SETPOINT_HEAT) return float(temp) @property def target_temperature_high(self): """Return the highbound target temperature we try to reach.""" set_req = self.gateway.const.SetReq if set_req.V_HVAC_SETPOINT_HEAT in self._values: return float(self._values.get(set_req.V_HVAC_SETPOINT_COOL)) @property def target_temperature_low(self): """Return the lowbound target temperature we try to reach.""" set_req = self.gateway.const.SetReq if set_req.V_HVAC_SETPOINT_COOL in self._values: return float(self._values.get(set_req.V_HVAC_SETPOINT_HEAT)) @property def current_operation(self): """Return current operation ie. heat, cool, idle.""" return self._values.get(self.gateway.const.SetReq.V_HVAC_FLOW_STATE) @property def operation_list(self): """List of available operation modes.""" return [STATE_OFF, STATE_AUTO, STATE_COOL, STATE_HEAT] @property def current_fan_mode(self): """Return the fan setting.""" return self._values.get(self.gateway.const.SetReq.V_HVAC_SPEED) @property def fan_list(self): """List of available fan modes.""" return ['Auto', 'Min', 'Normal', 'Max'] def set_temperature(self, **kwargs): """Set new target temperature.""" set_req = self.gateway.const.SetReq temp = kwargs.get(ATTR_TEMPERATURE) low = kwargs.get(ATTR_TARGET_TEMP_LOW) high = kwargs.get(ATTR_TARGET_TEMP_HIGH) heat = self._values.get(set_req.V_HVAC_SETPOINT_HEAT) cool = self._values.get(set_req.V_HVAC_SETPOINT_COOL) updates = () if temp is not None: if heat is not None: # Set HEAT Target temperature value_type = set_req.V_HVAC_SETPOINT_HEAT elif cool is not None: # Set COOL Target temperature value_type = set_req.V_HVAC_SETPOINT_COOL if heat is not None or cool is not None: updates = [(value_type, temp)] elif all(val is not None for val in (low, high, heat, cool)): updates = [ (set_req.V_HVAC_SETPOINT_HEAT, low), (set_req.V_HVAC_SETPOINT_COOL, high)] for value_type, value in updates: self.gateway.set_child_value( self.node_id, self.child_id, value_type, value) if self.gateway.optimistic: # optimistically assume that switch has changed state self._values[value_type] = value self.schedule_update_ha_state() def set_fan_mode(self, fan): """Set new target temperature.""" set_req = self.gateway.const.SetReq self.gateway.set_child_value( self.node_id, self.child_id, set_req.V_HVAC_SPEED, fan) if self.gateway.optimistic: # optimistically assume that switch has changed state self._values[set_req.V_HVAC_SPEED] = fan self.schedule_update_ha_state() def set_operation_mode(self, operation_mode): """Set new target temperature.""" set_req = self.gateway.const.SetReq self.gateway.set_child_value( self.node_id, self.child_id, set_req.V_HVAC_FLOW_STATE, DICT_HA_TO_MYS[operation_mode]) if self.gateway.optimistic: # optimistically assume that switch has changed state self._values[set_req.V_HVAC_FLOW_STATE] = operation_mode self.schedule_update_ha_state() def update(self): """Update the controller with the latest value from a sensor.""" set_req = self.gateway.const.SetReq node = self.gateway.sensors[self.node_id] child = node.children[self.child_id] for value_type, value in child.values.items(): _LOGGER.debug( "%s: value_type %s, value = %s", self._name, value_type, value) if value_type == set_req.V_HVAC_FLOW_STATE: self._values[value_type] = DICT_MYS_TO_HA[value] else: self._values[value_type] = value def set_humidity(self, humidity): """Set new target humidity.""" _LOGGER.error("Service Not Implemented yet") def set_swing_mode(self, swing_mode): """Set new target swing operation.""" _LOGGER.error("Service Not Implemented yet") def turn_away_mode_on(self): """Turn away mode on.""" _LOGGER.error("Service Not Implemented yet") def turn_away_mode_off(self): """Turn away mode off.""" _LOGGER.error("Service Not Implemented yet") def turn_aux_heat_on(self): """Turn auxillary heater on.""" _LOGGER.error("Service Not Implemented yet") def turn_aux_heat_off(self): """Turn auxillary heater off.""" _LOGGER.error("Service Not Implemented yet")