Example #1
0
    def test_ordered_transitions(self):
        states = ['beginning', 'middle', 'end']
        m = Machine('self', states)
        m.add_ordered_transitions()
        self.assertEqual(m.state, 'initial')
        m.next_state()
        self.assertEqual(m.state, 'beginning')
        m.next_state()
        m.next_state()
        self.assertEqual(m.state, 'end')
        m.next_state()
        self.assertEqual(m.state, 'initial')

        # Include initial state in loop
        m = Machine('self', states)
        m.add_ordered_transitions(loop_includes_initial=False)
        m.to_end()
        m.next_state()
        self.assertEqual(m.state, 'beginning')

        # Do not loop transitions
        m = Machine('self', states)
        m.add_ordered_transitions(loop=False)
        m.to_end()
        with self.assertRaises(MachineError):
            m.next_state()

        # Test user-determined sequence and trigger name
        m = Machine('self', states, initial='beginning')
        m.add_ordered_transitions(['end', 'beginning'], trigger='advance')
        m.advance()
        self.assertEqual(m.state, 'end')
        m.advance()
        self.assertEqual(m.state, 'beginning')

        # Via init argument
        m = Machine('self',
                    states,
                    initial='beginning',
                    ordered_transitions=True)
        m.next_state()
        self.assertEqual(m.state, 'middle')

        # Alter initial state
        m = Machine('self', states, initial='middle', ordered_transitions=True)
        m.next_state()
        self.assertEqual(m.state, 'end')
        m.next_state()
        self.assertEqual(m.state, 'beginning')

        # Partial state machine without the initial state
        m = Machine('self', states, initial='beginning')
        m.add_ordered_transitions(['middle', 'end'])
        self.assertEqual(m.state, 'beginning')
        with self.assertRaises(MachineError):
            m.next_state()
        m.to_middle()
        for s in ('end', 'middle', 'end'):
            m.next_state()
            self.assertEqual(m.state, s)
class TaskMachine(object):
    def __init__(self, machine_dict):
        # self.machine_dict = machine_dict
        self.events = Events([Event(**e) for e in machine_dict['events']])
        self.machine = Machine(model=self,
                               states=self.states(),
                               initial=STATES.PENDING)
        self.machine.add_ordered_transitions()
        self.max_timeout = machine_dict.get('max_timeout', FIVE_MINUTES)

    def states(self):
        pre_states = [STATES.PENDING]
        # scheduled?
        # pre-flight resource checks? if a db or an integration
        # is not accessible, fail early option
        post_states = [STATES.FINISHED]
        return pre_states + self.events.states() + post_states

    def is_running(self):
        return True

    # can event fulfillment strategy decorate?
    # noop strategy by default
    def run_current_event(self, event_result_q):
        """
        Executes the current event, using the provided fulfilment strategy
        until the transition conditions are met.

        TODO, errors, timeouts, etc.

        :param next_state_q:
        :return:
        """
        # right now sleep then trigger completion
        gevent.spawn(self.events.run, self.state, event_result_q)
Example #3
0
class Week(object):
    states = [
        'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
        'Saturday'
    ]

    def __init__(self, model):
        self.model = model
        self.machine = Machine(model=self,
                               states=Week.states,
                               initial='Thursday')
        self.machine.add_ordered_transitions()
Example #4
0
    def test_ordered_transition_condition(self):
        class Model:
            def __init__(self):
                self.blocker = False

            def check_blocker(self):
                return self.blocker

        model = Model()
        states = ['beginning', 'middle', 'end']
        m = Machine(model, states, initial='beginning')
        m.add_ordered_transitions(conditions=[None, None, 'check_blocker'])
        model.to_end()
        self.assertFalse(model.next_state())
        model.blocker = True
        self.assertTrue(model.next_state())
Example #5
0
    def test_ordered_transition_condition(self):
        class Model:
            def __init__(self):
                self.blocker = False

            def check_blocker(self):
                return self.blocker

        model = Model()
        states = ['beginning', 'middle', 'end']
        m = Machine(model, states, initial='beginning')
        m.add_ordered_transitions(conditions=[None, None, 'check_blocker'])
        model.to_end()
        self.assertFalse(model.next_state())
        model.blocker = True
        self.assertTrue(model.next_state())
Example #6
0
def get_machine(model):
    """Create the parser state machine.

    :param model: An instance of DbtLogParser. The state machine will
        mutate the parser after this function is invoked.
    """
    m = Machine(
        model=model,
        states=[
            State(name=States.SEEK_START),
            State(name=States.SEEK_START_SUMMARY),
            State(name=States.SEEK_FINISH),
            State(name=States.SEEK_DONE),
            State(name=States.DONE),
        ],
        initial=States.SEEK_START,
    )

    # the states above are linear in order; by using `add_ordered_transitions`
    # we automatically make it such that the single trigger `process_next_line`
    # will move linearly between states as ordered above.
    m.add_ordered_transitions(
        trigger="process_next_line",
        # `condition` has a 1:1 mapping with states i.e.
        # we will not transition out of the first state until the first condition
        # is satisfied. conditions correspond to boolean attributes on the model
        # i.e. the parser
        conditions=[
            "found_start",
            "found_start_summary",
            "found_finish",
            "found_done",
            lambda *args, **kwargs: True,
        ],
        # before attempting to transition, the following functions will be
        # invoked with any args or kwargs passed to `process_next_line`;
        # `prepare` occurs before conditions are evaluated;
        # if conditions fail to pass, a transition is halted;
        # in this way, we assure each attempted transition processes another
        # log line
        prepare=[
            "seek_start", "seek_summary", "seek_finish", "seek_done", None
        ],
    )

    return m
Example #7
0
    def test_ordered_transition_callback(self):
        class Model:
            def __init__(self):
                self.flag = False

            def make_true(self):
                self.flag = True

        model = Model()
        states = ['beginning', 'middle', 'end']
        transits = [None, None, 'make_true']
        m = Machine(model, states, initial='beginning')
        m.add_ordered_transitions(before=transits)
        model.next_state()
        self.assertFalse(model.flag)
        model.next_state()
        model.next_state()
        self.assertTrue(model.flag)
Example #8
0
    def test_ordered_transition_callback(self):
        class Model:
            def __init__(self):
                self.flag = False

            def make_true(self):
                self.flag = True

        model = Model()
        states = ['beginning', 'middle', 'end']
        transits = [None, None, 'make_true']
        m = Machine(model, states, initial='beginning')
        m.add_ordered_transitions(before=transits)
        model.next_state()
        self.assertFalse(model.flag)
        model.next_state()
        model.next_state()
        self.assertTrue(model.flag)
