implemented reset command.

fixing bugs in statemachine and storyboard.
This commit is contained in:
jpunkt 2022-01-24 20:12:59 +01:00
parent 927204b00a
commit 7ce7b70499
4 changed files with 76 additions and 42 deletions

View file

@ -58,6 +58,7 @@ class SerialCommands(Enum):
RECORD = b'C' RECORD = b'C'
REWIND = b'R' REWIND = b'R'
RESET = b'X'
DEBUG_SCROLL = b'S' DEBUG_SCROLL = b'S'
DEBUG_SENSORS = b'Z' DEBUG_SENSORS = b'Z'
@ -106,6 +107,24 @@ class PizzaHAL:
""" """
return self.lid_switch.is_pressed return self.lid_switch.is_pressed
@property
def helo1(self) -> bool:
"""
Returns the status of the HELO1 pin
"""
return bool(self.helo1.value)
@helo1.setter
def helo1(self, value: bool):
self.helo1.value = 1 if value else 0
@property
def helo2(self) -> bool:
"""
Returns the value of the HELO2 pin (read only)
"""
return bool(self.helo2.value)
def init_connection(self): def init_connection(self):
""" """
Set HELO1 pin to `High`, wait for HELO2 to be set `High` by microcontroller. Set HELO1 pin to `High`, wait for HELO2 to be set `High` by microcontroller.
@ -213,6 +232,9 @@ class PizzaHAL:
return resp return resp
def flush_serial(self): def flush_serial(self):
"""
Clear the serial connection from unhandled responses.
"""
self.serialcon.read_all() self.serialcon.read_all()
@ -240,6 +262,13 @@ def rewind(hal: PizzaHAL, **kwargs):
hal.send_cmd(SerialCommands.REWIND, ignore_lid=True) hal.send_cmd(SerialCommands.REWIND, ignore_lid=True)
def reset(hal: PizzaHAL, **kwargs):
"""
Prepare microcontroller for reset.
"""
hal.send_cmd(SerialCommands.RESET, ignore_lid=True)
def turn_off(hal: PizzaHAL, **kwargs): def turn_off(hal: PizzaHAL, **kwargs):
""" """
Turn off the lights. Turn off the lights.
@ -303,15 +332,15 @@ def wait_for_input(hal: PizzaHAL,
resp = resp[1] resp = resp[1]
if resp == 1: if resp == 1:
blue_cb(**kwargs) blue_cb()
elif resp == 2: elif resp == 2:
red_cb(**kwargs) red_cb()
elif resp == 4: elif resp == 4:
yellow_cb(**kwargs) yellow_cb()
elif resp == 8: elif resp == 8:
green_cb(**kwargs) green_cb()
elif timeout_cb is not None: elif timeout_cb is not None:
timeout_cb(**kwargs) timeout_cb()
def set_light(hal: PizzaHAL, def set_light(hal: PizzaHAL,

View file

@ -1,3 +1,4 @@
from email.policy import default
import sys import sys
import click import click
@ -11,18 +12,17 @@ logger = logging.getLogger('pizzactrl.main')
@click.command() @click.command()
@click.option('--move', is_flag=True)
@click.option('--test', is_flag=True, default=False) @click.option('--test', is_flag=True, default=False)
@click.option('--debug', is_flag=True, default=False) @click.option('--debug', is_flag=True, default=False)
@click.option('--loop', is_flag=True, default=False) @click.option('--loop', is_flag=True, default=False)
def main(move: bool=False, test: bool=False, debug: bool=False, loop: bool=False): def main(test: bool=False, debug: bool=False, loop: bool=False):
if debug or test: if debug or test:
logging.basicConfig(level=logging.DEBUG, stream=sys.stdout) logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)
else: else:
logging.basicConfig(level=logging.INFO, stream=sys.stdout) logging.basicConfig(level=logging.INFO, stream=sys.stdout)
hal = PizzaHAL() hal = PizzaHAL()
sm = Statemachine(hal, STORYBOARD, move=move, loop=loop, test=test) sm = Statemachine(hal, STORYBOARD, loop=loop, test=test)
sm.test = test sm.test = test

View file

@ -5,7 +5,7 @@ from enum import Enum, auto
from pizzactrl import fs_names from pizzactrl import fs_names
from .storyboard import Language, Storyboard from .storyboard import Language, Storyboard
from .hal_serial import SerialCommunicationError, CommunicationError, PizzaHAL, wait_for_input, play_sound, turn_off from .hal_serial import SerialCommunicationError, CommunicationError, PizzaHAL, wait_for_input, play_sound, turn_off, reset
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -32,7 +32,6 @@ class Statemachine:
hal: PizzaHAL, hal: PizzaHAL,
story: Storyboard, story: Storyboard,
default_lang=Language.NOT_SET, default_lang=Language.NOT_SET,
move: bool = False,
loop: bool = True, loop: bool = True,
test: bool = False): test: bool = False):
self.hal = hal self.hal = hal
@ -41,7 +40,7 @@ class Statemachine:
self.lang = None self.lang = None
self.story = story self.story = story
self.story.MOVE = move self.story.MOVE = True
self.test = test self.test = test
self.loop = loop self.loop = loop
@ -71,8 +70,7 @@ class Statemachine:
State.IDLE_END: self._idle_end State.IDLE_END: self._idle_end
} }
while (self.state is not State.ERROR) and \ while (self.state is not State.ERROR) and (self.state is not State.SHUTDOWN):
(self.state is not State.SHUTDOWN):
logger.debug(f'Run(state={self.state})') logger.debug(f'Run(state={self.state})')
try: try:
choice[self.state]() choice[self.state]()
@ -185,22 +183,24 @@ class Statemachine:
turn_off(self.hal) turn_off(self.hal)
self.story.skip_flag = False self.story.skip_flag = False
self.story.rewind() self.story.rewind()
if self.loop:
self.state = State.IDLE_START
else:
self._next_state() self._next_state()
def _idle_end(self): def _idle_end(self):
""" """
Initialize shutdown Initialize shutdown or go back to POST if `self.loop=True`
""" """
reset(self.hal)
self.hal.helo1 = False
if self.loop:
self.state = State.POST
else:
self._next_state() self._next_state()
def _shutdown(self): def _shutdown(self):
""" """
Clean up, end execution Clean up, end execution
""" """
self.hal.pin_helo1.off()
del self.hal del self.hal
del self.story del self.story

