pizzabox-main/pizzactrl/statemachine.py

208 lines
5.5 KiB
Python
Raw Normal View History

import logging
import os.path
from typing import Any
from time import sleep
from enum import Enum, auto
from subprocess import call
from pizzactrl import SOUNDS_PATH, fs_names
from pizzactrl.hal import ScrollSensor
from .storyboard import Language, Activity, Select, Option, Storyboard
from .hal_serial import SerialCommunicationError, PizzaHAL, wait_for_input, play_sound, turn_off
from pizzactrl import storyboard
logger = logging.getLogger(__name__)
class State(Enum):
POWER_ON = auto()
POST = auto()
IDLE_START = auto()
LANGUAGE_SELECT = auto()
PLAY = auto()
PAUSE = auto()
POST_PROCESS = auto()
REWIND = auto()
IDLE_END = auto()
SHUTDOWN = auto()
ERROR = -1
class Statemachine:
def __init__(self,
hal: PizzaHAL,
story: Storyboard,
default_lang=Language.NOT_SET,
move: bool = False,
loop: bool = True,
test: bool = False):
self.hal = hal
self.LANG = default_lang
self.lang = None
self.story = story
self.story.MOVE = move
self.test = test
self.loop = loop
self.state = State.POWER_ON
def run(self):
logger.debug(f'Starting Statemachine...')
choice = {
State.POWER_ON: self._power_on,
State.POST: self._post,
State.IDLE_START: self._idle_start,
State.LANGUAGE_SELECT: self._lang_select,
State.PLAY: self._play,
State.POST_PROCESS: self._post_process,
2021-11-19 15:09:49 +00:00
State.REWIND: self._rewind,
State.IDLE_END: self._idle_end
}
while (self.state is not State.ERROR) and \
(self.state is not State.SHUTDOWN):
logger.debug(f'Run(state={self.state})')
choice[self.state]()
if self.state is State.ERROR:
logger.debug('An error occurred. Trying to notify user...')
if self.lang is Language.DE:
play_sound(self.hal, fs_names.SFX_ERROR_DE)
elif self.lang is Language.EN:
play_sound(self.hal, fs_names.SFX_ERROR_EN)
else:
play_sound(self.hal, fs_names.SFX_ERROR)
self._shutdown()
def _power_on(self):
"""
Initialize hal callbacks, load sounds
"""
# TODO enable lid sensor
# self.hal.lid_sensor.when_pressed = self._lid_open
# self.hal.lid_sensor.when_released = self._lid_closed
self.hal.init_sounds()
self.hal.init_camera()
self.state = State.POST
def _post(self):
"""
Power on self test.
"""
if (not self.test) and (not os.path.exists(fs_names.USB_STICK)):
logger.warning('USB-Stick not found.')
self.state = State.ERROR
return
# TODO set RPi_HELO pins, wait for response
# Callback for start when blue button is held
# self.hal.btn_start.when_activated = self._start_or_rewind
# logger.debug('start button callback activated')
try:
self.hal.init_connection()
except SerialCommunicationError as e:
self.state = State.ERROR
logger.exception(e)
return
# play a sound if everything is alright
play_sound(self.hal, fs_names.SFX_POST_OK)
if self.test:
self.state = State.LANGUAGE_SELECT
else:
self.state = State.IDLE_START
def _idle_start(self):
"""
Device is armed. Wait for user to press start button
"""
pass
def _lang_select(self):
"""
Select language
"""
def _select_de():
self.lang = Language.DE
def _select_en():
self.lang = Language.EN
def _select_default():
self.lang = self.LANG
#sound = self.hal.soundcache.get(fs_names.SND_SELECT_LANG)
#logger.debug(f'got sound {sound} from soundcache.')
wait_for_input(self.hal,
blue_cb=_select_de,
red_cb=_select_en,
sound=fs_names.SND_SELECT_LANG,
timeout_cb=_select_default)
self.story.language = self.lang
logger.debug(f'User selected language={self.lang}')
self.state = State.PLAY
def _play(self):
"""
Select language, then run the storyboard
"""
self.story.hal = self.hal
while self.story.hasnext():
self.story.play_chapter()
self.story.advance_chapter()
self.state = State.POST_PROCESS
def _post_process(self):
"""
Post-processing
"""
# TODO postprocessing - add sound
# logger.debug('Converting video...')
# cmdstring = f'MP4Box -add {fs_names.REC_DRAW_CITY} {fs_names.REC_MERGED_VIDEO}'
# call([cmdstring], shell=True)
self.state = State.REWIND
def _rewind(self):
"""
Rewind all scrolls, post-process videos
"""
turn_off(self.hal)
self.story.rewind()
if self.loop:
self.state = State.IDLE_START
else:
self.state = State.IDLE_END
def _idle_end(self):
"""
Initialize shutdown
"""
self.state = State.SHUTDOWN
def _shutdown(self):
"""
Clean up, end execution
"""
del self.hal