class NarcolepticAttocube(object):

    # Define some states. Most of the time, narcoleptic superheroes are just like
    # everyone else. Except for...

    def __init__(self, name):
        self.name = name

        # Initialize the state machine
        self.machine = Machine(
            model=self,
            states=attocube_states,
            transitions=attocube_transitions,
            initial='system idle',
            ignore_invalid_triggers=True,
        )

        self.machine.add_ordered_transitions(
            ['measurement starting', 'measurement running', 'system idle'])

        self.machine.add_ordered_transitions([
            'pilot laser enabled',
            'optics alignment starting',
            'optics alignment running',
            'pilot laser enabled',
        ])

    def on_enter_measurement_starting(self):
        sleep(1)
        self.next_state()

    def on_enter_measurement_running(self):
        sleep(3)
        self.next_state()

    def on_enter_alignment_starting(self):
        print(self.state)
        sleep(1)
        self.next_state()

    def on_enter_alignment_running(self):
        print(self.state)
        sleep(3)
        self.next_state()
Example #10
0
class FSM(object):

    state = None
    states = ['injecting', 'testing_quality', 'testing_extraction']
    initial_state = states[0]
    camera = None

    def __init__(self):
        self.camera = Camera()
        # Initialize the state machine
        self.machine = Machine(model=self,
                               states=self.states,
                               initial=self.initial_state)
        self.machine.add_ordered_transitions()
        self.machine.on_enter_injecting('inject')
        self.machine.on_enter_testing_quality('test_quality')
        self.machine.on_enter_testing_extraction('test_extraction')

    def test_quality(self):
        log.info("Testing quality")
        log.info("Waiting for open signal")
        open_mould_signal = IO(Ports["open_signal"])
        open_mould_signal.wait_signal()
        log.info("Open signal acknowledged")
        log.info("Taking photo")
        test_quality_image = self.camera.take_photo()
        test_quality_image.save("full")

    def test_extraction(self):
        log.info("Testing extraction")

        log.info("Waiting for extraction signal")
        extration_complete_signal = IO(Ports["extraction_signal"])
        extration_complete_signal.wait_signal()
        log.info("Open signal acknowledged")
        log.info("Taking photo")
        test_extraction_image = self.camera.take_photo()
        test_extraction_image.save("empty")

    def inject(self):
        log.info("Injecting")
Example #11
0
    def test_ordered_transitions(self):
        states = ['beginning', 'middle', 'end']
        m = Machine(None, states)
        m.add_ordered_transitions()
        self.assertEquals(m.state, 'initial')
        m.next_state()
        self.assertEquals(m.state, 'beginning')
        m.next_state()
        m.next_state()
        self.assertEquals(m.state, 'end')
        m.next_state()
        self.assertEquals(m.state, 'initial')

        # Include initial state in loop
        m = Machine(None, states)
        m.add_ordered_transitions(loop_includes_initial=False)
        m.to_end()
        m.next_state()
        self.assertEquals(m.state, 'beginning')

        # Test user-determined sequence and trigger name
        m = Machine(None, states, initial='beginning')
        m.add_ordered_transitions(['end', 'beginning'], trigger='advance')
        m.advance()
        self.assertEquals(m.state, 'end')
        m.advance()
        self.assertEquals(m.state, 'beginning')

        # Via init argument
        m = Machine(
            None, states, initial='beginning', ordered_transitions=True)
        m.next_state()
        self.assertEquals(m.state, 'middle')
Example #12
0
    def test_ordered_transitions(self):
        states = ["beginning", "middle", "end"]
        m = Machine(None, states)
        m.add_ordered_transitions()
        self.assertEquals(m.state, "initial")
        m.next_state()
        self.assertEquals(m.state, "beginning")
        m.next_state()
        m.next_state()
        self.assertEquals(m.state, "end")
        m.next_state()
        self.assertEquals(m.state, "initial")

        # Include initial state in loop
        m = Machine(None, states)
        m.add_ordered_transitions(loop_includes_initial=False)
        m.to_end()
        m.next_state()
        self.assertEquals(m.state, "beginning")

        # Test user-determined sequence and trigger name
        m = Machine(None, states, initial="beginning")
        m.add_ordered_transitions(["end", "beginning"], trigger="advance")
        m.advance()
        self.assertEquals(m.state, "end")
        m.advance()
        self.assertEquals(m.state, "beginning")

        # Via init argument
        m = Machine(None, states, initial="beginning", ordered_transitions=True)
        m.next_state()
        self.assertEquals(m.state, "middle")
Example #13
0
    def test_ordered_transitions(self):
        states = ['beginning', 'middle', 'end']
        m = Machine(None, states)
        m.add_ordered_transitions()
        self.assertEquals(m.state, 'initial')
        m.next_state()
        self.assertEquals(m.state, 'beginning')
        m.next_state()
        m.next_state()
        self.assertEquals(m.state, 'end')
        m.next_state()
        self.assertEquals(m.state, 'initial')

        # Include initial state in loop
        m = Machine(None, states)
        m.add_ordered_transitions(loop_includes_initial=False)
        m.to_end()
        m.next_state()
        self.assertEquals(m.state, 'beginning')

        # Test user-determined sequence and trigger name
        m = Machine(None, states, initial='beginning')
        m.add_ordered_transitions(['end', 'beginning'], trigger='advance')
        m.advance()
        self.assertEquals(m.state, 'end')
        m.advance()
        self.assertEquals(m.state, 'beginning')

        # Via init argument
        m = Machine(
            None, states, initial='beginning', ordered_transitions=True)
        m.next_state()
        self.assertEquals(m.state, 'middle')
Example #14
0
class Calendar(object):
    def __init__(self, months, daysPerMonth, firstMonth, year):
        # self.locality = locality
        self.machine = Machine(model=self, states=months, initial=firstMonth)
        self.machine.add_ordered_transitions()
        self.first_month = firstMonth
        self.dayOfMonth = 1

    #should use daysPerMonth
    def next_day(self):
        if self.dayOfMonth == 30:
            self.next_state()
            self.dayOfMonth = 1
        else:
            self.dayOfMonth += 1

    def yearChange(self):
        self.year += 1

    def date(self):
        date = self.state + " " + str(self.dayOfMonth) + ", " + str(self.year)
        return date
Example #15
0
 def test_ordered_transition_error(self):
     m = Machine(states=['A'], initial='A')
     with self.assertRaises(ValueError):
         m.add_ordered_transitions()
     m.add_state('B')
     m.add_ordered_transitions()
     m.add_state('C')
     with self.assertRaises(ValueError):
         m.add_ordered_transitions(['C'])
