diff --git a/oven.py b/oven.py new file mode 100644 index 0000000..386ced5 --- /dev/null +++ b/oven.py @@ -0,0 +1,77 @@ +import threading,time,random,datetime,logging + +log_format = '%(asctime)s %(levelname)s %(name)s: %(message)s' +logging.basicConfig(level = logging.INFO, format = log_format) +log = logging.getLogger(__name__) + +class Oven (threading.Thread): + STATE_IDLE = "IDLE" + STATE_RUNNING = "RUNNING" + STATE_ABORT = "ABORT" + STATE_ERROR = "ERROR" + + def __init__(self): + threading.Thread.__init__(self) + self.profile = None + self.start_time = 0 + self.power = 0.0 + self.state = Oven.STATE_IDLE + self.temp_sensor = TempSensor(self) + self.temp_sensor.start() + + def run_profile(self, profile): + self.profile = profile + self.state = Oven.STATE_RUNNING + self.start_time = datetime.datetime.now() + log.info("Starting") + + def abort_run(self): + self.state = Oven.STATE_ABORT + + def run(self): + while True: + if self.state == Oven.STATE_RUNNING: + log.info("running at %f deg C, power %f"%(self.temp_sensor.temperature,self.power)) + if self.temp_sensor.temperature < 250: + self.power = 1.0 + else: + self.power = 0.0 + elif self.state == Oven.STATE_ABORT: + self.power = 0.0 + self.state = Oven.STATE_IDLE + time.sleep(1) + + + def get_state(self): + if self.state == Oven.STATE_RUNNING: + runtime = (datetime.datetime.now() - self.start_time).total_seconds() + else: + runtime = 0 + state = { + 'runtime': runtime, + 'temperature': self.temp_sensor.temperature, + 'state': self.state, + 'power': self.power, + 'totaltime': 300 + } + return state + +class TempSensor(threading.Thread): + def __init__(self,oven): + threading.Thread.__init__(self) + self.temperature = 0 + self.oven = oven + def run(self): + while True: + time_delta = (20.0 - self.temperature)/40 + power_delta = 8.0*self.oven.power + + self.temperature += (time_delta+power_delta) + time.sleep(1) + + + +if __name__ == "__main__": + my_oven = Oven() + my_oven.run_profile("abc") + diff --git a/oven_server.py b/oven_server.py new file mode 100644 index 0000000..4463c04 --- /dev/null +++ b/oven_server.py @@ -0,0 +1,93 @@ +import threading,time +import json +from oven import Oven + +import bottle +from gevent.pywsgi import WSGIServer +from geventwebsocket import WebSocketHandler, WebSocketError + +app = bottle.Bottle() +oven = Oven() +oven.start() +wsocks = [] +wsocks_control = [] + +class OvenWatcher(threading.Thread): + def __init__(self,oven): + threading.Thread.__init__(self) + self.oven = oven + + def run(self): + while True: + oven_state = self.oven.get_state() + notifyAll(oven_state) + time.sleep(1) + +ovenWatcher = OvenWatcher(oven) +ovenWatcher.start() + +@app.route('/run') +def start_oven(): + oven.run_profile("abc") + + return "Starting" + +@app.route('/control') +def handle_control(): + env = bottle.request.environ; + print env + wsock = env.get('wsgi.websocket') + if not wsock: + abort(400, 'Expected WebSocket request.') + + wsocks_control.append(wsock) + while True: + try: + message = wsock.receive() + wsock.send("Your message was: %r" % message) + print message + if message == "start": + print "START" + oven.run_profile("abc") + elif message == "stop": + oven.abort_run() + except WebSocketError: + break + + +@app.route('/status') +def handle_websocket(): + env = bottle.request.environ; + print env + wsock = env.get('wsgi.websocket') + if not wsock: + abort(400, 'Expected WebSocket request.') + + wsocks.append(wsock) + while True: + try: + message = wsock.receive() + wsock.send("Your message was: %r" % message) + except WebSocketError: + break + +def notifyAll(message): + message_json = json.dumps(message) + print "sending to %d clients: %s"%(len(wsocks),message_json) + for wsock in wsocks: + if wsock: + try: + wsock.send(message_json) + except: + print "Could not write to socket!" + wsocks.remove(wsock) + else: + wsocks.remove(wsock) +def main(): + server = WSGIServer(("0.0.0.0", 8080), app, + handler_class=WebSocketHandler) + server.serve_forever() + +if __name__ == "__main__": + main() +