2021-01-02 22:42:56 +00:00
|
|
|
# SPDX-FileCopyrightText: 2020-2021 Andrius Štikonas <andrius@stikonas.eu>
|
2020-11-22 00:59:22 +00:00
|
|
|
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
|
|
|
2021-01-19 21:51:48 +00:00
|
|
|
import logging
|
2020-12-20 22:58:04 +00:00
|
|
|
from datetime import datetime, timedelta
|
2020-12-06 22:53:50 +00:00
|
|
|
from types import SimpleNamespace
|
2020-11-22 00:59:22 +00:00
|
|
|
|
2020-12-27 20:30:12 +00:00
|
|
|
from async_property import async_property
|
|
|
|
|
2020-12-27 18:58:30 +00:00
|
|
|
from neohubapi.enums import Weekday
|
2020-12-20 22:58:04 +00:00
|
|
|
|
2020-12-06 22:53:50 +00:00
|
|
|
|
|
|
|
class NeoStat(SimpleNamespace):
|
2020-11-22 00:59:22 +00:00
|
|
|
"""
|
|
|
|
Class representing NeoStat theormostat
|
|
|
|
"""
|
|
|
|
|
2020-12-06 22:53:50 +00:00
|
|
|
def __init__(self, hub, thermostat):
|
2021-01-19 21:51:48 +00:00
|
|
|
self._logger = logging.getLogger('neohub')
|
2020-12-06 22:53:50 +00:00
|
|
|
self._data_ = thermostat
|
2020-11-22 10:23:27 +00:00
|
|
|
self._hub = hub
|
2020-11-22 00:59:22 +00:00
|
|
|
|
2021-01-19 21:51:48 +00:00
|
|
|
self._simple_attrs = (
|
|
|
|
'active_level',
|
|
|
|
'active_profile',
|
|
|
|
'available_modes',
|
|
|
|
'away',
|
|
|
|
'cool_on',
|
|
|
|
'cool_temp',
|
|
|
|
'current_floor_temperature',
|
|
|
|
'date',
|
|
|
|
'device_id',
|
|
|
|
'fan_control',
|
|
|
|
'fan_speed',
|
|
|
|
'floor_limit',
|
|
|
|
'hc_mode',
|
|
|
|
'heat_mode',
|
|
|
|
'heat_on',
|
|
|
|
'hold_cool',
|
|
|
|
'fan_control',
|
|
|
|
'fan_speed',
|
|
|
|
'hc_mode',
|
|
|
|
'heat_mode',
|
|
|
|
'heat_on',
|
|
|
|
'hold_cool',
|
|
|
|
'hold_off',
|
|
|
|
'hold_on',
|
|
|
|
'hold_temp',
|
|
|
|
'hold_time', # This is updated below.
|
|
|
|
'holiday',
|
|
|
|
'lock',
|
|
|
|
'low_battery',
|
|
|
|
'manual_off',
|
|
|
|
'modelock',
|
|
|
|
'modulation_level',
|
|
|
|
'offline',
|
|
|
|
'pin_number',
|
|
|
|
'preheat_active',
|
|
|
|
'prg_temp',
|
|
|
|
'prg_timer',
|
|
|
|
'standby',
|
|
|
|
'switch_delay_left', # This is updated below.
|
|
|
|
'temporary_set_flag',
|
|
|
|
'time', # This is updated below.
|
|
|
|
'timer_on',
|
|
|
|
'window_open',
|
|
|
|
'write_count'
|
|
|
|
)
|
|
|
|
|
|
|
|
for a in self._simple_attrs:
|
|
|
|
data_attr = a.upper()
|
|
|
|
if not hasattr(self._data_, data_attr):
|
|
|
|
self._logger.debug(f"Thermostat object has no attribute {data_attr}")
|
|
|
|
self.__dict__[a] = getattr(self._data_, data_attr, None)
|
|
|
|
|
|
|
|
# Renamed attrs
|
|
|
|
self.name = getattr(self._data_, 'ZONE_NAME', None)
|
|
|
|
self.floor_limit = getattr(self._data_, 'ZONE_NAME', None)
|
|
|
|
self.target_temperature = getattr(self._data_, 'SET_TEMP', None)
|
|
|
|
self.temperature = getattr(self._data_, 'ACTUAL_TEMP', None)
|
|
|
|
|
|
|
|
# must be ints
|
|
|
|
self.pin_number = int(self.pin_number)
|
|
|
|
self.preheat_active = int(self.preheat_active)
|
|
|
|
|
|
|
|
# HOLD_TIME can be up to 99:99
|
|
|
|
_hold_time = list(map(int, self.hold_time.split(':')))
|
2021-01-02 17:14:10 +00:00
|
|
|
_hold_time_minutes = _hold_time[0] * 60 + _hold_time[1]
|
|
|
|
self.hold_time = timedelta(minutes=_hold_time_minutes)
|
2021-01-19 21:51:48 +00:00
|
|
|
|
|
|
|
self.weekday = Weekday(self.date)
|
|
|
|
|
|
|
|
_switch_delay_left = datetime.strptime(self.switch_delay_left, "%H:%M")
|
|
|
|
self.switch_delay_left = timedelta(
|
|
|
|
hours=_switch_delay_left.hour,
|
|
|
|
minutes=_switch_delay_left.minute)
|
|
|
|
_time = datetime.strptime(self.time, "%H:%M")
|
2020-12-20 22:58:04 +00:00
|
|
|
self.time = timedelta(hours=_time.hour, minutes=_time.minute)
|
2020-11-22 10:23:27 +00:00
|
|
|
|
|
|
|
async def identify(self):
|
|
|
|
"""
|
|
|
|
Flashes red LED light
|
|
|
|
"""
|
|
|
|
|
2020-12-06 22:53:50 +00:00
|
|
|
message = {"IDENTIFY_DEV": self.name}
|
2020-11-22 10:23:27 +00:00
|
|
|
reply = {"result": "Device identifying"}
|
|
|
|
|
|
|
|
result = await self._hub._send(message, reply)
|
|
|
|
return result
|
2020-11-22 10:52:33 +00:00
|
|
|
|
|
|
|
async def rename(self, new_name):
|
|
|
|
"""
|
|
|
|
Renames this zone
|
|
|
|
"""
|
|
|
|
|
|
|
|
message = {"ZONE_TITLE": [self.name, new_name]}
|
2020-12-07 00:54:29 +00:00
|
|
|
reply = {"result": "zone renamed"}
|
2020-11-22 10:52:33 +00:00
|
|
|
|
|
|
|
result = await self._hub._send(message, reply)
|
|
|
|
return result
|
2020-11-22 11:13:24 +00:00
|
|
|
|
|
|
|
async def remove(self):
|
|
|
|
"""
|
|
|
|
Removes this zone
|
|
|
|
|
|
|
|
If successful, thermostat will be disconnected from the hub
|
|
|
|
Note that it takes a few seconds to remove thermostat
|
|
|
|
New get_zones call will still return the original list
|
|
|
|
during that period.
|
|
|
|
"""
|
|
|
|
|
|
|
|
message = {"REMOVE_ZONE": self.name}
|
|
|
|
reply = {"result": "zone removed"}
|
|
|
|
|
|
|
|
result = await self._hub._send(message, reply)
|
|
|
|
return result
|
2020-11-22 11:55:41 +00:00
|
|
|
|
2020-12-20 22:58:04 +00:00
|
|
|
async def set_lock(self, pin: int):
|
|
|
|
result = await self._hub.set_lock(pin, [self])
|
2020-11-22 11:55:41 +00:00
|
|
|
return result
|
|
|
|
|
|
|
|
async def unlock(self):
|
|
|
|
result = await self._hub.unlock([self])
|
|
|
|
return result
|
2020-11-22 12:22:14 +00:00
|
|
|
|
2020-12-20 22:58:04 +00:00
|
|
|
async def set_frost(self, state: bool):
|
2021-01-03 13:39:19 +00:00
|
|
|
result = await self._hub.set_frost(state, [self])
|
2020-11-22 12:22:14 +00:00
|
|
|
return result
|
2020-11-22 12:30:59 +00:00
|
|
|
|
2020-12-30 12:42:01 +00:00
|
|
|
async def set_target_temperature(self, temperature: int):
|
2021-01-03 13:42:52 +00:00
|
|
|
result = await self._hub.set_target_temperature(temperature, [self])
|
2020-11-22 12:30:59 +00:00
|
|
|
return result
|
2020-11-22 15:36:18 +00:00
|
|
|
|
|
|
|
async def set_diff(self, switching_differential: int):
|
|
|
|
result = await self._hub.set_diff(switching_differential, [self])
|
|
|
|
return result
|
2020-12-07 00:43:54 +00:00
|
|
|
|
2020-12-27 20:30:12 +00:00
|
|
|
@async_property
|
2020-12-07 00:43:54 +00:00
|
|
|
async def rate_of_change(self):
|
|
|
|
result = await self._hub.rate_of_change([self])
|
2020-12-27 20:30:12 +00:00
|
|
|
roc = result[self.name]
|
|
|
|
return roc
|
2021-01-03 13:46:03 +00:00
|
|
|
|
|
|
|
async def set_timer_hold(self, state: bool, minutes: int):
|
|
|
|
"""
|
|
|
|
Turns the output of timeclock on or off for certain duration
|
|
|
|
|
|
|
|
Works only with NeoStats in timeclock mode
|
|
|
|
"""
|
|
|
|
result = await self._hub.set_timer_hold(state, minutes, [self])
|
|
|
|
return result
|