Example #16
0
 def test_ordered_transition_error(self):
     m = Machine(states=['A'], initial='A')
     with self.assertRaises(ValueError):
         m.add_ordered_transitions()
     m.add_state('B')
     m.add_ordered_transitions()
     m.add_state('C')
     with self.assertRaises(ValueError):
         m.add_ordered_transitions(['C'])
class TransportOrderStateMachine(object):

    # Define some states. Most of the time, narcoleptic superheroes are just like
    # everyone else. Except for...
    states = [
        'init', 'waitForTrigger', 'startPickup', 'movingToPickup',
        'waitForLoading', 'startDelivery', 'movingToDelivery',
        'waitForUnloading', 'waitForFinished', 'waitForFinishedEvents',
        'finished', 'error'
    ]

    def __init__(self, name):
        self.name = name
        #self.task = task
        self.uuid = createUuid(self.name)
        print(self.uuid)
        # Initialize the state machine
        self.machine = Machine(model=self,
                               states=TransportOrderStateMachine.states,
                               initial='init')
        self.machine.add_ordered_transitions()
        # Add some transitions. We could also define these using a static list of
        # dictionaries, as we did with states above, and then pass the list to
        # the Machine initializer as the transitions= argument.

        # At some point, every superhero must rise and shine.
        self.machine.add_transition(trigger='Initialized',
                                    source='init',
                                    dest='waitForTrigger')
        self.machine.add_transition(trigger='TriggerReceived',
                                    source='waitForTrigger',
                                    dest='startPickup')

        # Pickup
        self.machine.add_transition(trigger='GotoPickupDestination',
                                    source='startPickup',
                                    dest='movingToPickup')

        self.machine.add_transition(trigger='ArrivedAtPickupDestination',
                                    source='movingToPickup',
                                    dest='waitForLoading')
        self.machine.add_transition(trigger='AgvIsLoaded',
                                    source='waitForLoading',
                                    dest='startDelivery')

        # Delivery
        self.machine.add_transition(trigger='GotoDeliveryDestination',
                                    source='startDelivery',
                                    dest='movingToDelivery')

        self.machine.add_transition(trigger='ArrivedAtDeliveryDestination',
                                    source='movingToDelivery',
                                    dest='waitForUnloading')

        self.machine.add_transition(trigger='AgvIsUnloaded',
                                    source='waitForUnloading',
                                    dest='waitForFinished')

        # Unused at the moment
        self.machine.add_transition(trigger='OrderStart',
                                    source='moveOrderStart',
                                    dest='moveOrder')
        self.machine.add_transition(trigger='OrderFinished',
                                    source='moveOrder',
                                    dest='moveOrderFinished')
        # Done
        self.machine.add_transition(trigger='SubscribedToFinishedEvents',
                                    source='waitForFinished',
                                    dest='waitForFinishedEvents')

        self.machine.add_transition(trigger='FinishedTriggerReceived',
                                    source='waitForFinishedEvents',
                                    dest='finished')

        self.machine.add_transition(
            trigger='FinishedReceived',
            source=['waitForFinished', 'waitForFinishedEvents'],
            dest='finished')

        self.machine.add_transition(trigger='TransportOrderError',
                                    source='*',
                                    dest='error')

        self.machine.add_transition(trigger='Panic', source='*', dest='idle')
        self.machine.add_transition('Panic', '*', 'error')
        self.machine.add_transition('Init', 'error', 'init')

    # def registerForTrigger(self):
    #     print "reigstererd for Trigger"

    def get_state(self):
        return self.state

    def current_state_is(self, _state):
        if not isinstance(_state, TRANSPORT_ORDER_STATES):
            raise RuntimeError("Wrong parameter")
        if self.__dict__["state"]:
            if self.state == self.states[_state.value]:
                return True
        return False

    def getUuid(self):
        return self.uuid
Example #18
0
class MainController:
    """
    This Class is the global controller of the application.
    """
    states = ['init',
              'starting_trigger',
              'unpausing_trigger',
              'playing_ready_sound',
              'waiting_for_trigger_callback',
              'start_order_listener',
              'playing_wake_up_answer',
              'waiting_for_order_listener_callback',
              'analysing_order']

    def __init__(self, brain=None):
        self.brain = brain
        # get global configuration
        sl = SettingLoader()
        self.settings = sl.settings
        # keep in memory the order to process
        self.order_to_process = None

        # Starting the rest API
        self._start_rest_api()

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # boolean used to know id we played the on ready notification at least one time
        self.on_ready_notification_played_once = False

        # Initialize the state machine
        self.machine = Machine(model=self, states=MainController.states, initial='init', queued=True)

        # define transitions
        self.machine.add_transition('start_trigger', 'init', 'starting_trigger')
        self.machine.add_transition('unpause_trigger', ['starting_trigger', 'analysing_order'], 'unpausing_trigger')
        self.machine.add_transition('play_ready_sound', 'unpausing_trigger', 'playing_ready_sound')
        self.machine.add_transition('wait_trigger_callback', 'playing_ready_sound', 'waiting_for_trigger_callback')
        self.machine.add_transition('play_wake_up_answer', 'waiting_for_trigger_callback', 'playing_wake_up_answer')
        self.machine.add_transition('wait_for_order', 'playing_wake_up_answer', 'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order', 'waiting_for_order_listener_callback', 'analysing_order')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_playing_ready_sound('play_ready_sound_process')
        self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread')
        self.machine.on_enter_playing_wake_up_answer('play_wake_up_answer_thread')
        self.machine.on_enter_start_order_listener('start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')
        self.machine.on_enter_unpausing_trigger('unpausing_trigger_process')

        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("Entering state: %s" % self.state)
        self.trigger_instance = self._get_default_trigger()
        self.trigger_instance.daemon = True
        # Wait that the kalliope trigger is pronounced by the user
        self.trigger_instance.start()
        self.next_state()

    def unpausing_trigger_process(self):
        """
        If the trigger was in pause, this method will unpause it to listen again for the hotword
        """
        logger.debug("Entering state: %s" % self.state)
        self.trigger_instance.unpause()
        self.trigger_callback_called = False
        Utils.print_info("Waiting for trigger detection")
        self.next_state()

    def play_ready_sound_process(self):
        """
        Play a sound when Kalliope is ready to be awaken at the first start
        """
        logger.debug("Entering state: %s" % self.state)
        if (not self.on_ready_notification_played_once and self.settings.play_on_ready_notification == "once") or \
                self.settings.play_on_ready_notification == "always":
            # we remember that we played the notification one time
            self.on_ready_notification_played_once = True
            # here we tell the user that we are listening
            if self.settings.on_ready_answers is not None:
                Say(message=self.settings.on_ready_answers)
            elif self.settings.on_ready_sounds is not None:
                random_sound_to_play = self._get_random_sound(self.settings.on_ready_sounds)
                Mplayer.play(random_sound_to_play)
        self.next_state()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug("Trigger callback called, switching to the next state")
        # self.next_state()
        self.trigger_callback_called = True

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("Entering state: %s" % self.state)
        # pause the trigger process
        self.trigger_instance.pause()
        # start listening for an order
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def play_wake_up_answer_thread(self):
        """
        Play a sound or make Kalliope say something to notify the user that she has been awaken and now
        waiting for order
        """
        logger.debug("Entering state: %s" % self.state)
        # if random wake answer sentence are present, we play this
        if self.settings.random_wake_up_answers is not None:
            Say(message=self.settings.random_wake_up_answers)
        else:
            random_sound_to_play = self._get_random_sound(self.settings.random_wake_up_sounds)
            Mplayer.play(random_sound_to_play)

        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug("order listener callback called. Order to process: %s" % order)
        self.order_to_process = order
        self.order_listener_callback_called = True

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        logger.debug("order in analysing_order_thread %s" % self.order_to_process)
        if self.order_to_process is not None:   # maybe we have received a null audio from STT engine
            order_analyser = OrderAnalyser(self.order_to_process, brain=self.brain)
            order_analyser.start()
        else:
            if self.settings.default_synapse is not None:
                SynapseLauncher.start_synapse(name=self.settings.default_synapse, brain=self.brain)
        # return to the state "unpausing_trigger"
        self.unpause_trigger()

    def _get_default_trigger(self):
        """
        Return an instance of the default trigger
        :return: Trigger
        """
        for trigger in self.settings.triggers:
            if trigger.name == self.settings.default_trigger_name:
                return TriggerLauncher.get_trigger(trigger, callback=self.trigger_callback)

    @staticmethod
    def _get_random_sound(random_wake_up_sounds):
        """
        Return a path of a sound to play
        If the path is absolute, test if file exist
        If the path is relative, we check if the file exist in the sound folder
        :param random_wake_up_sounds: List of wake_up sounds
        :return: path of a sound to play
        """
        # take first randomly a path
        random_path = random.choice(random_wake_up_sounds)
        logger.debug("Selected sound: %s" % random_path)
        return Utils.get_real_file_path(random_path)

    def _start_rest_api(self):
        """
        Start the Rest API if asked in the user settings
        """
        # run the api if the user want it
        if self.settings.rest_api.active:
            Utils.print_info("Starting REST API Listening port: %s" % self.settings.rest_api.port)
            app = Flask(__name__)
            flask_api = FlaskAPI(app=app,
                                 port=self.settings.rest_api.port,
                                 brain=self.brain,
                                 allowed_cors_origin=self.settings.rest_api.allowed_cors_origin)
            flask_api.daemon = True
            flask_api.start()
