Skip to content

Commit

Permalink
Improved responsiveness
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbe-B committed Jan 12, 2024
1 parent 0cf14c3 commit 2d29dab
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 22 deletions.
15 changes: 14 additions & 1 deletion custom_components/maestro_mcz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import timedelta
import logging
import os
import asyncio
import async_timeout
from .config_flow import CONF_POLLING_INTERVAL
from .maestro.responses.model import Configuration, ModelConfiguration, SensorConfiguration, SensorConfigurationMultipleModes
Expand Down Expand Up @@ -91,6 +92,8 @@ def has_mocked_files() -> list[str] | None:
class MczCoordinator(DataUpdateCoordinator):
"""MCZ Coordinator."""

_avoid_ping: bool = False

def __init__(self, hass, maestroapi, polling_interval):
"""Initialize my coordinator."""
super().__init__(
Expand All @@ -104,8 +107,18 @@ def __init__(self, hass, maestroapi, polling_interval):
async def _async_update_data(self):
"""Fetch data from API endpoint."""
async with async_timeout.timeout(15):
await self._maestroapi.Refresh()
await self._maestroapi.Refresh(not self._avoid_ping)
return True

async def update_date_after_set(self):
"""force refresh of data from API endpoint after a SET was executed."""
#we need to wait here because there is an actual delay between sending a SET and receiving the updated value from the polled MCZ database
await asyncio.sleep(3)
await self.async_refresh()
await asyncio.sleep(3)
self._avoid_ping = True
await self.async_refresh()
self._avoid_ping = False

@property
def maestroapi(self) -> MaestroStove:
Expand Down
4 changes: 2 additions & 2 deletions custom_components/maestro_mcz/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ async def async_press(self) -> None:
if(self._button_configuration is not None and self._attr_return_value is not None):
if(self._button_configuration.configuration.type == TypeEnum.BOOLEAN.value):
await self.coordinator._maestroapi.ActivateProgram(self._button_configuration.configuration.sensor_id, self._button_configuration.configuration_id, bool(self._attr_return_value))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()
elif(self._button_configuration.configuration.type == TypeEnum.INT.value):
await self.coordinator._maestroapi.ActivateProgram(self._button_configuration.configuration.sensor_id, self._button_configuration.configuration_id, int(self._attr_return_value))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

@property
def entity_registry_enabled_default(self) -> bool:
Expand Down
8 changes: 4 additions & 4 deletions custom_components/maestro_mcz/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,24 +138,24 @@ async def async_set_preset_mode(self, preset_mode):
if (self._attr_preset_modes_mappings is not None and preset_mode in self._attr_preset_modes_mappings.keys()):
converted_preset_mode = self._attr_preset_modes_mappings[preset_mode]
await self.coordinator._maestroapi.ActivateProgram(self._climate_function_mode_configuration.configuration.sensor_id, self._climate_function_mode_configuration.configuration_id, converted_preset_mode)
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

async def async_set_hvac_mode(self, hvac_mode):
if(self._power_configuration is not None):
if(self._power_configuration.configuration.type == TypeEnum.BOOLEAN.value):
if(self.hvac_mode is not None and self.hvac_mode is not hvac_mode): #avoid sending the same hvac mode to the API because this will result in a toggle of the power setting of the stove
await self.coordinator._maestroapi.ActivateProgram(self._power_configuration.configuration.sensor_id, self._power_configuration.configuration_id, True)
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()
elif(self._power_configuration.configuration.type == TypeEnum.INT.value):
if(self.hvac_mode is not None and self.hvac_mode is not hvac_mode): #avoid sending the same hvac mode to the API because this will result in a toggle of the power setting of the stove
if (self._attr_hvac_modes_mappings and hvac_mode in self._attr_hvac_modes_mappings.keys()):
await self.coordinator._maestroapi.ActivateProgram(self._power_configuration.configuration.sensor_id, self._power_configuration.configuration_id, int(self._attr_hvac_modes_mappings[hvac_mode]))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

async def async_set_temperature(self, **kwargs):
if(self._thermostat_configuration is not None):
await self.coordinator._maestroapi.ActivateProgram(self._thermostat_configuration.configuration.sensor_id, self._thermostat_configuration.configuration_id, float(kwargs["temperature"]))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

@callback
def _handle_coordinator_update(self) -> None:
Expand Down
6 changes: 3 additions & 3 deletions custom_components/maestro_mcz/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,19 @@ async def async_set_preset_mode(self, preset_mode: str) -> None:
"""Set the preset mode of the fan."""
if(self._current_fan_configuration is not None):
await self.coordinator._maestroapi.ActivateProgram(self._current_fan_configuration.configuration.sensor_id, self._current_fan_configuration.configuration_id, int(preset_mode))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

async def async_turn_on(self) -> None:
"""Turn on the fan."""
if(self._current_fan_configuration is not None and self._presets is not None and len(self._presets) > 0):
await self.coordinator._maestroapi.ActivateProgram(self._current_fan_configuration.configuration.sensor_id, self._current_fan_configuration.configuration_id, int(self._presets[-1]))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

async def async_turn_off(self) -> None:
"""Turn off the fan."""
if(self._current_fan_configuration is not None and self._presets is not None and len(self._presets) > 0):
await self.coordinator._maestroapi.ActivateProgram(self._current_fan_configuration.configuration.sensor_id, self._current_fan_configuration.configuration_id, int(self._presets[0]))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

def get_configuration_for_current_stove_mode(self) -> SensorConfiguration | None:
"""Get the correct sensor configuration for the current mode that the stove is in"""
Expand Down
13 changes: 7 additions & 6 deletions custom_components/maestro_mcz/maestro/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import asyncio

from .controller.controller_interface import MaestroControllerInterface

Expand Down Expand Up @@ -83,10 +82,10 @@ async def StoveState(self) -> State:
)
)