View file

@ -25,10 +25,11 @@ class Option(Enum):
""" """
Options can be chosen by the user in WAIT_FOR_INPUT Options can be chosen by the user in WAIT_FOR_INPUT
""" """
CONTINUE = {'skip_flag': False} # Continue with chapter. Set `skip_flag=True` to skip all chapters marked with `skip_flag` CONTINUE = {'skip_flag': None} # Continue with chapter. Set `skip_flag=True` to skip all chapters marked with `skip_flag`
REPEAT = {'rewind': True} # Repeat chapter from beginning. `rewind=True`: reset scrolls to starting position REPEAT = {'rewind': True} # Repeat chapter from beginning. `rewind=True`: reset scrolls to starting position
GOTO = {'chapter': 0} # Jump to chapter number GOTO = {'chapter': 0,
QUIT = {'quit': True} # End playback. 'skip_flag': None} # Jump to chapter number
QUIT = {} # End playback. Will cause restart if `statemachine.loop=True`
class Select: class Select:
@ -65,10 +66,10 @@ class Activity(Enum):
RECORD_VIDEO = {'duration': 60.0, RECORD_VIDEO = {'duration': 60.0,
'filename': ''} 'filename': ''}
TAKE_PHOTO = {'filename': ''} TAKE_PHOTO = {'filename': ''}
ADVANCE_UP = {'steps': 46, ADVANCE_UP = {'steps': 48,
'scroll': Scrolls.VERTICAL, 'scroll': Scrolls.VERTICAL,
'speed': 3} 'speed': 3}
ADVANCE_LEFT = {'steps': 96, ADVANCE_LEFT = {'steps': 92,
'scroll': Scrolls.HORIZONTAL, 'scroll': Scrolls.HORIZONTAL,
'speed': 3} 'speed': 3}
LIGHT_FRONT = {'r': 0, LIGHT_FRONT = {'r': 0,
@ -211,7 +212,7 @@ class Storyboard:
self.skip_flag = False # Set `True` to skip chapters marked with skip_flag self.skip_flag = False # Set `True` to skip chapters marked with skip_flag
self.MOVE = False # self.move is reset to this value self.MOVE = True # self.move is reset to this value
self._move = self.MOVE self._move = self.MOVE
self._lang = Language.NOT_SET self._lang = Language.NOT_SET
@ -255,39 +256,40 @@ class Storyboard:
Return a callback for the appropriate option and parameters. Return a callback for the appropriate option and parameters.
Callbacks set the properties of `Statemachine` to determine it's behaviour. Callbacks set the properties of `Statemachine` to determine it's behaviour.
""" """
# rewind = selection.values.get('rewind', Option.REPEAT.value['rewind']) _rewind = selection.values.get('rewind', None)
# next_chapter = selection.values.get('chapter', Option.GOTO.value['chapter']) _next_chapter = selection.values.get('chapter', None)
# shutdown = selection.values.get('shutdown', Option.QUIT.value['shutdown'])
_skip_flag = selection.values.get('skip_flag', None) _skip_flag = selection.values.get('skip_flag', None)
if _skip_flag is not None:
self.skip_flag = _skip_flag
def _continue(**kwargs): def _continue():
""" """
Continue in the Storyboard. Prepare advancing to the next chapter. Continue in the Storyboard. Prepare advancing to the next chapter.
""" """
logger.debug('User selected continue') logger.debug('User selected continue')
if len(self.story) > (self._index + 1): if len(self.story) > (self._index + 1):
self.next_chapter = self._index + 1 self.next_chapter = self._index + 1
if _skip_flag is not None:
self.skip_flag = _skip_flag
else: else:
self.next_chapter = None self.next_chapter = None
def _repeat(rewind: bool=None, **kwargs): def _repeat():
""" """
Repeat the current chapter. Do not rewind if the selection says so. Repeat the current chapter. Do not rewind if the selection says so.
""" """
logger.debug('User selected repeat') logger.debug('User selected repeat')
self.next_chapter = self._index self.next_chapter = self._index
self.move = rewind self.move = _rewind
def _goto(chapter: int=None, **kwargs): def _goto():
""" """
Jump to a specified chapter. Jump to a specified chapter.
""" """
logger.debug(f'User selected goto {chapter}') logger.debug(f'User selected goto {_next_chapter}')
self.next_chapter = chapter self.next_chapter = _next_chapter
if _skip_flag is not None:
self.skip_flag = _skip_flag
def _quit(**kwargs): def _quit():
logger.debug('User selected quit') logger.debug('User selected quit')
self.next_chapter = None self.next_chapter = None
@ -346,6 +348,8 @@ class Storyboard:
def _move(hal, do_now=True, **kwargs): def _move(hal, do_now=True, **kwargs):
logger.debug(f'Storyboard._move({kwargs})') logger.debug(f'Storyboard._move({kwargs})')
if not self.move:
return
set_movement(hal, **kwargs) set_movement(hal, **kwargs)
if do_now: if do_now:
do_it(hal) do_it(hal)
@ -421,12 +425,12 @@ class Storyboard:
steps = ch.rewind() steps = ch.rewind()
h_steps += steps['h_steps'] h_steps += steps['h_steps']
v_steps += steps['v_steps'] v_steps += steps['v_steps']
elif diff > 0: elif diff > 0:
""" """
Skip all chapters up to target Skip all chapters up to target
""" """
for ch in self.story[self._index:self._next_chapter]: for ch in self.story[self._index:self._next_chapter]:
logger.debug(f'Queueing chapter {ch} for skipping')
steps = ch.skip() steps = ch.skip()
h_steps += steps['h_steps'] h_steps += steps['h_steps']
v_steps += steps['v_steps'] v_steps += steps['v_steps']
@ -438,6 +442,7 @@ class Storyboard:
h_steps = steps['h_steps'] h_steps = steps['h_steps']
v_steps = steps['v_steps'] v_steps = steps['v_steps']
logger.debug(f'storyboard.move={self.move} and h_steps={h_steps}, v_steps={v_steps}.')
if self.move and ((h_steps != 0) or (v_steps != 0)): if self.move and ((h_steps != 0) or (v_steps != 0)):
set_movement(self.hal, scroll=Scrolls.HORIZONTAL, steps=h_steps, speed=4) set_movement(self.hal, scroll=Scrolls.HORIZONTAL, steps=h_steps, speed=4)
set_movement(self.hal, scroll=Scrolls.VERTICAL, steps=v_steps, speed=4) set_movement(self.hal, scroll=Scrolls.VERTICAL, steps=v_steps, speed=4)