Example #19
0
class Order(SignalModule, Thread):

    states = ['init',
              'starting_trigger',
              'waiting_for_trigger_callback',
              'stopping_trigger',
              'start_order_listener',
              'waiting_for_order_listener_callback',
              'analysing_order']

    def __init__(self):
        super(SignalModule, self).__init__()
        Thread.__init__(self, name=Order)
        Utils.print_info('Starting order signal')
        # load settings and brain from singleton
        sl = SettingLoader()
        self.settings = sl.settings
        self.brain = BrainLoader().brain

        # keep in memory the order to process
        self.order_to_process = None

        # get the player instance
        self.player_instance = PlayerLauncher.get_player(settings=self.settings)

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False
        self.skip_trigger = False  # keep the status of the trigger, if true we can skip it in the statue machine

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # Initialize the state machine
        self.machine = Machine(model=self, states=Order.states, initial='init', queued=True)

        # define transitions
        self.machine.add_transition('start_trigger', ['init', 'analysing_order'], 'starting_trigger')
        self.machine.add_transition('wait_trigger_callback', 'starting_trigger', 'waiting_for_trigger_callback')
        self.machine.add_transition('stop_trigger', 'waiting_for_trigger_callback', 'stopping_trigger')
        self.machine.add_transition('wait_for_order', 'stopping_trigger', 'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order', 'waiting_for_order_listener_callback', 'analysing_order')
        self.machine.add_transition('start_order_listener', 'analysing_order', 'start_order_listener')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread')
        self.machine.on_enter_stopping_trigger('stop_trigger_process')
        self.machine.on_enter_start_order_listener('start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')

    def run(self):
        # run hook on_start
        HookManager.on_start()
        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        HookManager.on_waiting_for_trigger()
        self.trigger_instance = TriggerLauncher.get_trigger(settings=self.settings, callback=self.trigger_callback)
        self.trigger_callback_called = False
        self.trigger_instance.daemon = True
        # Wait that the kalliope trigger is pronounced by the user
        self.trigger_instance.start()
        self.next_state()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        if self.settings.options.deaf:  # the user asked to deaf inside the deaf neuron
            Utils.print_info("Kalliope is deaf")
            self.trigger_instance.pause()
        else:
            Utils.print_info("Waiting for trigger detection")
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        # if here, then the trigger has been called
        HookManager.on_triggered()
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        # TODO on end listening here
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug("[Order] Trigger callback called, switching to the next state")
        self.trigger_callback_called = True

    def stop_trigger_process(self):
        """
        The trigger has been awaken, we don't needed it anymore
        :return:
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        self.trigger_instance.stop()
        self.next_state()

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        HookManager.on_start_listening()
        # start listening for an order
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug("[Order] Order listener callback called. Order to process: %s" % order)
        HookManager.on_stop_listening()
        self.order_to_process = order
        self.order_listener_callback_called = True
        # save in kalliope memory the last order
        Cortex.save('kalliope_last_order', order)

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        if self.order_to_process is None or self.order_to_process == "":
            logger.debug("[Order] No audio caught from analysing_order_thread")
            HookManager.on_stt_error()
        else:
            logger.debug("[Order] order in analysing_order_thread %s" % self.order_to_process)
            SynapseLauncher.run_matching_synapse_from_order(self.order_to_process,
                                                            self.brain,
                                                            self.settings,
                                                            is_api_call=False)

        if self.skip_trigger:
            self.start_order_listener()
        else:
            self.start_trigger()

    def on_notification_received(self, notification=None, payload=None):
        logger.debug("[Order] received notification, notification: %s, payload: %s" % (notification, payload))
        if notification == "skip_trigger":
            if "status" in payload:
                if payload["status"] == "True":
                    logger.debug("[Order] switch signals to True")
                    self.skip_trigger = True
                if payload["status"] == "False":
                    logger.debug("[Order] switch signals to False")
                    self.skip_trigger = False
Example #20
0
class Order(SignalModule, Thread):

    states = [
        'init', 'starting_trigger', 'unpausing_trigger',
        'waiting_for_trigger_callback', 'pausing_trigger',
        'start_order_listener', 'waiting_for_order_listener_callback',
        'analysing_order'
    ]

    def __init__(self):
        super(SignalModule, self).__init__()
        Thread.__init__(self, name=Order)
        Utils.print_info('Starting order signal')
        # load settings and brain from singleton
        sl = SettingLoader()
        self.settings = sl.settings
        self.brain = BrainLoader().brain

        # keep in memory the order to process
        self.order_to_process = None

        # get the player instance
        self.player_instance = PlayerLauncher.get_player(
            settings=self.settings)

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False

        # variable from notifications
        self.skip_trigger = False  # keep the status of the trigger, if true we can skip it in the statue machine
        self.counter_max_retry = 0  # 0 means disabled

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # Initialize the state machine
        self.machine = Machine(model=self,
                               states=Order.states,
                               initial='init',
                               queued=True)

        # define transitions
        self.machine.add_transition('start_trigger', 'init',
                                    'starting_trigger')
        self.machine.add_transition('unpause_trigger', 'analysing_order',
                                    'unpausing_trigger')
        self.machine.add_transition('wait_trigger_callback',
                                    'unpausing_trigger',
                                    'waiting_for_trigger_callback')
        self.machine.add_transition('pause_trigger',
                                    'waiting_for_trigger_callback',
                                    'pausing_trigger')
        self.machine.add_transition('wait_for_order', 'pausing_trigger',
                                    'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order',
                                    'waiting_for_order_listener_callback',
                                    'analysing_order')
        self.machine.add_transition('start_order_listener', 'analysing_order',
                                    'start_order_listener')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_unpausing_trigger('unpausing_trigger_process')
        self.machine.on_enter_waiting_for_trigger_callback(
            'waiting_for_trigger_callback_thread')
        self.machine.on_enter_pausing_trigger('pause_trigger_process')
        self.machine.on_enter_start_order_listener(
            'start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback(
            'waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')

    def run(self):
        # run hook on_start
        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        self.trigger_instance = TriggerLauncher.get_trigger(
            settings=self.settings, callback=self.trigger_callback)
        self.trigger_callback_called = False
        self.trigger_instance.daemon = True
        # Wait that the kalliope trigger is pronounced by the user
        self.trigger_instance.start()
        HookManager.on_start()
        self.next_state()

    def unpausing_trigger_process(self):
        """ 
        If the trigger was in pause, this method will unpause it to listen again for the hotword    
        """
        logger.debug("Entering state: %s" % self.state)
        HookManager.on_waiting_for_trigger()
        self.trigger_instance.unpause()
        self.trigger_callback_called = False
        self.next_state()
        #self.waiting_for_trigger_callback_thread()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        if self.settings.options.deaf:  # the user asked to deaf inside the deaf neuron
            Utils.print_info("Kalliope is deaf")
            self.trigger_instance.pause()
        else:
            Utils.print_info("Waiting for trigger detection")
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        # if here, then the trigger has been called
        HookManager.on_triggered()
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        # TODO on end listening here
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug(
            "[Order] Trigger callback called, switching to the next state")
        self.trigger_callback_called = True

    def pause_trigger_process(self):
        """
        The trigger has been awaken, we pause it
        :return:
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        self.trigger_instance.pause()
        self.next_state()

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("[Order] Entering state: %s" % self.state)

        # start listening for an order
        HookManager.on_start_listening()
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(
            callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug(
            "[Order] Order listener callback called. Order to process: %s" %
            order)
        HookManager.on_stop_listening()
        self.order_to_process = order
        self.order_listener_callback_called = True
        # save in kalliope memory the last order
        Cortex.save('kalliope_last_order', order)

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        if self.order_to_process is None or self.order_to_process == "":
            logger.debug("[Order] No audio caught from analysing_order_thread")
            HookManager.on_stt_error()
        else:
            logger.debug("[Order] order in analysing_order_thread %s" %
                         self.order_to_process)
            SynapseLauncher.run_matching_synapse_from_order(
                self.order_to_process,
                self.brain,
                self.settings,
                is_api_call=False)

        if self.skip_trigger:
            self.start_order_listener()
        else:
            self.unpause_trigger()

    def on_notification_received(self, notification=None, payload=None):
        logger.debug(
            "[Order] received notification, notification: %s, payload: %s" %
            (notification, payload))

        # skip_trigger: change the trigger status
        if notification == "skip_trigger":
            self.switch_trigger(payload)

        if notification == "skip_trigger_max_retry":
            self.set_counter_max_retry(payload)

        if notification == "skip_trigger_decrease_max_retry":
            self.decrease_max_retry()

    def set_counter_max_retry(self, payload):
        """
        set a 'counter_max_retry' for max retry before switching automatically the skip_trigger flag to False
        :param payload: payload that contains the max_retry counter value to set
        """
        if "max_retry" in payload:
            if payload["max_retry"] > 0:
                self.counter_max_retry = payload["max_retry"]
                logger.debug("[Order] max_retry set to %s" %
                             self.counter_max_retry)

    def decrease_max_retry(self):
        """
        will decrease the current value of 'counter_max_retry' if the current is > 0
        If the new value == 0, then the skip_trigger flag is automatically switched to False
        """
        logger.debug("[Order] current max_retry: %s" % self.counter_max_retry)
        if self.counter_max_retry > 0:
            self.counter_max_retry = self.counter_max_retry - 1
            logger.debug("[Order] new max_retry value after decrease: %s" %
                         self.counter_max_retry)
            if self.counter_max_retry == 0:
                logger.debug(
                    "[Order] max_retry reached '0'. Set skip_trigger to False")
                # the counter raised 0, we can stop to skip the trigger
                self.skip_trigger = False

        else:
            logger.debug(
                "[Order] cannot decrease max_retry because current value is <= 0"
            )

    def switch_trigger(self, payload):
        """
        switch the skip_trigger flag
        :param payload: payload dict that contains the new status of the skip_trigger flag
        """
        if "status" in payload:
            status = Utils.str_to_bool(payload["status"])
            if status:
                logger.debug("[Order] switch signals to True")
                self.skip_trigger = True
            else:
                logger.debug("[Order] switch signals to False")
                self.skip_trigger = False
Example #21
0
class Order(Thread):
    states = ['init',
              'starting_trigger',
              'playing_ready_sound',
              'waiting_for_trigger_callback',
              'stopping_trigger',
              'playing_wake_up_answer',
              'start_order_listener',
              'waiting_for_order_listener_callback',
              'analysing_order']

    def __init__(self):
        super(Order, self).__init__()
        Utils.print_info('Starting voice order manager')
        # load settings and brain from singleton
        sl = SettingLoader()
        self.settings = sl.settings
        self.brain = BrainLoader().get_brain()

        # keep in memory the order to process
        self.order_to_process = None

        # get the player instance
        self.player_instance = PlayerLauncher.get_player(settings=self.settings)

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False
        self.is_trigger_muted = False

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # boolean used to know id we played the on ready notification at least one time
        self.on_ready_notification_played_once = False

        # rpi setting for led and mute button
        self.init_rpi_utils()

        # Initialize the state machine
        self.machine = Machine(model=self, states=Order.states, initial='init', queued=True)

        # define transitions
        self.machine.add_transition('start_trigger', ['init', 'analysing_order'], 'starting_trigger')
        self.machine.add_transition('play_ready_sound', 'starting_trigger', 'playing_ready_sound')
        self.machine.add_transition('wait_trigger_callback', 'playing_ready_sound', 'waiting_for_trigger_callback')
        self.machine.add_transition('stop_trigger', 'waiting_for_trigger_callback', 'stopping_trigger')
        self.machine.add_transition('play_wake_up_answer', 'stopping_trigger', 'playing_wake_up_answer')
        self.machine.add_transition('wait_for_order', 'playing_wake_up_answer', 'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order', 'playing_wake_up_answer', 'analysing_order')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_playing_ready_sound('play_ready_sound_process')
        self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread')
        self.machine.on_enter_playing_wake_up_answer('play_wake_up_answer_thread')
        self.machine.on_enter_stopping_trigger('stop_trigger_process')
        self.machine.on_enter_start_order_listener('start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')

    def run(self):
        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        self.trigger_instance = TriggerLauncher.get_trigger(settings=self.settings, callback=self.trigger_callback)
        self.trigger_callback_called = False
        self.trigger_instance.daemon = True
        # Wait that the kalliope trigger is pronounced by the user
        self.trigger_instance.start()
        self.next_state()

    def play_ready_sound_process(self):
        """
        Play a sound when Kalliope is ready to be awaken at the first start
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        if (not self.on_ready_notification_played_once and self.settings.play_on_ready_notification == "once") or \
                        self.settings.play_on_ready_notification == "always":
            # we remember that we played the notification one time
            self.on_ready_notification_played_once = True
            # here we tell the user that we are listening
            if self.settings.on_ready_answers is not None:
                Say(message=self.settings.on_ready_answers)
            elif self.settings.on_ready_sounds is not None:
                random_sound_to_play = self._get_random_sound(self.settings.on_ready_sounds)
                self.player_instance.play(random_sound_to_play)
        self.next_state()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        if self.is_trigger_muted:  # the user asked to mute inside the mute neuron
            Utils.print_info("Kalliope is muted")
            self.trigger_instance.pause()
        else:
            Utils.print_info("Waiting for trigger detection")
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        if self.settings.rpi_settings:
            if self.settings.rpi_settings.pin_led_listening:
                RpiUtils.switch_pin_to_off(self.settings.rpi_settings.pin_led_listening)
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug("[MainController] Trigger callback called, switching to the next state")
        self.trigger_callback_called = True

    def stop_trigger_process(self):
        """
        The trigger has been awaken, we don't needed it anymore
        :return:
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        self.trigger_instance.stop()
        self.next_state()

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        # start listening for an order
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def play_wake_up_answer_thread(self):
        """
        Play a sound or make Kalliope say something to notify the user that she has been awaken and now
        waiting for order
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        # if random wake answer sentence are present, we play this
        if self.settings.random_wake_up_answers is not None:
            Say(message=self.settings.random_wake_up_answers)
        else:
            random_sound_to_play = self._get_random_sound(self.settings.random_wake_up_sounds)
            self.player_instance.play(random_sound_to_play)
        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug("[MainController] Order listener callback called. Order to process: %s" % order)
        self.order_to_process = order
        self.order_listener_callback_called = True

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        logger.debug("[MainController] order in analysing_order_thread %s" % self.order_to_process)
        SynapseLauncher.run_matching_synapse_from_order(self.order_to_process,
                                                        self.brain,
                                                        self.settings,
                                                        is_api_call=False)

        # return to the state "unpausing_trigger"
        self.start_trigger()

    @staticmethod
    def _get_random_sound(random_wake_up_sounds):
        """
        Return a path of a sound to play
        If the path is absolute, test if file exist
        If the path is relative, we check if the file exist in the sound folder
        :param random_wake_up_sounds: List of wake_up sounds
        :return: path of a sound to play
        """
        # take first randomly a path
        random_path = random.choice(random_wake_up_sounds)
        logger.debug("[MainController] Selected sound: %s" % random_path)
        return Utils.get_real_file_path(random_path)

    def set_mute_status(self, muted=False):
        """
        Define is the trigger is listening or not
        :param muted: Boolean. If true, kalliope is muted
        """
        logger.debug("[MainController] Mute button pressed. Switch trigger process to muted: %s" % muted)
        if muted:
            self.trigger_instance.pause()
            self.is_trigger_muted = True
            Utils.print_info("Kalliope now muted")
        else:
            self.trigger_instance.unpause()
            self.is_trigger_muted = False
            Utils.print_info("Kalliope now listening for trigger detection")

    def get_mute_status(self):
        """
        return the current state of the trigger (muted or not)
        :return: Boolean
        """
        return self.is_trigger_muted

    def init_rpi_utils(self):
        """
        Start listening on GPIO if defined in settings
        """
        if self.settings.rpi_settings:
            # the user set GPIO pin, we need to instantiate the RpiUtils class in order to setup GPIO
            rpi_utils = RpiUtils(self.settings.rpi_settings, self.set_mute_status)
            if self.settings.rpi_settings.pin_mute_button:
                # start the listening for button pressed thread only if the user set a pin
                rpi_utils.daemon = True
                rpi_utils.start()
        # switch high the start led, as kalliope is started. Only if the setting exist
        if self.settings.rpi_settings:
            if self.settings.rpi_settings.pin_led_started:
                logger.debug("[MainController] Switching pin_led_started to ON")
                RpiUtils.switch_pin_to_on(self.settings.rpi_settings.pin_led_started)
Example #22
0
class Order(Thread):
    states = ['init',
              'starting_trigger',
              'waiting_for_trigger_callback',
              'stopping_trigger',
              'start_order_listener',
              'waiting_for_order_listener_callback',
              'analysing_order']

    def __init__(self):
        super(Order, self).__init__()
        Utils.print_info('Starting order signal')
        # load settings and brain from singleton
        sl = SettingLoader()
        self.settings = sl.settings
        self.brain = BrainLoader().brain

        # keep in memory the order to process
        self.order_to_process = None

        # get the player instance
        self.player_instance = PlayerLauncher.get_player(settings=self.settings)

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False
        self.is_trigger_muted = False

        # If intelora is asked to start muted
        if self.settings.start_options['muted'] is True:
            self.is_trigger_muted = True

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # Initialize the state machine
        self.machine = Machine(model=self, states=Order.states, initial='init', queued=True)

        # define transitions
        self.machine.add_transition('start_trigger', ['init', 'analysing_order'], 'starting_trigger')
        self.machine.add_transition('wait_trigger_callback', 'starting_trigger', 'waiting_for_trigger_callback')
        self.machine.add_transition('stop_trigger', 'waiting_for_trigger_callback', 'stopping_trigger')
        self.machine.add_transition('wait_for_order', 'stopping_trigger', 'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order', 'waiting_for_order_listener_callback', 'analysing_order')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_waiting_for_trigger_callback('waiting_for_trigger_callback_thread')
        self.machine.on_enter_stopping_trigger('stop_trigger_process')
        self.machine.on_enter_start_order_listener('start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback('waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')

    def run(self):
        # run hook on_start
        HookManager.on_start()
        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        HookManager.on_waiting_for_trigger()
        self.trigger_instance = TriggerLauncher.get_trigger(settings=self.settings, callback=self.trigger_callback)
        self.trigger_callback_called = False
        self.trigger_instance.daemon = True
        # Wait that the intelora trigger is pronounced by the user
        self.trigger_instance.start()
        self.next_state()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        if self.is_trigger_muted:  # the user asked to mute inside the mute neuron
            Utils.print_info("Intelora is muted")
            self.trigger_instance.pause()
        else:
            Utils.print_info("Waiting for trigger detection")
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        # if here, then the trigger has been called
        HookManager.on_triggered()
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        # TODO on end listening here
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug("[MainController] Trigger callback called, switching to the next state")
        self.trigger_callback_called = True

    def stop_trigger_process(self):
        """
        The trigger has been awaken, we don't needed it anymore
        :return:
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        self.trigger_instance.stop()
        self.next_state()

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("[MainController] Entering state: %s" % self.state)
        HookManager.on_start_listening()
        # start listening for an order
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug("[MainController] Order listener callback called. Order to process: %s" % order)
        HookManager.on_stop_listening()
        self.order_to_process = order
        self.order_listener_callback_called = True

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        logger.debug("[MainController] order in analysing_order_thread %s" % self.order_to_process)
        SynapseLauncher.run_matching_synapse_from_order(self.order_to_process,
                                                        self.brain,
                                                        self.settings,
                                                        is_api_call=False)

        # return to the state "unpausing_trigger"
        self.start_trigger()

    def set_mute_status(self, muted=False):
        """
        Define is the trigger is listening or not
        :param muted: Boolean. If true, intelora is muted
        """
        logger.debug("[MainController] Mute button pressed. Switch trigger process to muted: %s" % muted)
        if muted:
            self.trigger_instance.pause()
            self.is_trigger_muted = True
            Utils.print_info("Intelora now muted")
            HookManager.on_mute()
        else:
            self.trigger_instance.unpause()
            self.is_trigger_muted = False
            Utils.print_info("Intelora now listening for trigger detection")
            HookManager.on_unmute()

    def get_mute_status(self):
        """
        return the current state of the trigger (muted or not)
        :return: Boolean
        """
        return self.is_trigger_muted
Example #23
0
class Clock(object):
    states = ['work', 'relax', 'shop', 'sleep']

    def __init__(self, model):
        self.dayNumber = -1
        self.model = model
        self.machine = Machine(model=self,
                               states=Clock.states,
                               initial='sleep')
        self.machine.add_ordered_transitions()
        self.machine.on_enter_work('workHandler')
        self.machine.on_enter_relax('relaxHandler')
        self.machine.on_enter_shop('shopHandler')
        self.machine.on_enter_sleep('sleepHandler')

    def next_day(self):
        self.model.week.next_state()
        self.model.calendar.next_day()
        d.shufflePeople()
        self.dayNumber += 1

    def workHandler(self):

        self.next_day()

        religionList = d.getReligions()
        unitList = d.getUnit()
        businessList = d.getBusinesses()
        peopleList = d.getPeople()
        bossList = d.getBosses()
        localityList = d.getLocality()

        if self.model.week.state == 'Friday':
            self.model.salaryPayer.paySalaries()

        if self.model.week.state == 'Sunday':
            for person in peopleList:
                person.churchHandler()
            for religion in religionList:
                for business in religion.getBusinesses():
                    for priest in business.getPriestJobs():
                        priest.service()
        #workday
        if self.model.week.state != 'Sunday':
            for business in businessList:
                business.workHandler()
            for person in peopleList:
                person.workHandler()
                person.bossmaker()
            for boss in bossList:
                i_build = self.model.startupAI.whatToBuild(boss)
                self.model.builder.buildChain(boss.businesses[0], i_build)

    def relaxHandler(self):
        bossList = d.getBosses()
        businessList = d.getBusinesses()
        peopleList = d.getPeople()

        if self.model.week.state != 'Sunday':
            for boss in bossList:
                for business in boss.getBusinesses():
                    self.model.productionAI.setProduction(business)
                    for job in business.craftingJobs:
                        self.model.jobPoster.managePositions(job)
            for business in businessList:
                business.restHandler()

        for person in peopleList:
            person.restHandler()

    def shopHandler(self):
        businessList = d.getBusinesses()
        peopleList = d.getPeople()

        if self.model.week.state != 'Sunday':
            for business in businessList:
                business.shopHandler()
            for person in peopleList:
                person.shopHandler()

    def sleepHandler(self):
        peopleList = d.getPeople()
        businessList = d.getBusinesses()

        for person in peopleList:
            person.sleepHandler()

        if self.model.week.state != 'Sunday':
            for business in businessList:
                business.sleepHandler()

        self.model.out("\nThe day ends.\n")

    def toString(self):
        return ("Today is " + self.model.week.state + ", " +
                str(self.model.calendar.dayOfMonth) + " of " +
                self.model.calendar.state + " in the year " +
                str(self.model.calendar.year) + "." +
                " At this time of day people generally " + self.state + ".")

    def runDay(self):
        self.next_state()
        self.next_state()
        self.next_state()
        self.next_state()

    def getDayNum(self):
        return self.dayNumber
Example #24
0
class Order(SignalModule, Thread):

    states = [
        'init', 'starting_trigger', 'waiting_for_trigger_callback',
        'stopping_trigger', 'start_order_listener',
        'waiting_for_order_listener_callback', 'analysing_order'
    ]

    def __init__(self):
        super(SignalModule, self).__init__()
        Thread.__init__(self, name=Order)
        Utils.print_info('Starting order signal')
        # load settings and brain from singleton
        sl = SettingLoader()
        self.settings = sl.settings
        self.brain = BrainLoader().brain

        # keep in memory the order to process
        self.order_to_process = None

        # get the player instance
        self.player_instance = PlayerLauncher.get_player(
            settings=self.settings)

        # save an instance of the trigger
        self.trigger_instance = None
        self.trigger_callback_called = False
        self.skip_trigger = False  # keep the status of the trigger, if true we can skip it in the statue machine

        # save the current order listener
        self.order_listener = None
        self.order_listener_callback_called = False

        # Initialize the state machine
        self.machine = Machine(model=self,
                               states=Order.states,
                               initial='init',
                               queued=True)

        # define transitions
        self.machine.add_transition('start_trigger',
                                    ['init', 'analysing_order'],
                                    'starting_trigger')
        self.machine.add_transition('wait_trigger_callback',
                                    'starting_trigger',
                                    'waiting_for_trigger_callback')
        self.machine.add_transition('stop_trigger',
                                    'waiting_for_trigger_callback',
                                    'stopping_trigger')
        self.machine.add_transition('wait_for_order', 'stopping_trigger',
                                    'waiting_for_order_listener_callback')
        self.machine.add_transition('analyse_order',
                                    'waiting_for_order_listener_callback',
                                    'analysing_order')
        self.machine.add_transition('start_order_listener', 'analysing_order',
                                    'start_order_listener')

        self.machine.add_ordered_transitions()

        # add method which are called when changing state
        self.machine.on_enter_starting_trigger('start_trigger_process')
        self.machine.on_enter_waiting_for_trigger_callback(
            'waiting_for_trigger_callback_thread')
        self.machine.on_enter_stopping_trigger('stop_trigger_process')
        self.machine.on_enter_start_order_listener(
            'start_order_listener_thread')
        self.machine.on_enter_waiting_for_order_listener_callback(
            'waiting_for_order_listener_callback_thread')
        self.machine.on_enter_analysing_order('analysing_order_thread')

    def run(self):
        # run hook on_start
        HookManager.on_start()
        self.start_trigger()

    def start_trigger_process(self):
        """
        This function will start the trigger thread that listen for the hotword
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        HookManager.on_waiting_for_trigger()
        self.trigger_instance = TriggerLauncher.get_trigger(
            settings=self.settings, callback=self.trigger_callback)
        self.trigger_callback_called = False
        self.trigger_instance.daemon = True
        # Wait that the kalliope trigger is pronounced by the user
        self.trigger_instance.start()
        self.next_state()

    def waiting_for_trigger_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for a trigger detection
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        if self.settings.options.deaf:  # the user asked to deaf inside the deaf neuron
            Utils.print_info("Kalliope is deaf")
            self.trigger_instance.pause()
        else:
            Utils.print_info("Waiting for trigger detection")
        # this loop is used to keep the main thread alive
        while not self.trigger_callback_called:
            sleep(0.1)
        # if here, then the trigger has been called
        HookManager.on_triggered()
        self.next_state()

    def waiting_for_order_listener_callback_thread(self):
        """
        Method to print in debug that the main process is waiting for an order to analyse
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        # this loop is used to keep the main thread alive
        while not self.order_listener_callback_called:
            sleep(0.1)
        # TODO on end listening here
        self.next_state()

    def trigger_callback(self):
        """
        we have detected the hotword, we can now pause the Trigger for a while
        The user can speak out loud his order during this time.
        """
        logger.debug(
            "[Order] Trigger callback called, switching to the next state")
        self.trigger_callback_called = True

    def stop_trigger_process(self):
        """
        The trigger has been awaken, we don't needed it anymore
        :return:
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        self.trigger_instance.stop()
        self.next_state()

    def start_order_listener_thread(self):
        """
        Start the STT engine thread
        """
        logger.debug("[Order] Entering state: %s" % self.state)
        HookManager.on_start_listening()
        # start listening for an order
        self.order_listener_callback_called = False
        self.order_listener = OrderListener(
            callback=self.order_listener_callback)
        self.order_listener.daemon = True
        self.order_listener.start()
        self.next_state()

    def order_listener_callback(self, order):
        """
        Receive an order, try to retrieve it in the brain.yml to launch to attached plugins
        :param order: the sentence received
        :type order: str
        """
        logger.debug(
            "[Order] Order listener callback called. Order to process: %s" %
            order)
        HookManager.on_stop_listening()
        self.order_to_process = order
        self.order_listener_callback_called = True
        # save in kalliope memory the last order
        Cortex.save('kalliope_last_order', order)

    def analysing_order_thread(self):
        """
        Start the order analyser with the caught order to process
        """
        if self.order_to_process is None or self.order_to_process == "":
            logger.debug("[Order] No audio caught from analysing_order_thread")
            HookManager.on_stt_error()
        else:
            logger.debug("[Order] order in analysing_order_thread %s" %
                         self.order_to_process)
            SynapseLauncher.run_matching_synapse_from_order(
                self.order_to_process,
                self.brain,
                self.settings,
                is_api_call=False)

        if self.skip_trigger:
            self.start_order_listener()
        else:
            self.start_trigger()

    def on_notification_received(self, notification=None, payload=None):
        logger.debug(
            "[Order] received notification, notification: %s, payload: %s" %
            (notification, payload))
        if notification == "skip_trigger":
            if "status" in payload:
                if payload["status"] == "True":
                    logger.debug("[Order] switch signals to True")
                    self.skip_trigger = True
                if payload["status"] == "False":
                    logger.debug("[Order] switch signals to False")
                    self.skip_trigger = False
Example #25
0
    def __init__(self, game):
        self.game = game

        m = Machine(self, states=GAME_STATES, initial='turn_start'
                    )  #Note! on_enter won't fire for initial state first time!
        m.add_ordered_transitions()
Example #26
0
from transitions import Machine

from .models import Pizza

states = [{
    'name': 'start'
}, {
    'name': 'size'
}, {
    'name': 'payment_type'
}, {
    'name': 'confirmation'
}]

machine = Machine(states=states, initial='start')
machine.add_ordered_transitions()

TELEGRAM_URL = 'https://api.telegram.org/bot{TOKEN}/'


class Phrases:
    def get_size(self):
        return "Какую вы хотите пиццу?  Большую или маленькую?"

    def get_payment(self):
        return 'Как вы будете платить?'

    def get_confirm(self, size, payment_type):
        return 'Вы хотите {} пиццу, оплата - {}?'.format(
            size.lower(), payment_type.lower())