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'
REWIND = b'R'
RESET = b'X'
DEBUG_SCROLL = b'S'
DEBUG_SENSORS = b'Z'
@ -106,6 +107,24 @@ class PizzaHAL:
"""
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):
"""
Set HELO1 pin to `High`, wait for HELO2 to be set `High` by microcontroller.
@ -213,6 +232,9 @@ class PizzaHAL:
return resp
def flush_serial(self):
"""
Clear the serial connection from unhandled responses.
"""
self.serialcon.read_all()
@ -240,6 +262,13 @@ def rewind(hal: PizzaHAL, **kwargs):
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):
"""
Turn off the lights.
@ -303,15 +332,15 @@ def wait_for_input(hal: PizzaHAL,
resp = resp[1]
if resp == 1:
blue_cb(**kwargs)
blue_cb()
elif resp == 2:
red_cb(**kwargs)
red_cb()
elif resp == 4:
yellow_cb(**kwargs)
yellow_cb()
elif resp == 8:
green_cb(**kwargs)
green_cb()
elif timeout_cb is not None:
timeout_cb(**kwargs)
timeout_cb()
def set_light(hal: PizzaHAL,

View file

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

View file

@ -5,7 +5,7 @@ from enum import Enum, auto
from pizzactrl import fs_names
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__)
@ -32,7 +32,6 @@ class Statemachine:
hal: PizzaHAL,
story: Storyboard,
default_lang=Language.NOT_SET,
move: bool = False,
loop: bool = True,
test: bool = False):
self.hal = hal
@ -41,7 +40,7 @@ class Statemachine:
self.lang = None
self.story = story
self.story.MOVE = move
self.story.MOVE = True
self.test = test
self.loop = loop
@ -71,8 +70,7 @@ class Statemachine:
State.IDLE_END: self._idle_end
}
while (self.state is not State.ERROR) and \
(self.state is not State.SHUTDOWN):
while (self.state is not State.ERROR) and (self.state is not State.SHUTDOWN):
logger.debug(f'Run(state={self.state})')
try:
choice[self.state]()
@ -185,22 +183,24 @@ class Statemachine:
turn_off(self.hal)
self.story.skip_flag = False
self.story.rewind()
if self.loop:
self.state = State.IDLE_START
else:
self._next_state()
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()
def _shutdown(self):
"""
Clean up, end execution
"""
self.hal.pin_helo1.off()
del self.hal
del self.story

View file

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