1

我正在使用 PyTransitions 生成一个简单的 FSM,并使用 yml 文件对其进行配置。一个例子可能是这样的:

initial: A
states:
  - A
  - B
  - C
transitions:
  - {trigger: "AtoC", source: "A", dest: "C"}
  - {trigger: "CtoB", source: "C", dest: "B"}

我的问题是,使用 yml 文件,我如何写入状态输出?例如,在状态 A 打开 LED 1,状态 B 打开 LED2,状态 C 打开 LED1 和 2。我在 PyTransitions 页面中找不到任何文档。

4

1 回答 1

1

我的问题是,使用 yml 文件,我如何写入状态输出?

状态没有专用的输出槽,但您可以transitions在进入或离开状态时触发某些操作。动作可以在回调中完成。这些动作需要在模型中实现。如果你想通过配置做大部分事情,你可以自定义Machine和使用的State类。例如,您可以创建一个自定义LEDState并分配一个调用led_states它的值数组,其中每个值代表一个 LED 状态。该数组应用于after_state_change调用的模型回调中的 LED 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.

这只是如何做到这一点的一种方式。您也可以只传递一个带有索引的数组,该索引表示应该是的所有 LED ON。退出状态时,我们会关闭所有 LEDbefore_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]}

于 2021-10-04T16:47:23.487 回答