#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
TODO: modul doc string
This is an example state machine following this article:
http://accu.org/index.php/journals/1548
"""
__version__ = "1.0.3.0"
__author__ = "dr0iddr0id {at} gmail [dot] com (C) 2010"
from operator import methodcaller
import symplehfsm
from symplehfsm import Structure
from symplehfsm import SympleDictHFSM
from symplehfsm import BaseHFSMTests
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
[docs]class Events(object):
dark = 0
light = 1
movement = 2
no_movement = 3
timeout = 4
# ------------------------------------------------------------------------------
[docs]class Actions(object):
[docs] def lamp_off(self):
print("lamp off")
[docs] def lamp_on(self):
print("lamp on")
[docs] def start_timer(self):
print("starting timer")
# ------------------------------------------------------------------------------
[docs]def main():
structure = Structure()
# state, parent, initial, entry, exit
structure.add_state("parent", None, False)
structure.add_state( "day", "parent", True)
structure.add_state( "night", "parent", False)
structure.add_state( "off", "night", True)
structure.add_state( "moving", "night", False)
structure.add_state( "timing", "night", False)
# handling state, event, next state, action, guard
structure.add_trans( "day", "dark", "night")
structure.add_trans( "night", "light", "day", methodcaller("lamp_off"))
structure.add_trans( "off", "movement", "moving", methodcaller("lamp_on"))
structure.add_trans("moving", "no_movement", "timing", methodcaller("start_timer"))
structure.add_trans("timing", "timeout", "off", methodcaller("lamp_off"))
structure.add_trans("timing", "movement", "moving")
actions = Actions()
sm = SympleDictHFSM(structure, actions)
sm.init(False)
# run a event sequence
sm.handle_event("dark")
sm.handle_event("movement")
sm.handle_event("no_movement")
sm.handle_event("movement")
sm.handle_event("no_movement")
sm.handle_event("timeout")
sm.handle_event("light")
sm.handle_event("dark")
if __name__ == "__main__":
main()
# ------------------------------------------------------------------------------
# class MyStateMachine(SympleDictHFSM, Events):
# # instantiate the states and tarnsitions only once for all instances of MyStateMahine
# state_day = "day"
# state_night = "night"
# state_off = "off"
# state_moving = "moving"
# state_timing = "timing"
# def __init__(self, actions):
# SympleDictHFSM.__init__(self)
# self.actions = actions
# self.init(self.state_day, self)
# def dark(self):
# f = operator.methodcaller('dark', self)
# self.handle_event(f, self)
# def light(self):
# f = operator.methodcaller('light', self)
# self.handle_event(f, self)
# def movement(self):
# f = operator.methodcaller('movement', self)
# self.handle_event(f, self)
# def no_movement(self):
# f = operator.methodcaller('no_movement', self)
# self.handle_event(f, self)
# def timeout(self):
# f = operator.methodcaller('timeout', self)
# self.handle_event(f, self)
# # ------------------------------------------------------------------------------
# class MyStateMachineTests(BaseHFSMTests):
# class AEnum(object):
# LAMPON = "lamp_on"
# LAMPOFF ="lamp_off"
# STARTTIMER = "start_timer"
# # make it read only
# AEnum.__setattr__ = None
# # -- transition tests -- #
# def setUp(self):
# self.actions = MyStateMachineTests.RecordingActions()
# self.state_machine = MyStateMachine(self.actions)
# def test_trans_day_dark(self):
# # init: s0 -> s11: s0.entry, s1.entry, s11.entry
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Day + dark -> off", START_DAY, StateMachine::Dark, "Off", 0 },
# v = self.TestVector("day + dark", MyStateMachine.state_day, self.state_machine.dark, MyStateMachine.state_off, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_day_light(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Day + light -> no change", START_DAY, StateMachine::Light, "Day", 0 },
# v = self.TestVector("day + light", MyStateMachine.state_day, self.state_machine.light, MyStateMachine.state_day, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_day_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Day + movement -> no change", START_DAY, StateMachine::Movement, "Day", 0 },
# v = self.TestVector("day + movement", MyStateMachine.state_day, self.state_machine.movement, MyStateMachine.state_day, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_day_no_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Day + no_movement -> no change", START_DAY, StateMachine::NoMovement, "Day", 0 },
# v = self.TestVector("day + nomovement", MyStateMachine.state_day, self.state_machine.no_movement, MyStateMachine.state_day, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_day_timeout(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Day + timeout -> no change", START_DAY, StateMachine::Timeout, "Day", 0 },
# v = self.TestVector("day + timeout", MyStateMachine.state_day, self.state_machine.timeout, MyStateMachine.state_day, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_off_dark(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Off + dark -> no change", START_OFF, StateMachine::Dark, "Off", 0 },
# v = self.TestVector("off + dark", MyStateMachine.state_off, self.state_machine.dark, MyStateMachine.state_off, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_off_light(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Off + light -> lamp off; day", START_OFF, StateMachine::Light, "Day", &L_Off },
# v = self.TestVector("off + light -> lamp off; day", MyStateMachine.state_off, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_off_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Off + movement -> lamp on; moving", START_OFF, StateMachine::Movement, "Moving", &L_On },
# v = self.TestVector("off + movement -> lamp on; moving", MyStateMachine.state_off, self.state_machine.movement, MyStateMachine.state_moving, [self.AEnum.LAMPON])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_off_no_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Off + no_movement -> no change", START_OFF, StateMachine::NoMovement, "Off", 0 },
# v = self.TestVector("off + nomovement", MyStateMachine.state_off, self.state_machine.no_movement, MyStateMachine.state_off, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_off_timeout(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Off + timeout -> no change", START_OFF, StateMachine::Timeout, "Off", 0 },
# v = self.TestVector("off + timeout", MyStateMachine.state_off, self.state_machine.timeout, MyStateMachine.state_off, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_moving_dark(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Moving + dark -> no change", START_MOVING, StateMachine::Dark, "Moving", 0 },
# v = self.TestVector("moving + dark", MyStateMachine.state_moving, self.state_machine.dark, MyStateMachine.state_moving, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_moving_light(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Moving + light -> lamp off; day", START_MOVING, StateMachine::Light, "Day", &L_Off },
# v = self.TestVector("moving + light -> lamp off, day", MyStateMachine.state_moving, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_moving_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Moving + movement -> no change", START_MOVING, StateMachine::Movement, "Moving", 0 },
# v = self.TestVector("moving + movement", MyStateMachine.state_moving, self.state_machine.movement, MyStateMachine.state_moving, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_moving_no_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Moving + no_movement -> timing", START_MOVING, StateMachine::NoMovement, "Timing", &Start_T },
# v = self.TestVector("moving + no_movement -> timing", MyStateMachine.state_moving, self.state_machine.no_movement, MyStateMachine.state_timing, [self.AEnum.STARTTIMER])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_moving_timout(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Moving + timeout -> no change", START_MOVING, StateMachine::Timeout, "Moving", 0 },
# v = self.TestVector("moving + timeout", MyStateMachine.state_moving, self.state_machine.timeout, MyStateMachine.state_moving, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_timing_dark(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Timing + dark -> no change", START_TIMING, StateMachine::Dark, "Timing", 0 },
# v = self.TestVector("timing + dark", MyStateMachine.state_timing, self.state_machine.dark, MyStateMachine.state_timing, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_timing_light(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Timing + light -> lamp off; day", START_TIMING, StateMachine::Light, "Day", &L_Off },
# v = self.TestVector("timing + light", MyStateMachine.state_timing, self.state_machine.light, MyStateMachine.state_day, [self.AEnum.LAMPOFF])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_timing_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Timing + movement -> no change", START_TIMING, StateMachine::Movement, "Timing", 0 },
# v = self.TestVector("timing + movement", MyStateMachine.state_timing, self.state_machine.movement, MyStateMachine.state_moving, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_timing_no_movement(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Timing + no_movement -> no change", START_TIMING, StateMachine::NoMovement, "Timing", 0 },
# v = self.TestVector("timing + no movement ", MyStateMachine.state_timing, self.state_machine.no_movement, MyStateMachine.state_timing, [])
# self.prove_one_transition(self.state_machine, self.actions, v)
# def test_trans_timing_timout(self):
# # title, starting_state, event_func, expected_state, expected_actions):
# # { "Timing + timeout -> lamp off; off", START_TIMING, StateMachine::Timeout, "Off", &L_Off },
# v = self.TestVector("timing + timeout -> lamp off: off", MyStateMachine.state_timing, self.state_machine.timeout, MyStateMachine.state_off, [self.AEnum.LAMPOFF])
# self.prove_one_transition(self.state_machine, self.actions, v)
# # ------------------------------------------------------------------------------
# def test_sequence(self):
# self.prove_transition_sequence("rout1",
# MyStateMachine.state_day,
# [self.state_machine.dark, \
# self.state_machine.movement, \
# self.state_machine.no_movement, \
# self.state_machine.movement, \
# self.state_machine.no_movement, \
# self.state_machine.timeout],
# MyStateMachine.state_off,
# [self.AEnum.LAMPON, self.AEnum.STARTTIMER, self.AEnum.STARTTIMER, self.AEnum.LAMPOFF],
# self.state_machine,
# self.actions)
# # ------------------------------------------------------------------------------