Skip to content

Commit

Permalink
Preliminary support for climate controls. Seeing some issues, TBC
Browse files Browse the repository at this point in the history
  • Loading branch information
optiluca committed Dec 19, 2022
1 parent 78c552a commit 7f9e2e2
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 1 deletion.
1 change: 1 addition & 0 deletions custom_components/comelit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def setup(hass, config):
hass.helpers.discovery.load_platform('cover', DOMAIN, {}, config)
hass.helpers.discovery.load_platform('scene', DOMAIN, {}, config)
hass.helpers.discovery.load_platform('switch', DOMAIN, {}, config)
hass.helpers.discovery.load_platform('climate', DOMAIN, {}, config)
_LOGGER.info("Comelit Hub integration started")

# Comelit Vedo
Expand Down
87 changes: 87 additions & 0 deletions custom_components/comelit/climate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import logging


from homeassistant.components.climate import ClimateEntity

from homeassistant.components.climate import HVACMode, HVACAction

from homeassistant.components.climate.const import (
SUPPORT_TARGET_TEMPERATURE
)
from homeassistant.const import (
ATTR_TEMPERATURE,
TEMP_CELSIUS,
)

from .const import DOMAIN

from .comelit_device import ComelitDevice

_LOGGER = logging.getLogger(__name__)



def setup_platform(hass, config, add_entities, discovery_info=None):
hass.data[DOMAIN]['hub'].climate_add_entities = add_entities
_LOGGER.info("Comelit Climate Integration started")

class ComelitClimate(ComelitDevice, ClimateEntity):
def __init__(self, id, description, state, measured_temperature, target_temperature, measured_humidity, hub):
ComelitDevice.__init__(self, id, "climate", description)
self._hub = hub
self._state = state
self._temperature = measured_temperature
self._target_temperature = target_temperature
self._humidity = measured_humidity

@property
def hvac_mode(self):
return HVACMode.HEAT if self._state else HVACMode.OFF

@property
def hvac_modes(self):
return [HVACMode.HEAT, HVACMode.OFF]

@property
def hvac_action(self):
if self._state:
return HVACAction.HEATING
else:
return HVACAction.IDLE if self._target_temperature else HVACAction.OFF

@property
def target_temperature(self):
return self._target_temperature

@property
def temperature_unit(self):
return TEMP_CELSIUS

@property
def current_temperature(self):
return self._temperature

@property
def current_humidity(self):
return self._humidity

@property
def supported_features(self):
return SUPPORT_TARGET_TEMPERATURE

def set_temperature(self, **kwargs):
temperature = kwargs.get(ATTR_TEMPERATURE)
if temperature is not None:
self._hub.climate_set_temperature(self._id, temperature)

def set_hvac_mode(self, hvac_mode):
self._hub.climate_set_state(self._id, hvac_mode == HVACMode.HEAT)

def update_state(self, state, temperature, humidity):
self._state = state
self._temperature = temperature
self._humidity = humidity
self.async_write_ha_state()

def update(self):
pass
63 changes: 62 additions & 1 deletion custom_components/comelit/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .light import ComelitLight
from .cover import ComelitCover
from .switch import ComelitSwitch
from .climate import ComelitClimate
import logging

_LOGGER = logging.getLogger(__name__)
Expand All @@ -29,6 +30,7 @@ class RequestType:
STATUS = 0
LIGHT = 1
AUTOMATION = 1
TEMPERATURE = 1
COVER = 1
SCENARIO = 1
ANNOUNCE = 13
Expand All @@ -39,6 +41,7 @@ class RequestType:
class HubFields:
TOKEN = 'sessiontoken'
TEMPERATURE = 'temperatura'
TARGET_TEMPERATURE = 'soglia_attiva'
HUMIDITY = 'umidita'
DESCRIPTION = 'descrizione'
INSTANT_POWER = 'instant_power'
Expand Down Expand Up @@ -152,6 +155,22 @@ def cover_position(self, id, position):
def cover_down(self, id):
self.off(RequestType.COVER, id)

def climate_set_temperature(self, id, temperature):
try:
_LOGGER.info(f'Setting climate {id} to temperature {temperature}')
req = {"req_type": RequestType.TEMPERATURE, "req_sub_type": 3, "obj_id": id, "act_type": 2, "act_params": [temperature]}
self._hub.publish(req)
except Exception as e:
_LOGGER.exception("Error setting temperature %s", e)

