Skip to content

Commit

Permalink
Merge pull request #33 from tonyroberts/dev
Browse files Browse the repository at this point in the history
Merge dev changes into main ready for 1.2.0 release
  • Loading branch information
tonyroberts authored Apr 15, 2024
2 parents f272f4c + af7fee0 commit 9e69366
Show file tree
Hide file tree
Showing 25 changed files with 679 additions and 190 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Tests

on:
push:
branches: [ "main" ]
branches: [ "main", "dev" ]
pull_request:
branches: [ "main" ]
branches: [ "main", "dev" ]

permissions:
contents: read
Expand Down
4 changes: 2 additions & 2 deletions custom_components/wundasmart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ async def _async_update_data(self):
while attempts < max_attempts:
attempts += 1

async with get_session() as session:
async with get_session(self._wunda_ip) as session:
result = await get_devices(
session,
self._wunda_ip,
Expand Down Expand Up @@ -132,7 +132,7 @@ async def _async_update_data(self):
# Get the hub switch serial number if we don't have it already
if self._device_sn is None and "device_sn" in device:
self._device_sn = device["device_sn"]
self._device_name = device.get("name", "Smart HubSwitch").replace("%20", " ")
self._device_name = device.get("name", "Smart HubSwitch")
self._sw_version = device.get("device_soft_version", "unknown")
self._hw_version = device.get("device_hard_version", "unknown")

Expand Down
50 changes: 32 additions & 18 deletions custom_components/wundasmart/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
CONF_HOST,
CONF_USERNAME,
CONF_PASSWORD,
TEMP_CELSIUS,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from . import WundasmartDataUpdateCoordinator
from .pywundasmart import send_command
from .pywundasmart import send_command, get_room_id_from_device
from .session import get_session
from .const import *

Expand Down Expand Up @@ -89,7 +89,7 @@ class Device(CoordinatorEntity[WundasmartDataUpdateCoordinator], ClimateEntity):
"""Representation of an Wundasmart climate."""

_attr_hvac_modes = SUPPORTED_HVAC_MODES
_attr_temperature_unit = TEMP_CELSIUS
_attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_preset_modes = SUPPORTED_PRESET_MODES
_attr_translation_key = DOMAIN

Expand All @@ -109,12 +109,19 @@ def __init__(
self._wunda_user = wunda_user
self._wunda_pass = wunda_pass
self._wunda_id = wunda_id
self._attr_name = device["name"].replace("%20", " ")
self._attr_name = device["name"]
self._attr_unique_id = device["id"]
self._attr_type = device["device_type"]
self._attr_device_info = coordinator.device_info
# This flag needs to be set until 2025.1 to prevent warnings about
# implicitly supporting the turn_off/turn_on methods.
# https://developers.home-assistant.io/blog/2024/01/24/climate-climateentityfeatures-expanded/
self._enable_turn_on_off_backwards_compatibility = False
self._attr_supported_features = (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_ON
| ClimateEntityFeature.TURN_OFF
)
self._attr_current_temperature = None
self._attr_target_temperature = None
Expand All @@ -140,12 +147,11 @@ def __sensor_state(self):

@property
def __trvs(self):
for trv in (self.coordinator.data.get(x, {}) for x in range(MIN_TRV_ID, MAX_TRV_ID+1)):
room_id = trv.get("state", {}).get("room_id", None)
if room_id is not None \
and (isinstance(room_id, int) or (isinstance(room_id, str) and room_id.isdigit())) \
and (int(room_id) + MIN_ROOM_ID) == self._wunda_id:
yield trv
for device in self.coordinator.data.values():
if device.get("device_type") == "TRV":
room_id = get_room_id_from_device(device)
if int(room_id) == int(self._wunda_id):
yield device

def __set_current_temperature(self):
"""Set the current temperature from the coordinator data."""
Expand Down Expand Up @@ -280,7 +286,7 @@ async def async_added_to_hass(self) -> None:

async def async_set_temperature(self, temperature, **kwargs):
# Set the new target temperature
async with get_session() as session:
async with get_session(self._wunda_ip) as session:
await send_command(
session,
self._wunda_ip,
Expand All @@ -301,7 +307,7 @@ async def async_set_temperature(self, temperature, **kwargs):
async def async_set_hvac_mode(self, hvac_mode: HVACMode):
if hvac_mode == HVACMode.AUTO:
# Set to programmed mode
async with get_session() as session:
async with get_session(self._wunda_ip) as session:
await send_command(
session,
self._wunda_ip,
Expand All @@ -316,8 +322,8 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode):
"time": 0
})
elif hvac_mode == HVACMode.HEAT:
# Set the target temperature to the current temperature + 1 degree, rounded up
async with get_session() as session:
# Set the target temperature to the t_hi preset temp
async with get_session(self._wunda_ip) as session:
await send_command(
session,
self._wunda_ip,
Expand All @@ -327,13 +333,13 @@ async def async_set_hvac_mode(self, hvac_mode: HVACMode):
params={
"cmd": 1,
"roomid": self._wunda_id,
"temp": math.ceil(self._attr_current_temperature) + 1,
"temp": float(self.__state["t_hi"]),
"locktt": 0,
"time": 0
})
elif hvac_mode == HVACMode.OFF:
# Set the target temperature to zero
async with get_session() as session:
async with get_session(self._wunda_ip) as session:
await send_command(
session,
self._wunda_ip,
Expand Down Expand Up @@ -361,7 +367,7 @@ async def async_set_preset_mode(self, preset_mode) -> None:

t_preset = float(self.__state[state_key])

async with get_session() as session:
async with get_session(self._wunda_ip) as session:
await send_command(
session,
self._wunda_ip,
Expand All @@ -379,3 +385,11 @@ async def async_set_preset_mode(self, preset_mode) -> None:

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

async def async_turn_on(self) -> None:
"""Turn the entity on."""
await self.async_set_hvac_mode(HVACMode.HEAT)

async def async_turn_off(self) -> None:
"""Turn the entity off."""
await self.async_set_hvac_mode(HVACMode.OFF)
2 changes: 1 addition & 1 deletion custom_components/wundasmart/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self, hass, wunda_ip, wunda_user, wunda_pass):

async def authenticate(self):
"""Wundasmart Hub class authenticate."""
async with get_session() as session:
async with get_session(self._wunda_ip) as session:
return await get_devices(
session,
self._wunda_ip,
Expand Down
45 changes: 37 additions & 8 deletions custom_components/wundasmart/const.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Constants for the wundasmart integration."""
from dataclasses import dataclass

DOMAIN = "wundasmart"

Expand All @@ -9,11 +10,39 @@
DEFAULT_CONNECT_TIMEOUT = 5
DEFAULT_READ_TIMEOUT = 5

MIN_SENSOR_ID = 1
MAX_SENSOR_ID = 30
MIN_TRV_ID = 31
MAX_TRV_ID = 90
MIN_UFH_ID = 91
MAX_UFH_ID = 94
MIN_ROOM_ID = 121
MAX_ROOM_ID = 150

@dataclass
class DeviceIdRanges:
MIN_SENSOR_ID: int
MAX_SENSOR_ID: int
MIN_TRV_ID: int
MAX_TRV_ID: int
MIN_UFH_ID: int
MAX_UFH_ID: int
MIN_ROOM_ID: int
MAX_ROOM_ID: int


DEVICE_ID_RANGES = {
# HW version
2: DeviceIdRanges(
MIN_SENSOR_ID=1,
MAX_SENSOR_ID=30,
MIN_TRV_ID=31, # TRV min/max is a guess, no data to confirm
MAX_TRV_ID=79,
MIN_UFH_ID=80,
MAX_UFH_ID=84,
MIN_ROOM_ID=100,
MAX_ROOM_ID=119
),
4: DeviceIdRanges(
MIN_SENSOR_ID=1,
MAX_SENSOR_ID=30,
MIN_TRV_ID=31,
MAX_TRV_ID=89,
MIN_UFH_ID=90,
MAX_UFH_ID=94,
MIN_ROOM_ID=121,
MAX_ROOM_ID=150
)
}
Loading

0 comments on commit 9e69366

Please sign in to comment.