Skip to content

Commit

Permalink
Add config options for update interval and timeouts
Browse files Browse the repository at this point in the history
Fixes #16
  • Loading branch information
tonyroberts committed Dec 4, 2023
1 parent 3b720de commit 1cfa945
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 54 deletions.
19 changes: 12 additions & 7 deletions custom_components/wundasmart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@

from datetime import timedelta
import asyncio
import aiohttp
import logging
from typing import Final

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, CONF_SCAN_INTERVAL, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.helpers.device_registry import DeviceInfo

from .const import DOMAIN
from .const import *
from .pywundasmart import get_devices

_LOGGER = logging.getLogger(__name__)
Expand All @@ -31,9 +32,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
wunda_ip = entry.data[CONF_HOST]
wunda_user = entry.data[CONF_USERNAME]
wunda_pass = entry.data[CONF_PASSWORD]
update_interval = timedelta(seconds=entry.data.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL))
connect_timeout = entry.data.get(CONF_CONNECT_TIMEOUT, DEFAULT_CONNECT_TIMEOUT)
read_timeout = entry.data.get(CONF_READ_TIMEOUT, DEFAULT_READ_TIMEOUT)
timeout = aiohttp.ClientTimeout(sock_connect=connect_timeout, sock_read=read_timeout)

coordinator = WundasmartDataUpdateCoordinator(
hass, wunda_ip, wunda_user, wunda_pass
hass, wunda_ip, wunda_user, wunda_pass, update_interval, timeout
)
await coordinator.async_config_entry_first_refresh()

