2014-10-16 06:01:52 +00:00
|
|
|
import stepper
|
2014-10-18 19:41:05 +00:00
|
|
|
import time
|
|
|
|
import random
|
2014-10-21 21:21:43 +00:00
|
|
|
import thermo
|
2014-10-16 06:01:52 +00:00
|
|
|
import warnings
|
2014-10-21 21:21:43 +00:00
|
|
|
import threading
|
|
|
|
import traceback
|
2014-10-22 01:08:10 +00:00
|
|
|
import logging
|
|
|
|
import states
|
|
|
|
|
|
|
|
logger = logging.getLogger("kiln.manager")
|
2014-10-15 18:10:54 +00:00
|
|
|
|
2014-10-21 21:21:43 +00:00
|
|
|
class Manager(threading.Thread):
|
2014-10-22 01:08:10 +00:00
|
|
|
def __init__(self, start=states.Idle):
|
2014-10-21 21:21:43 +00:00
|
|
|
"""
|
2014-10-22 01:08:10 +00:00
|
|
|
Implement a state machine that cycles through States
|
2014-10-21 21:21:43 +00:00
|
|
|
"""
|
2014-10-22 01:08:10 +00:00
|
|
|
super(Manager, self).__init__()
|
2014-10-21 21:21:43 +00:00
|
|
|
self._send = None
|
2014-10-22 01:08:10 +00:00
|
|
|
self.thermocouple = thermo.Monitor(self._send_state)
|
|
|
|
self.regulator = stepper.Regulator()
|
2014-10-21 21:21:43 +00:00
|
|
|
|
|
|
|
self.profile = None
|
|
|
|
|
2014-10-22 01:08:10 +00:00
|
|
|
self.state = start(self)
|
|
|
|
self.state_change = threading.Event()
|
|
|
|
|
|
|
|
self.running = True
|
|
|
|
self.start()
|
|
|
|
|
2014-10-21 21:21:43 +00:00
|
|
|
def register(self, webapp):
|
|
|
|
self._send = webapp.send
|
|
|
|
|
2014-10-22 01:08:10 +00:00
|
|
|
def notify(self, data):
|
|
|
|
if self._send is not None:
|
|
|
|
self._send(data)
|
|
|
|
else:
|
|
|
|
logging.warn("No notifier set, ignoring message: %s"%data)
|
|
|
|
|
2014-10-21 21:21:43 +00:00
|
|
|
def _send_state(self, time, temp):
|
|
|
|
profile = None
|
|
|
|
if self.profile is not None:
|
|
|
|
profile.get_state()
|
|
|
|
|
|
|
|
state = dict(
|
2014-10-22 01:08:10 +00:00
|
|
|
output=self.regulator.output,
|
2014-10-21 21:21:43 +00:00
|
|
|
profile=profile,
|
|
|
|
time=time,
|
|
|
|
temp=temp,
|
|
|
|
)
|
|
|
|
if self._send is not None:
|
|
|
|
self._send(state)
|
|
|
|
|
2014-10-22 01:08:10 +00:00
|
|
|
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())
|
|
|
|
|
2014-10-21 21:21:43 +00:00
|
|
|
def stop(self):
|
|
|
|
self.running = False
|
2014-10-22 01:08:10 +00:00
|
|
|
self.state_change.set()
|