interface: Support recipe phases next and stop

This commit is contained in:
Nicolò Balzarotti 2022-11-19 21:42:54 +01:00
parent 88324263c9
commit 51ac9d1842
4 changed files with 48 additions and 11 deletions

View File

@ -44,11 +44,13 @@ class MockPIN(Actuator):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def enable(self, enable=True): 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): def disable(self):
print('FAKE DISABLE') pass
# print('FAKE DISABLE')
actuators = { actuators = {
'heater': GPIOPin( 'heater': GPIOPin(

11
app.py
View File

@ -88,13 +88,22 @@ def handle_manual_response(response):
def load_recipe_idx(idx): def load_recipe_idx(idx):
statemachine.loadByIdx(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(): def run_recipes():
while True: while True:
while statemachine.recipe is not None: while statemachine.recipe is not None:
done = statemachine.run_step() done = statemachine.run_step()
if done: if done:
statemachine.done() statemachine.done()
updateState()
sleep(1) sleep(1)
def read_sensors(): def read_sensors():

25
dist/server.js vendored
View File

@ -119,7 +119,6 @@ function render_sensors(sensordata) {
} }
data.push({what: what, unit: unit, data: req_data}); data.push({what: what, unit: unit, data: req_data});
} }
console.log({sensors:data});
html.innerHTML = Mustache.render(template, {sensors:data}); html.innerHTML = Mustache.render(template, {sensors:data});
} }
@ -158,6 +157,14 @@ function load_recipe() {
socket.emit('load recipe idx', localstate.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() { function dismiss_modal() {
applyState(state); applyState(state);
} }
@ -214,6 +221,7 @@ function current_recipe(data) {
html.innerHTML = ''; html.innerHTML = '';
return; return;
} }
data.current_phase = data.phases.find(function (p) { return p.current; });
let template = ` let template = `
<div class="card"> <div class="card">
<header class="card-header"> <header class="card-header">
@ -230,10 +238,21 @@ function current_recipe(data) {
{{/phases}} {{/phases}}
</ul> </ul>
</div> </div>
{{current_phase.text}}
<br/>
<br/>
Next Cond: {{current_phase.text}}
<br/>
On Load: {{current_phase.onload}}
<br/>
On Exit: {{current_phase.onexit}}
</div> </div>
<footer class="card-footer"> <footer class="card-footer">
<a class="card-footer-item is-primary">Pause</a> <!-- <a class="card-footer-item is-primary">Pause</a> -->
<a class="card-footer-item">Stop</a> <a onclick="next_phase()"
class="card-footer-item">Next Phase</a>
<a onclick="stop_recipe()"
class="card-footer-item">Stop</a>
</footer> </footer>
</div>`; </div>`;
html.innerHTML = Mustache.render(template, data); html.innerHTML = Mustache.render(template, data);

View File

@ -105,6 +105,10 @@ class State():
self.recipe = self.recipes[recipe] self.recipe = self.recipes[recipe]
self.postload() self.postload()
def stop(self):
self.current_phase().exit(self.env)
self.done(message='(concat "Recipe " (recipe-name) " stopped manually")')
def loadByName(self, recipe): def loadByName(self, recipe):
r = tuple(i for (i, r) in enumerate(self.recipes) if r.name == recipe) r = tuple(i for (i, r) in enumerate(self.recipes) if r.name == recipe)
if len(r) > 0: if len(r) > 0:
@ -161,8 +165,11 @@ class State():
self.onupdate() self.onupdate()
return resp return resp
def done(self): def done(self, message=None):
self.recipe.done(self.env) self.recipe.done(self.env, message)
# Stop all actuators
for controller in self.envdata.get('controllers', {}).keys():
actuators[controller].disable()
self.recipe = None self.recipe = None
self.env = self.baseenv self.env = self.baseenv
self.envdata = {} self.envdata = {}
@ -217,9 +224,9 @@ class Recipe():
# 'phase': self.phase # 'phase': self.phase
} }
def done(self, env): def done(self, env, message=None):
safe_eval('(notify (concat "Recipe " (recipe-name) " completed at " (now)))', message = message or '(concat "Recipe " (recipe-name) " completed at " (now))'
env) safe_eval(f'(notify {message})', env)
class Phase(): class Phase():
def __init__(self, name, text='', nextcond='#t', onload='', onexit=''): def __init__(self, name, text='', nextcond='#t', onload='', onexit=''):