async def Refresh(self):
async def Refresh(self, include_ping: bool = True):
if(not self._usemockeddata): #make sure not to execute this code with a mocked controller
await self.Ping()
await asyncio.sleep(3.5) #we need to wait here because there is an actual delay between sending a SET and receiving the updated value from the polled MCZ database
if(include_ping):
await self.Ping()
self._state = await self.StoveState()
self._status = await self.StoveStatus()

Expand All @@ -96,8 +95,10 @@ async def SetMockedData(self, model: Model, state: State, status: Status): # for
self._status = status
self._usemockeddata = True

async def ActivateProgram(self, sensor_id: str, configuration_id: str, value: object):
async def ActivateProgram(self, sensor_id: str, configuration_id: str, value: object, callback_on_success = None):
url = f"https://s.maestro.mcz.it/mcz/v1.0/Program/ActivateProgram/{self.Id}"
command = [{"SensorId": sensor_id, "Value": value}]
body = RequestBuilder(self, ConfigurationId=configuration_id, Commands=command)
await self._controller.MakeRequest("POST", url=url, body=body, recursive_try_on_error = False)
success = await self._controller.MakeRequest("POST", url=url, body=body, recursive_try_on_error = False)
if(callback_on_success is not None and success is not None):
callback_on_success()
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def Connected(self) -> bool:
def Stoves(self):
pass

async def MakeRequest(self, method:str, url:str, headers={}, body=None, recursive_try_on_error:bool = True, is_first_try:bool = True):
async def MakeRequest(self, method:str, url:str, headers={}, body=None, recursive_try_on_error:bool = True, is_first_try:bool = True, callback=None):
pass

async def Login(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ async def MakeRequest(self, method:str, url:str, headers={}, body=None, recursiv
return await self.MakeRequest(
method=method, url=url, headers=headers, body=body, recursive_try_on_error=recursive_try_on_error, is_first_try = False
)
else:
return None
except Exception as err:
print(f"Error making request. Attempting to relogin. Error: {err}")

Expand All @@ -65,6 +67,7 @@ async def MakeRequest(self, method:str, url:str, headers={}, body=None, recursiv
return await self.MakeRequest(
method=method, url=url, headers=headers, body=body, recursive_try_on_error=recursive_try_on_error, is_first_try = False
)
return None

async def Login(self):
LOGIN_BODY = {"username": self.Username, "password": self.Password}
Expand Down
2 changes: 1 addition & 1 deletion custom_components/maestro_mcz/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async def async_set_native_value(self, value: float) -> None:
converted_value = value

await self.coordinator._maestroapi.ActivateProgram(self._number_configuration.configuration.sensor_id, self._number_configuration.configuration_id, converted_value)
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

@callback
def _handle_coordinator_update(self) -> None:
Expand Down
2 changes: 1 addition & 1 deletion custom_components/maestro_mcz/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async def async_select_option(self, option: str) -> None:

if(found_value is not None):
await self.coordinator._maestroapi.ActivateProgram(self._selector_configuration.configuration.sensor_id, self._selector_configuration.configuration_id, int(found_value))
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

@property
def entity_registry_enabled_default(self) -> bool:
Expand Down
6 changes: 3 additions & 3 deletions custom_components/maestro_mcz/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,13 @@ async def async_turn_on(self, **kwargs):
"""Set the switch on."""
if(self._switch_configuration is not None):
await self.coordinator._maestroapi.ActivateProgram(self._switch_configuration.configuration.sensor_id, self._switch_configuration.configuration_id, True)
await self.coordinator.async_refresh()

await self.coordinator.update_date_after_set()
async def async_turn_off(self, **kwargs):
"""Set the switch off."""
if(self._switch_configuration is not None):
await self.coordinator._maestroapi.ActivateProgram(self._switch_configuration.configuration.sensor_id, self._switch_configuration.configuration_id, False)
await self.coordinator.async_refresh()
await self.coordinator.update_date_after_set()

@property
def entity_registry_enabled_default(self) -> bool:
Expand Down

0 comments on commit 2d29dab

Please sign in to comment.