kiln_controller/kiln/manager.py

87 wiersze
2.1 KiB
Python
Czysty Zwykły widok Historia

import stepper
import time
import random
import thermo
import warnings
import threading
import traceback
import logging
import states
logger = logging.getLogger("kiln.manager")
2014-10-15 18:10:54 +00:00
class Manager(threading.Thread):
def __init__(self, start=states.Idle):
"""
Implement a state machine that cycles through States
"""
super(Manager, self).__init__()
self._send = None
self.thermocouple = thermo.Monitor(self._send_state)
self.regulator = stepper.Regulator()
self.profile = None
self.state = start(self)
self.state_change = threading.Event()
self.running = True
self.start()
def register(self, webapp):
self._send = webapp.send
def notify(self, data):
if self._send is not None:
self._send(data)
else:
logging.warn("No notifier set, ignoring message: %s"%data)
def _send_state(self, time, temp):
profile = None
if self.profile is not None:
profile.get_state()
state = dict(
output=self.regulator.output,
profile=profile,
time=time,
temp=temp,
)
if self._send is not None:
self._send(state)
def __getattr__(self, name):
"""Mutates the manager to return State actions
If the requested attribute is a function, wrap the function
such that returned objects which are States indicate a state change
"""
attr = getattr(self.state, name)
if hasattr(attr, "__call__"):
def func(*args, **kwargs):
self._change_state(attr(*args, **kwargs))
return func
return attr
def _change_state(self, output):
if isinstance(output, states.State) :
self.state = output()
self.state_change.set()
self.notify(dict(type="change", state=newstate.__name__))
elif isinstance(output, tuple) and isinstance(output[0], states.State):
newstate, kwargs = output
self.state = output(**kwargs)
self.notify(dict(type="change", state=newstate.__name__))
elif isinstance(output, dict) and "type" in dict:
self.notify(output)
elif output is not None:
logger.warn("Unknown state output: %s"%output)
def run(self):
while running:
self._change_state(self.state.run())
def stop(self):
self.running = False
self.state_change.set()