Exemple #1
0
def test_state_machine():
    idle = State('idle')
    active = State('active')
    d1cl = Event('D1CL', 'Door 1 closed')
    idle.add_transition(d1cl, active)
    sm = StateMachine(idle)
    assert sm.start == sm.current_state == idle
    assert sm.all_states() == set([idle, active])
    sm.handle('D1CL')
    assert sm.current_state == active
    def __init__(self):
        super(SimulatedBearings, self).__init__()

        self._csm = StateMachine({
            'initial': 'resting',
            'transitions': {
                ('resting', 'levitating'): lambda: self._levitate,
                ('levitating', 'levitated'): self.levitationComplete,
                ('levitated', 'delevitating'): lambda: not self._levitate,
                ('delevitating', 'resting'): self.delevitationComplete,
            }
        })

        self._levitate = False
Exemple #3
0
 def add_state(self, state_name):
     s = State(state_name)
     if not self.states:
         self.states = [s]
         self.state_machine = StateMachine(s)
     else:
         self.states.append(s)
Exemple #4
0
def state_machine(request):
    idle = State('Idle')
    a = State('A')
    b = State('B')
    idle.add_transition(Event('EVT1', 'Primer evento'), a)
    a.add_transition(Event('EVT2', 'Segundo evento'), b)
    sm = StateMachine(idle)
    return sm
class SimulatedBearings(CanProcess, MagneticBearings):
    def __init__(self):
        super(SimulatedBearings, self).__init__()

        self._csm = StateMachine({
            'initial': 'resting',
            'transitions': {
                ('resting', 'levitating'): lambda: self._levitate,
                ('levitating', 'levitated'): self.levitationComplete,
                ('levitated', 'delevitating'): lambda: not self._levitate,
                ('delevitating', 'resting'): self.delevitationComplete,
            }
        })

        self._levitate = False

    def engage(self):
        self.levitate()

    def disengage(self):
        self.delevitate()

    def levitate(self):
        self._levitate = True

    def delevitate(self):
        self._levitate = False

    def levitationComplete(self):
        return True

    def delevitationComplete(self):
        return True

    def doProcess(self, dt):
        self._csm.process(dt)

    @property
    def ready(self):
        return self._csm.state == 'levitated' and self._levitate

    @property
    def idle(self):
        return self._csm.state == 'resting' and not self._levitate
    def __init__(self,
                 override_states=None,
                 override_transitions=None,
                 override_initial_state=None,
                 override_initial_data=None):
        """
        This class is intended to be sub-classed to implement devices using a finite state machine
        internally.

        Implementing such a device is straightforward, there are three methods that *must* be overriden:

            `_get_state_handlers`
            `_get_initial_state`
            `_get_transition_handlers`

        The first method is supposed to return a dictionary with state handlers for each state
        of the state machine, the second method must return the name of the initial state.
        The third method must return a dict-like object (often an OrderedDict from collections)
        that defines the conditions for transitions between the states of the state machine.

        They are implemented as methods and not as plain class member variables, because often
        they use the `self`-variable, which does not exist at the class level.

        From these three methods, a `StateMachine`-instance is constructed, it's available as
        the device's `_csm`-member. CSM is short for "cycle-based state machine".

        Most device implementation will also want to override this method:

            `_initialize_data`

        This method should initialise device state variables (such as temperature, speed, etc.). Having
        this in a separate method from `__init__` has the advantage that it can be used to reset those
        variables at a later stage, without having to write the same code again.

        Following this scheme, inheriting from `StateMachineDevice` also provides the possibility
        for users of the class to override the states, the transitions, the initial state and
        even the data. For states, transitions and data, dicts need to be passed to the constructor,
        for the initial state that should be a string.

        All these overrides can be used to define device setups to describe certain scenarios more easily.

        :param override_states: Dict with one entry per state. Only states defined in the state machine are allowed.
        :param override_transitions: Dict with (state, state) tuples as keys and callables as values.
        :param override_initial_state: The initial state.
        :param override_initial_data: A dict that contains data members that should be overwritten on construction.
        """
        super(StateMachineDevice, self).__init__()

        self._initialize_data()
        self._override_data(override_initial_data)

        state_handlers = self._get_final_state_handlers(override_states)
        initial = self._get_initial_state(
        ) if override_initial_state is None else override_initial_state

        if not initial in state_handlers:
            raise RuntimeError(
                'Initial state \'{}\' is not a valid state.'.format(initial))

        self._csm = StateMachine(
            {
                'initial':
                initial,
                'states':
                state_handlers,
                'transitions':
                self._get_final_transition_handlers(override_transitions)
            },
            context=self)

        self.add_processor(self._csm)
key2 = State('k2', 'keyboard key 2 pressed')

# Events
door_closed = Event('D1CL', 'Door closed')
key_one_pressed = Event('KEY1', 'Key 1 pressed')
key_two_pressed = Event('KEY2', 'Key 2 pressed')
open_batcave = Event('OPEN', 'Open batcave')

# Transitions
idle.add_transition(door_closed, active)
active.add_transition(key_one_pressed, key1)
key1.add_transition(key_two_pressed, key2)
key2.add_action(open_batcave)
key2.add_transition(open_batcave, idle)

sm = StateMachine(idle)

print('All states:', ', '.join([_.name for _ in sm.all_states()]))

bus = NetworkBus()
bus.subscribe(sm)
bus.send('D1CL')
bus.send('KEY1')
bus.send('KEY2')






Exemple #8
0
 def state_machine(self):
     return StateMachine(self.initial_state)