My question is, using the yml file, how do I write in state outputs?
There is no dedicated output slot for states but you can use transitions
to trigger certain actions when a state is entered or left.
Actions can be done in callbacks. Those actions need to be implemented in the model. If you want to do most things via configurations you can customize Machine
and the used State
class. For instance, you could create a custom LEDState
and assign a value array called led_states
to it where each value represents a LED state. The array is applied to the LEDs in the after_state_change
callback of the Model that is called update_leds
:
from transitions import Machine, State
class LEDState(State):
ALL_OFF = [False] * 2 # number of LEDs
def __init__(self, name, on_enter=None, on_exit=None,
ignore_invalid_triggers=None, led_states=None):
# call the base class constructor without 'led_states'...
super().__init__(name, on_enter, on_exit, ignore_invalid_triggers)
# ... and assign its value to a custom property
# when 'led_states' is not passed, we assign the default
# setting 'ALL_OFF'
self.led_states = led_states if led_states is not None else self.ALL_OFF
# create a custom machine that uses 'LEDState'
# 'LEDMachine' will pass all parameters in the configuration
# dictionary to the constructor of 'LEDState'.
class LEDMachine(Machine):
state_cls = LEDState
class LEDModel:
def __init__(self, config):
self.machine = LEDMachine(model=self, **config, after_state_change='update_leds')
def update_leds(self):
print(f"---New State {self.state}---")
for idx, led in enumerate(self.machine.get_state(self.state).led_states):
print(f"Set LED {idx} {'ON' if led else 'OFF'}.")
# using a dictionary here instead of YAML
# but the process is the same
config = {
'name': 'LEDModel',
'initial': 'Off',
'states': [
{'name': 'Off'},
{'name': 'A', 'led_states': [True, False]},
{'name': 'B', 'led_states': [False, True]},
{'name': 'C', 'led_states': [True, True]}
]
}
model = LEDModel(config)
model.to_A()
# ---New State A---
# Set LED 0 ON.
# Set LED 1 OFF.
model.to_C()
# ---New State C---
# Set LED 0 ON.
# Set LED 1 ON.
This is just one way how this could be done. You could also just pass an array with indexes representing all LEDs that should be ON
. We'd switch off all LEDs when exiting a state with before_state_change
ALL_OFF = []
# ...
self.machine = LEDMachine(model=self, **config, before_state_change='reset_leds', after_state_change='set_lets')
# ...
def reset_leds(self):
for led_idx in range(num_leds):
print(f"Set {led_idx} 'OFF'.")
def set_lets(self):
for led_idx in self.machine.get_state(self.state).led_states:
print(f"Set LED {led_idx} 'ON'.")
# ...
{'name': 'A', 'led_states': [0]},
{'name': 'B', 'led_states': [1]},
{'name': 'C', 'led_states': [0, 1]}