From 51ac9d1842f78df4874cebe137a86d3a07945875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=B2=20Balzarotti?= Date: Sat, 19 Nov 2022 21:42:54 +0100 Subject: [PATCH] interface: Support recipe phases next and stop --- actuators.py | 6 ++++-- app.py | 11 ++++++++++- dist/server.js | 25 ++++++++++++++++++++++--- phasectrl.py | 17 ++++++++++++----- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/actuators.py b/actuators.py index afb925f..3820e4f 100644 --- a/actuators.py +++ b/actuators.py @@ -44,11 +44,13 @@ class MockPIN(Actuator): super().__init__(*args, **kwargs) def enable(self, enable=True): - print('FAKE ENABLE') if enable else self.disable() + pass + # print('FAKE ENABLE') if enable else self.disable() def disable(self): - print('FAKE DISABLE') + pass + # print('FAKE DISABLE') actuators = { 'heater': GPIOPin( diff --git a/app.py b/app.py index 51b345a..211dd1b 100644 --- a/app.py +++ b/app.py @@ -88,13 +88,22 @@ def handle_manual_response(response): def load_recipe_idx(idx): statemachine.loadByIdx(idx) +@socketio.on('stop recipe') +def stop_recipe(): + statemachine.stop() + +@socketio.on('next phase') +def next_phase(): + done = statemachine.next() is None + if done: + statemachine.done() + def run_recipes(): while True: while statemachine.recipe is not None: done = statemachine.run_step() if done: statemachine.done() - updateState() sleep(1) def read_sensors(): diff --git a/dist/server.js b/dist/server.js index f1c7d20..e0446d7 100644 --- a/dist/server.js +++ b/dist/server.js @@ -119,7 +119,6 @@ function render_sensors(sensordata) { } data.push({what: what, unit: unit, data: req_data}); } - console.log({sensors:data}); html.innerHTML = Mustache.render(template, {sensors:data}); } @@ -158,6 +157,14 @@ function load_recipe() { socket.emit('load recipe idx', localstate.recipe); } +function stop_recipe() { + socket.emit('stop recipe'); +} + +function next_phase() { + socket.emit('next phase'); +} + function dismiss_modal() { applyState(state); } @@ -214,6 +221,7 @@ function current_recipe(data) { html.innerHTML = ''; return; } + data.current_phase = data.phases.find(function (p) { return p.current; }); let template = `
@@ -230,10 +238,21 @@ function current_recipe(data) { {{/phases}}
+{{current_phase.text}} +
+
+Next Cond: {{current_phase.text}} +
+On Load: {{current_phase.onload}} +
+On Exit: {{current_phase.onexit}} `; html.innerHTML = Mustache.render(template, data); diff --git a/phasectrl.py b/phasectrl.py index 737348e..46c5f5b 100644 --- a/phasectrl.py +++ b/phasectrl.py @@ -105,6 +105,10 @@ class State(): self.recipe = self.recipes[recipe] self.postload() + def stop(self): + self.current_phase().exit(self.env) + self.done(message='(concat "Recipe " (recipe-name) " stopped manually")') + def loadByName(self, recipe): r = tuple(i for (i, r) in enumerate(self.recipes) if r.name == recipe) if len(r) > 0: @@ -161,8 +165,11 @@ class State(): self.onupdate() return resp - def done(self): - self.recipe.done(self.env) + def done(self, message=None): + self.recipe.done(self.env, message) + # Stop all actuators + for controller in self.envdata.get('controllers', {}).keys(): + actuators[controller].disable() self.recipe = None self.env = self.baseenv self.envdata = {} @@ -217,9 +224,9 @@ class Recipe(): # 'phase': self.phase } - def done(self, env): - safe_eval('(notify (concat "Recipe " (recipe-name) " completed at " (now)))', - env) + def done(self, env, message=None): + message = message or '(concat "Recipe " (recipe-name) " completed at " (now))' + safe_eval(f'(notify {message})', env) class Phase(): def __init__(self, name, text='', nextcond='#t', onload='', onexit=''):