def climate_set_state(self, id, state):
try:
_LOGGER.info(f'Setting climate {id} to state {state}')
req = {"req_type": RequestType.TEMPERATURE, "req_sub_type": 3, "obj_id": id, "act_type": 0, "act_params": [int(state)]}
self._hub.publish(req)
except Exception as e:
_LOGGER.exception("Error setting climate state %s", e)


# Manage scenario
class SceneHub:
Expand All @@ -173,6 +192,7 @@ class ComelitHub:
def __init__(self, client_name, hub_serial, hub_host, mqtt_port, mqtt_user, mqtt_password, hub_user, hub_password, scan_interval):
"""Initialize the sensor."""
self.sensors = {}
self.climates = {}
self.lights = {}
self.covers = {}
self.scenes = {}
Expand Down Expand Up @@ -212,6 +232,11 @@ def dispatch(self, payload):
try:
req_type = payload["req_type"]

if req_type == RequestType.STATUS:
_LOGGER.debug(f"Dispatching {payload}")
else:
_LOGGER.info(f"Dispatching {payload}")

options = {
RequestType.ANNOUNCE: self.manage_announce,
RequestType.LOGIN: self.token,
Expand All @@ -220,6 +245,7 @@ def dispatch(self, payload):
}
options[req_type](payload)
except Exception as e:
_LOGGER.error(f"Error dispatching {payload}")
_LOGGER.error(e)

def manage_announce(self, payload):
Expand Down Expand Up @@ -293,6 +319,34 @@ def add_or_update_sensor(self, sensor, value):
self.sensors[name].update_state(value)
_LOGGER.debug("updated the sensor %s", name)

def update_climate(self, id, description, data):
try:
assert HubClasses.TEMPERATURE in id
_LOGGER.debug("update_climate: %s has data %s", description, data)
measured_temp = format(float(data[HubFields.TEMPERATURE]), '.1f')
measured_temp = float(measured_temp) / 10

target = format(float(data[HubFields.TARGET_TEMPERATURE]), '.1f')
target = float(target) / 10

measured_humidity = float(data[HubFields.HUMIDITY])

state = bool(int(data[HubFields.STATUS]))

climate = ComelitClimate(id, description, state, measured_temp, target, measured_humidity, CommandHub(self))

name = climate.entity_name
if climate.name not in self.climates: # Add the new sensor
if hasattr(self, 'climate_add_entities'):
self.climate_add_entities([climate])
self.climates[name] = climate
_LOGGER.info("added the climate %s", name)
else:
self.climates[name].update_state(state, measured_temp, measured_humidity)
_LOGGER.debug("updated the climate %s", name)
except Exception as e:
_LOGGER.exception("Error updating climate %s", e)

def update_light(self, id, description, data):
try:
_LOGGER.debug("update_light: %s has data %s", description, data)
Expand Down Expand Up @@ -384,6 +438,7 @@ def update_switch(self, id, description, data):
def update_entities(self, elements):
try:
for item in elements:
_LOGGER.debug("processing item %s", item)

id = item[HubFields.ID]

Expand All @@ -401,9 +456,13 @@ def update_entities(self, elements):
except Exception:
item = item

if HubClasses.POWER_CONSUMPTION in id or HubClasses.FTV in id or HubClasses.TEMPERATURE in id: # Sensor
if HubClasses.POWER_CONSUMPTION in id or HubClasses.FTV in id:
description = item[HubFields.DESCRIPTION]
self.update_sensor(id, description, item)
elif HubClasses.TEMPERATURE in id:
description = item[HubFields.DESCRIPTION]
self.update_sensor(id, description, item)
self.update_climate(id, description, item)
elif HubClasses.LIGHT in id:
description = item[HubFields.DESCRIPTION]
self.update_light(id, description, item)
Expand All @@ -422,13 +481,15 @@ def update_entities(self, elements):
else:
continue
except Exception as e:
_LOGGER.error("Update entities error")
_LOGGER.error(e)

def status(self, payload):
try:
elements = payload["out_data"][0][HubFields.ELEMENTS]
self.update_entities(elements)
except Exception as e:
_LOGGER.error("Status error")
_LOGGER.error(e)


Expand Down

0 comments on commit 7f9e2e2

Please sign in to comment.