-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple instances of the statemachine are not properly separated #330
Comments
Hi @Rosi2143 , how are you? Nice use case, let me know when you have something working, I'll be glad to know. Maybe you can post somewhere so I can learn about it. I have an ESP32 and like to learn more about home automation. I've tried your example, and actually, I've found two minor "gotchas" on the tests, so I think everything is fine with the library regarding this "isolation" concern. Machine extended state should be initialized at
|
Ow... extra hint if it helps... Given that I've implemented a "dynamic dispatch", the library also works directly with attributes and properties and can read from them directly as from statemachine import State
from statemachine import StateMachine
class TestStateMachine(StateMachine):
# States
st_1 = State("One", initial=True)
st_2 = State("Two")
st_3 = State("Three")
# Transitions
tr_change = (
st_1.to(st_1, cond="one")
| st_1.to(st_2, cond="two")
| st_1.to(st_3, cond="three")
| st_2.to(st_1, cond="one")
| st_2.to(st_2, cond="two")
| st_2.to(st_3, cond="three")
)
def __init__(self, name="unnamed"):
# variables
self.sm_name = name
self.one = False
self.two = True
self.three = True
super().__init__() |
Closing for now. If you have any other issue please let me know. |
I am not sure this was solved, if I create multiple instances of a state machine -- the newest statemachines class variables will serve as the single point of truth for all state machines. from statemachine import State
from statemachine import StateMachine
class TestStateMachine(StateMachine):
# States
st_1 = State("One", initial=True)
st_2 = State("Two")
st_3 = State("Three")
# Transitions
tr_change = (
st_1.to(st_2, cond="two")
| st_2.to(st_3, cond="three")
| st_3.to(st_1, cond="one")
)
def __init__(self, name="unnamed"):
# variables
self.sm_name = name
self.one = False
self.two = True
self.three = False
super().__init__()
s1 = TestStateMachine()
s2 = TestStateMachine()
s1.current_state
State('One', id='st_1', value='st_1', initial=True, final=False)
s2.current_state
State('One', id='st_1', value='st_1', initial=True, final=False)
s1.tr_change()
s1.current_state
State('Two', id='st_2', value='st_2', initial=False, final=False)
s2.current_state
State('One', id='st_1', value='st_1', initial=True, final=False)
s2.two = False
s2
TestStateMachine(model=Model(state=st_1), state_field='state', current_state='st_1')
s2.tr_change()
statemachine.exceptions.TransitionNotAllowed: Can't tr_change when in One.
s1.three = True
s1.three
True
s2.three
False
s1.tr_change() # this shouldn't throw an error because s1.three is now true
statemachine.exceptions.TransitionNotAllowed: Can't tr_change when in Two.
s2.three = True # When I change the variable on s2, it then allows me to transition the state of s1
s1.tr_change()
s1.current_state
State('Two', id='st_2', value='st_2', initial=False, final=False) |
Hi @fgmacedo, sorry for not replying earlier but I was on vacation. I've seen that you already merged a patch. Thanks, I will try it out today. Also I really like the idea of using boolean attributes/properties directly. I will raise a MR again with some extention of the documentation for this. Great to see that you are so active and respond very quickly. |
I just re-run my test with your latest version (6dbc55c) and it works like a charm. Thanks. |
Another "feature" that's not well documented on the callbacks is that you can either pass a string or method, or even a list of strings or methods. This is valid for all callbacks:
def should_have_name(machine):
"Any method will work"
return machine.sm_name != "unnamed"
class TestStateMachine(StateMachine):
# States
st_1 = State("One", initial=True)
st_2 = State("Two")
st_3 = State("Three")
# Transitions
tr_change = (
st_1.to(st_2, cond=["two", should_have_name])
| st_2.to(st_3, cond=["three", "prepared"])
| st_3.to(st_1, cond="one")
)
def __init__(self, name="unnamed"):
# variables
self.sm_name = name
self.one = False
self.two = True
self.three = False
self.prepared = False
super().__init__() |
Description
I created a statemachine and instantiated it multiple times. Scenario is the control of my 14 thermostats for my home automation.
What I Did
Here is the reduced "minimal" setup to show the error.
The failing test is
the statemachine remains in state "Two"
Output:
Hint:
when I change
to change the LAST StateMachine in my list it works :-(
I can reproduce the same error with index sm_list[1] the same way,
Assumed reason:
When I debug and set the breakpoints into the functions e.g.
cond_one_is_active
the instance of TestStateMachine is always "3".The text was updated successfully, but these errors were encountered: