python simple finite state machine and logger
Doing another exercise from LMPTHW, and I'm enjoying it.
Only broke into Maximum recursion depth once so far.
Also I found this good article on logger, and I am really going to start using it from now on. Just yeah. It's not much work at all to put it in there.
---logger article: https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/
So a picture of what my plan was going in:
And a picture of the code results in Command Prompt ( Bash ):
color codes link : http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#16-colors
And I'm not sure I can explain well enough yet, but basically you're making a 'machine' that transitions to a predetermined amount of settings -- states.
In my code, it's the class's functions [ FSM_OFF, FSM_GO, FSM_GREEN, FSM_YELLOW, FSM_RED, FSM_BLINKING_RED, FSM_ERROR]
And the list of triggers/instructions to change the state are determined in each of those states. **FSM_BLINKING_RED is still in progress, was trying to work out a way to tell it to loop a 'blink' event in the FSM_RED like a real traffic light would. Which I can make happen, but without some kind of timer, it will just max out my recursion **
The DEBUG and De_Bug don't really do anything special yet, but they're there for future experiments.
List of instructions you can give it:
['DEBUG', 'ON', 'OFF', 'turn', 'blink']
Check it out.... My python Finite State Machine experiment.
*********************************************************************
#!usr/bin/python
import logging
import sys
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TrafficLights(object):
def __init__(self, De_Bug):
self.De_Bug = De_Bug
def FSM_OFF(self):
sys.exit()
def FSM_GO(self, event):
if event == 'ON':
return self.FSM_GREEN
elif event == 'DEBUG':
#self.FSM_BLINKING_RED(event)
return self.FSM_ERROR
elif event == 'OFF':
return self.FSM_ERROR('OFF')
def FSM_GREEN(self, event):
# green does not have a blinking mode, so it goes to ERROR
# if it recieves anything but 'turn'
green = "\u001b[32;1m"
reset = "\u001b[0m"
light = green + "GO GO GO" + reset
print(light)
if event == 'turn':
return self.FSM_YELLOW
else:
current = "FSM_GREEN"
return self.FSM_ERROR(event, current)
def FSM_YELLOW(self, event):
yellow ="\u001b[33;1m"
reset = "\u001b[0m"
light = yellow + "CAUTION" + reset
print(light)
if event == 'turn':
return self.FSM_RED
elif event == 'blink':
print("blinking yellow")
return self.FSM_YELLOW
else:
current = "FSM_YELLOW"
return self.FSM_ERROR(event, current)
def FSM_RED(self, event):
red = "\u001b[31;1m"
reset = "\u001b[0m"
light = red + "STOP" + reset
print(light)
if event == 'turn':
return self.FSM_GREEN
elif event == 'blink':
return self.FSM_RED
else:
current = "FSM_RED"
return self.FSM_ERROR(event, current)
def FSM_BLINKING_RED(self, event):
#blinking = "\e[31m Blink \e[5m Error \e[0m"
print("Blinking red light")
if event == "DEBUG":
# how would they test the lights without
# having them on?
print("DEBUG mode is on")
return self.FSM_ERROR(event)
else:
return self.FSM_ERROR(event)
def FSM_ERROR(self, event, current=None):
if event != 'OFF':
logger.info("ERROR was thrown in FiniteStateTrafficLight")
logger.info("event = %s", event)
if current != None and type(current) == str:
logger.info("Error occured in: %s", current)
self.FSM_OFF()
else:
logger.info("Prompted to turn off by: %s", event)
self.FSM_OFF()
class TrafficLightHandler(object):
def EVENT_HANDLER(self, instructions):
# instructions will need to be a list of commands
# Commands available : ['ON', 'DEBUG', 'OFF', 'turn', 'blink' ]
# # ---- this is probably where I should put the debugging handling ---- # #
debug = False
lights = TrafficLights(debug)
event = 'ON'
state = lights.FSM_GO(event)
for instruction in instructions:
state = state(instruction)
########## run with it! It's not scissors it'll be ok #######
alist = ['turn', 'blink', 'turn', 'turn', 'turn', 'throw bug']
start = TrafficLightHandler()
start.EVENT_HANDLER(alist)
Only broke into Maximum recursion depth once so far.
Also I found this good article on logger, and I am really going to start using it from now on. Just yeah. It's not much work at all to put it in there.
---logger article: https://fangpenlin.com/posts/2012/08/26/good-logging-practice-in-python/
So a picture of what my plan was going in:
And a picture of the code results in Command Prompt ( Bash ):
color codes link : http://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#16-colors
And I'm not sure I can explain well enough yet, but basically you're making a 'machine' that transitions to a predetermined amount of settings -- states.
In my code, it's the class's functions [ FSM_OFF, FSM_GO, FSM_GREEN, FSM_YELLOW, FSM_RED, FSM_BLINKING_RED, FSM_ERROR]
And the list of triggers/instructions to change the state are determined in each of those states. **FSM_BLINKING_RED is still in progress, was trying to work out a way to tell it to loop a 'blink' event in the FSM_RED like a real traffic light would. Which I can make happen, but without some kind of timer, it will just max out my recursion **
The DEBUG and De_Bug don't really do anything special yet, but they're there for future experiments.
List of instructions you can give it:
['DEBUG', 'ON', 'OFF', 'turn', 'blink']
Check it out.... My python Finite State Machine experiment.
*********************************************************************
#!usr/bin/python
import logging
import sys
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class TrafficLights(object):
def __init__(self, De_Bug):
self.De_Bug = De_Bug
def FSM_OFF(self):
sys.exit()
def FSM_GO(self, event):
if event == 'ON':
return self.FSM_GREEN
elif event == 'DEBUG':
#self.FSM_BLINKING_RED(event)
return self.FSM_ERROR
elif event == 'OFF':
return self.FSM_ERROR('OFF')
def FSM_GREEN(self, event):
# green does not have a blinking mode, so it goes to ERROR
# if it recieves anything but 'turn'
green = "\u001b[32;1m"
reset = "\u001b[0m"
light = green + "GO GO GO" + reset
print(light)
if event == 'turn':
return self.FSM_YELLOW
else:
current = "FSM_GREEN"
return self.FSM_ERROR(event, current)
def FSM_YELLOW(self, event):
yellow ="\u001b[33;1m"
reset = "\u001b[0m"
light = yellow + "CAUTION" + reset
print(light)
if event == 'turn':
return self.FSM_RED
elif event == 'blink':
print("blinking yellow")
return self.FSM_YELLOW
else:
current = "FSM_YELLOW"
return self.FSM_ERROR(event, current)
def FSM_RED(self, event):
red = "\u001b[31;1m"
reset = "\u001b[0m"
light = red + "STOP" + reset
print(light)
if event == 'turn':
return self.FSM_GREEN
elif event == 'blink':
return self.FSM_RED
else:
current = "FSM_RED"
return self.FSM_ERROR(event, current)
def FSM_BLINKING_RED(self, event):
#blinking = "\e[31m Blink \e[5m Error \e[0m"
print("Blinking red light")
if event == "DEBUG":
# how would they test the lights without
# having them on?
print("DEBUG mode is on")
return self.FSM_ERROR(event)
else:
return self.FSM_ERROR(event)
def FSM_ERROR(self, event, current=None):
if event != 'OFF':
logger.info("ERROR was thrown in FiniteStateTrafficLight")
logger.info("event = %s", event)
if current != None and type(current) == str:
logger.info("Error occured in: %s", current)
self.FSM_OFF()
else:
logger.info("Prompted to turn off by: %s", event)
self.FSM_OFF()
class TrafficLightHandler(object):
def EVENT_HANDLER(self, instructions):
# instructions will need to be a list of commands
# Commands available : ['ON', 'DEBUG', 'OFF', 'turn', 'blink' ]
# # ---- this is probably where I should put the debugging handling ---- # #
debug = False
lights = TrafficLights(debug)
event = 'ON'
state = lights.FSM_GO(event)
for instruction in instructions:
state = state(instruction)
########## run with it! It's not scissors it'll be ok #######
alist = ['turn', 'blink', 'turn', 'turn', 'turn', 'throw bug']
start = TrafficLightHandler()
start.EVENT_HANDLER(alist)
Comments
Post a Comment