Files
brewpi/brewpi.py
T
2020-11-29 10:59:33 +01:00

198 lines
5.1 KiB
Python

import asyncio
from time import sleep
import abc
from ws.server.ws_server_multi_user import WsServerMultiUser
from components.sensor.tempSensorSim import TempSensorSim, ATemperatureSensor
from components.plant.pot import Pot, APlant
from components.actor.heater import Heater, AHeater
from components.pid import kalman
from ws.message import MsgIo, MessageDispatcher
from utils.value import Value, ValueChanged
class ATask:
def __init__(self, interval):
self.interval = interval
@abc.abstractmethod
def on_process(self):
pass
class TempSensorTask(ATask):
def __init__(self, sensor: ATemperatureSensor, interval, msg_handler: MsgIo, kalman: kalman.Kalman):
ATask.__init__(self, interval)
self.msg_handler = msg_handler
msg_handler.set_recv_handler(self.recv)
self.sensor = sensor
self.kalman = kalman
def on_temp_changed(self, value):
print("Sensor temp {}".format(value))
def on_temp_changed_kalman(self, value):
print("Kalman temp {}".format(value))
asyncio.create_task(self.send({'Temp': value}))
async def recv(self, data):
print(data)
async def send(self, data):
await self.msg_handler.send(data)
async def on_process(self):
print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval))
self.kalman.initial((self.sensor.temperature(), 0))
temp = ValueChanged(self.on_temp_changed, prec=1)
temp_kalman = ValueChanged(self.on_temp_changed_kalman, prec=1)
self.sensor.set_on_changed("temp", temp)
while True:
self.sensor.process()
Z = self.kalman.process_measurement((self.sensor.temperature(), 0), 0)
xp = self.kalman.process(Z)
theta_ist = xp[0, 0]
heatrate_ist = xp[1, 0] * 60
temp_kalman.set(theta_ist)
await asyncio.sleep(self.interval)
class HeaterTask(ATask):
def __init__(self, heater: AHeater, interval, msg_handler: MsgIo):
ATask.__init__(self, interval)
self.msg_handler = msg_handler
msg_handler.set_recv_handler(self.recv)
self.heater = heater
async def recv(self, data):
print(data)
for pair in data.items():
if 'Power' in pair[0]:
self.heater.setPower(pair[1])
if 'Activate' in pair[0]:
self.heater.activate(bool(pair[1]))
async def send(self, data):
await self.msg_handler.send(data)
async def on_process(self):
print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval))
await self.send({'Capabilities': {'Power': {'Min': self.heater.get_power_min(), 'Max': self.heater.get_power_max()}}})
power = Value()
while True:
self.heater.process()
power.set(round(self.heater.getPower()))
if power.is_changed():
await self.send({'Power': power.get(), 'Activate': int(self.heater.getPower() != 0)})
await asyncio.sleep(self.interval)
class PotTask(ATask):
def __init__(self, pot: APlant, interval, msg_handler: MsgIo):
ATask.__init__(self, interval)
self.msg_handler = msg_handler
msg_handler.set_recv_handler(self.recv)
self.plant = pot
async def recv(self, data):
print(data)
for key in data:
print(key)
async def send(self, data):
await self.msg_handler.send(data)
async def on_process(self):
print("{}: Started with interval {} s".format(self.msg_handler.get_key(), self.interval))
plant_temp = Value(-1)
plant_power = Value()
while True:
self.plant.process()
plant_power.set(round(self.plant.getPower()))
plant_temp.set(round(self.plant.getTemperature(), 1))
if plant_power.is_changed():
print("Plant Power {}".format(plant_power.get()))
await self.send({'Power': plant_power.get()})
if plant_temp.is_changed():
print("Plant Temp {}".format(plant_temp.get()))
await self.send({'Temp': plant_temp.get()})
await asyncio.sleep(self.interval)
class TaskManager:
def __init__(self):
self.tasks = []
def add(self, task: ATask):
self.tasks.append(task)
def start(self):
funcs = []
for task in self.tasks:
funcs.append(task.on_process())
return asyncio.gather(*funcs)
async def asleep(time):
await asyncio.sleep(time)
if __name__ == '__main__':
if 0:
taskmgr = PeriodicUpdaterThreaded()
taskmgr.start("localhost", 8765)
bg_thread = Thread(target=taskmgr.loop.run_forever)
bg_thread.setDaemon(True)
bg_thread.start()
else:
dispatcher = MessageDispatcher()
server = WsServerMultiUser(listener=dispatcher)
taskmgr = TaskManager()
# Kalman Filter
kalman_params = {
"dt" : 1.0,
"var_P" : 0.1,
"var_Q" : 0.001,
"var_R" : 0.1
}
kalman = kalman.Kalman(kalman_params)
# Sensor
sensor = TempSensorSim()
taskmgr.add(TempSensorTask(sensor, 0.2, dispatcher.msgio_get("Sensor"), kalman))
# Plant
pot_params = {
"dt" : 1.0,
"theta_amb" : 15,
"C" : 4190,
"M" : 20,
"L" : 0.1,
"Td" : 12,
"kn" : 0.2
}
pot = Pot(pot_params)
pot.connect_theta_changed(sensor.set_fake_temp)
taskmgr.add(PotTask(pot, 0.1, dispatcher.msgio_get("Pot")))
# Heater
heater = Heater()
heater.connect_power_changed(pot.setPower)
taskmgr.add(HeaterTask(heater, 0.02, dispatcher.msgio_get("Heater")))
h_dispatcher = taskmgr.start()
h_server = server.listen("localhost", 8765)
asyncio.gather(h_dispatcher, h_server)
server.run_forever()
while True:
print("Hallo")
sleep(1)