Expand Down Expand Up @@ -69,7 +74,7 @@ async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> Non
class WundasmartDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching data from WundaSmart API."""

def __init__(self, hass, wunda_ip, wunda_user, wunda_pass):
def __init__(self, hass, wunda_ip, wunda_user, wunda_pass, update_interval, timeout):
"""Initialize."""
self._hass = hass
self._wunda_ip = wunda_ip
Expand All @@ -80,13 +85,13 @@ def __init__(self, hass, wunda_ip, wunda_user, wunda_pass):
self._device_name = None
self._sw_version = None
self._hw_version = None
self._timeout = timeout

update_interval = timedelta(minutes=1)
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=update_interval)

async def _async_update_data(self):
attempts = 0
max_attempts = 30
max_attempts = 5
session = aiohttp_client.async_get_clientsession(self._hass)
while attempts < max_attempts:
attempts += 1
Expand All @@ -96,7 +101,7 @@ async def _async_update_data(self):
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=1
timeout=self._timeout
)

if result["state"]:
Expand Down
92 changes: 63 additions & 29 deletions custom_components/wundasmart/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import math
import logging
import aiohttp
from typing import Any

from homeassistant.components.climate import (
Expand All @@ -29,7 +30,7 @@

from . import WundasmartDataUpdateCoordinator
from .pywundasmart import send_command
from .const import DOMAIN, MIN_ROOM_ID, MIN_TRV_ID, MAX_TRV_ID
from .const import *

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -65,6 +66,11 @@ async def async_setup_entry(
wunda_pass: str = entry.data[CONF_PASSWORD]
coordinator: WundasmartDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
session = aiohttp_client.async_get_clientsession(hass)

connect_timeout = entry.data.get(CONF_CONNECT_TIMEOUT, DEFAULT_CONNECT_TIMEOUT)
read_timeout = entry.data.get(CONF_READ_TIMEOUT, DEFAULT_READ_TIMEOUT)
timeout = aiohttp.ClientTimeout(sock_connect=connect_timeout, sock_read=read_timeout)

rooms = (
(wunda_id, device) for wunda_id, device
in coordinator.data.items()
Expand All @@ -78,6 +84,7 @@ async def async_setup_entry(
wunda_id,
device,
coordinator,
timeout
)
for wunda_id, device in rooms))

Expand All @@ -99,6 +106,7 @@ def __init__(
wunda_id: str,
device: dict[str, Any],
coordinator: WundasmartDataUpdateCoordinator,
timeout: aiohttp.ClientTimeout
) -> None:
"""Initialize the Wundasmart climate."""
super().__init__(coordinator)
Expand All @@ -119,6 +127,7 @@ def __init__(
self._attr_current_humidity = None
self._attr_hvac_mode = HVACMode.AUTO
self._attr_preset_mode = None
self._timeout = timeout

# Update with initial state
self.__update_state()
Expand Down Expand Up @@ -277,45 +286,69 @@ async def async_added_to_hass(self) -> None:

async def async_set_temperature(self, temperature, **kwargs):
# Set the new target temperature
await send_command(self._session, self._wunda_ip, self._wunda_user, self._wunda_pass, params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": temperature,
"locktt": 0,
"time": 0
})
await send_command(
self._session,
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=self._timeout,
params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": temperature,
"locktt": 0,
"time": 0
})

# Fetch the updated state
await self.coordinator.async_request_refresh()

async def async_set_hvac_mode(self, hvac_mode: HVACMode):
if hvac_mode == HVACMode.AUTO:
# Set to programmed mode
await send_command(self._session, self._wunda_ip, self._wunda_user, self._wunda_pass, params={
"cmd": 1,
"roomid": self._wunda_id,
"prog": None,
"locktt": 0,
"time": 0
})
await send_command(
self._session,
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=self._timeout,
params={
"cmd": 1,
"roomid": self._wunda_id,
"prog": None,
"locktt": 0,
"time": 0
})
elif hvac_mode == HVACMode.HEAT:
# Set the target temperature to the current temperature + 1 degree, rounded up
await send_command(self._session, self._wunda_ip, self._wunda_user, self._wunda_pass, params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": math.ceil(self._attr_current_temperature) + 1,
"locktt": 0,
"time": 0
})
await send_command(
self._session,
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=self._timeout,
params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": math.ceil(self._attr_current_temperature) + 1,
"locktt": 0,
"time": 0
})
elif hvac_mode == HVACMode.OFF:
# Set the target temperature to zero
await send_command(self._session, self._wunda_ip, self._wunda_user, self._wunda_pass, params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": 0.0,
"locktt": 0,
"time": 0
})
await send_command(
self._session,
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=self._timeout,
params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": 0.0,
"locktt": 0,
"time": 0
})
else:
raise NotImplementedError(f"Unsupported HVAC mode {hvac_mode}")

Expand All @@ -335,6 +368,7 @@ async def async_set_preset_mode(self, preset_mode) -> None:
self._wunda_ip,
self._wunda_user,
self._wunda_pass,
timeout=self._timeout,
params={
"cmd": 1,
"roomid": self._wunda_id,
Expand Down
33 changes: 31 additions & 2 deletions custom_components/wundasmart/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
"""Config flow to configure Wundasmart."""
import voluptuous as vol
from typing import Any

from homeassistant import config_entries, core, exceptions
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD, CONF_SCAN_INTERVAL
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import aiohttp_client
from homeassistant.core import callback

from .const import DOMAIN
from .const import *
from .pywundasmart import get_devices

STEP_USER_DATA_SCHEMA = vol.Schema(
Expand All @@ -16,6 +19,14 @@
}
)

STEP_INIT_DATA_SCHEMA = vol.Schema(
{
vol.Optional(CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL): int,
vol.Optional(CONF_CONNECT_TIMEOUT, default=DEFAULT_CONNECT_TIMEOUT): int,
vol.Optional(CONF_READ_TIMEOUT, default=DEFAULT_READ_TIMEOUT): int
}
)


class Hub:
"""Wundasmart Hub class."""
Expand Down Expand Up @@ -53,6 +64,12 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):

VERSION = 1

@staticmethod
@callback
def async_get_options_flow(config_entry: config_entries.ConfigEntry) -> config_entries.OptionsFlow:
"""Get the options flow for this handler."""
return OptionsFlow(config_entry)

async def async_step_user(self, user_input=None):
"""Show the setup form to the user."""
if user_input is None:
Expand Down Expand Up @@ -81,6 +98,18 @@ async def async_step_user(self, user_input=None):
)


class OptionsFlow(config_entries.OptionsFlow):

def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
self.config_entry = config_entry

async def async_step_init(self, user_input: dict[str, Any] | None = None) -> FlowResult:
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

return self.async_show_form(step_id="init", data_schema=STEP_INIT_DATA_SCHEMA)


class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""

Expand Down
7 changes: 7 additions & 0 deletions custom_components/wundasmart/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

DOMAIN = "wundasmart"

CONF_CONNECT_TIMEOUT = "connect_timeout"
CONF_READ_TIMEOUT = "read_timeout"

DEFAULT_SCAN_INTERVAL = 300
DEFAULT_CONNECT_TIMEOUT = 5
DEFAULT_READ_TIMEOUT = 5

MIN_SENSOR_ID = 1
MAX_SENSOR_ID = 30
MIN_TRV_ID = 31
Expand Down
12 changes: 12 additions & 0 deletions custom_components/wundasmart/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
}
},
"options": {
"step": {
"init": {
"data": {
"scan_interval": "[%key:common::config_flow::data::scan_interval%]",
"connect_timeout": "Connect Timeout",
"read_timeout": "Read Timeout"
},
"title": "Wundasmart options"
}
}
},
"entity": {
"climate": {
"wundasmart": {
Expand Down
12 changes: 12 additions & 0 deletions custom_components/wundasmart/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@
}
}
},
"options": {
"step": {
"init": {
"data": {
"scan_interval": "Poll Interval",
"connect_timeout": "Connect Timeout",
"read_timeout": "Read Timeout"
},
"title": "Wundasmart options"
}
}
},
"entity": {
"climate": {
"wundasmart": {
Expand Down
Loading

0 comments on commit 1cfa945

Please sign in to comment.