74 lines
2.3 KiB
Python
74 lines
2.3 KiB
Python
import numpy as np
|
|
import time
|
|
|
|
from utils import send_update
|
|
|
|
from humidifier import Humidifier, HumidifierV2
|
|
from humidifier_v3 import HumidifierV3
|
|
|
|
class Controller:
|
|
def __init__(self, humidifiers):
|
|
self.target_lower = 83
|
|
self.target_upper = 87
|
|
self.feedforward_coeff = 50
|
|
self.last_toggle = 0
|
|
|
|
self._manual_mode = False
|
|
self.manual_on = False
|
|
self.manual_timeout = 0
|
|
self.manual_duration = 40
|
|
|
|
self.humidifier_history = np.zeros(50)
|
|
self.first_sample = False
|
|
self.humidifiers = humidifiers
|
|
|
|
@property
|
|
def manual_mode(self):
|
|
return self._manual_mode
|
|
|
|
@manual_mode.setter
|
|
def manual_mode(self, on):
|
|
self._manual_mode = on
|
|
send_update({"status": {"manual_mode": on}})
|
|
|
|
def set_checked(self, s, humidifier, on):
|
|
if time.time() - self.last_toggle > 0.8:
|
|
print("setting {} to {}".format(humidifier, on))
|
|
if isinstance(humidifier, HumidifierV3):
|
|
humidifier.set(s, on)
|
|
elif isinstance(humidifier, Humidifier) or isinstance(humidifier, HumidifierV2):
|
|
humidifier.toggle(s)
|
|
self.last_toggle = time.time()
|
|
|
|
def update(self, s, humidity):
|
|
if self.first_sample:
|
|
self.humidifier_history[:] = humidity
|
|
self.first_sample = False
|
|
else:
|
|
self.humidifier_history[:-1] = self.humidifier_history[1:]
|
|
self.humidifier_history[-1] = humidity
|
|
|
|
# compensate for the slow response time by adding a little feed forward
|
|
# using the slope of the humidifier data
|
|
slope = (self.humidifier_history[-1] - self.humidifier_history[0])/self.humidifier_history.shape[0]
|
|
comp_humidity = humidity + self.feedforward_coeff*slope
|
|
|
|
if self.manual_mode and time.time() > self.manual_timeout:
|
|
self.manual_mode = False
|
|
|
|
if self.manual_mode:
|
|
for humidifier in self.humidifiers:
|
|
if not humidifier.on and self.manual_on:
|
|
self.set_checked(s, humidifier, True)
|
|
elif not humidifier.off and not self.manual_on:
|
|
self.set_checked(s, humidifier, False)
|
|
else:
|
|
if comp_humidity < self.target_lower:
|
|
for humidifier in self.humidifiers:
|
|
if not humidifier.on:
|
|
self.set_checked(s, humidifier, True)
|
|
elif comp_humidity > self.target_upper:
|
|
for humidifier in self.humidifiers:
|
|
if not humidifier.off:
|
|
self.set_checked(s, humidifier, False)
|