|
1
|
|
|
import asyncio, logging |
|
2
|
|
|
from asyncua import Server, ua, Node |
|
3
|
|
|
from Statemachine import FiniteStateMachine |
|
4
|
|
|
|
|
5
|
|
|
logging.basicConfig(level=logging.INFO) |
|
6
|
|
|
_logger = logging.getLogger('asyncua') |
|
7
|
|
|
|
|
8
|
|
|
if __name__ == "__main__": |
|
9
|
|
|
async def main(): |
|
10
|
|
|
server = Server() |
|
11
|
|
|
await server.init() |
|
12
|
|
|
server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/") |
|
13
|
|
|
idx = await server.register_namespace("http://examples.freeopcua.github.io") |
|
14
|
|
|
|
|
15
|
|
|
# get a instance of the FiniteStateMachine-Class def "__init__(self, server=None, parent=None, idx=None, name=None):" |
|
16
|
|
|
mystatemachine = FiniteStateMachine(server, server.nodes.objects, idx, "FiniteStateMachine") |
|
17
|
|
|
# call statemachine.install() to instantiate the statemachinetype (with or without optional nodes) |
|
18
|
|
|
await mystatemachine.install(optionals=True) |
|
19
|
|
|
|
|
20
|
|
|
# the FiniteStateMachine provides helperclasses for states and transition each class is a representation of the state- and transition-variabletype |
|
21
|
|
|
# "def __init__(self, name, id=0, node=None):" |
|
22
|
|
|
# if the state node already exist for example from xml model you can assign it here aswell as if its a substate this is importent for the change of the state |
|
23
|
|
|
state1 = mystatemachine.State("Idle", 1) |
|
24
|
|
|
# adds the state (StateType) to the statemachine childs - this is mandatory for the FiniteStateMachine! |
|
25
|
|
|
await mystatemachine.add_state(state1, state_type=ua.NodeId(2309, 0)) #this is a init state -> InitialStateType: ua.NodeId(2309, 0) |
|
26
|
|
|
state2 = mystatemachine.State("Loading", 2) |
|
27
|
|
|
await mystatemachine.add_state(state2) |
|
28
|
|
|
state3 = mystatemachine.State("Initializing", 3) |
|
29
|
|
|
await mystatemachine.add_state(state3) |
|
30
|
|
|
state4 = mystatemachine.State("Processing", 4) |
|
31
|
|
|
await mystatemachine.add_state(state4) |
|
32
|
|
|
state5 = mystatemachine.State("Finished", 5) |
|
33
|
|
|
await mystatemachine.add_state(state5) |
|
34
|
|
|
|
|
35
|
|
|
# sets the avalible states of the FiniteStateMachine |
|
36
|
|
|
# this is mandatory! |
|
37
|
|
|
await mystatemachine.set_available_states([ |
|
38
|
|
|
state1.node.nodeid, |
|
39
|
|
|
state2.node.nodeid, |
|
40
|
|
|
state3.node.nodeid, |
|
41
|
|
|
state4.node.nodeid, |
|
42
|
|
|
state5.node.nodeid |
|
43
|
|
|
]) |
|
44
|
|
|
|
|
45
|
|
|
# setup your transition helperclass |
|
46
|
|
|
# "def __init__(self, name, id=0, node=None):" |
|
47
|
|
|
# if the transition node already exist for example from xml model you can assign it here |
|
48
|
|
|
trans1 = mystatemachine.Transition("to Idle", 1) |
|
49
|
|
|
# adds the state (TransitionType) to the statemachine childs - this is optional for the FiniteStateMachine |
|
50
|
|
|
await mystatemachine.add_transition(trans1) |
|
51
|
|
|
trans2 = mystatemachine.Transition("to Loading", 2) |
|
52
|
|
|
await mystatemachine.add_transition(trans2) |
|
53
|
|
|
trans3 = mystatemachine.Transition("to Initializing", 3) |
|
54
|
|
|
await mystatemachine.add_transition(trans3) |
|
55
|
|
|
trans4 = mystatemachine.Transition("to Processing", 4) |
|
56
|
|
|
await mystatemachine.add_transition(trans4) |
|
57
|
|
|
trans5 = mystatemachine.Transition("to Finished", 5) |
|
58
|
|
|
await mystatemachine.add_transition(trans5) |
|
59
|
|
|
|
|
60
|
|
|
# this is optional for the FiniteStateMachine |
|
61
|
|
|
await mystatemachine.set_available_transitions([ |
|
62
|
|
|
trans1.node.nodeid, |
|
63
|
|
|
trans2.node.nodeid, |
|
64
|
|
|
trans3.node.nodeid, |
|
65
|
|
|
trans4.node.nodeid, |
|
66
|
|
|
trans5.node.nodeid |
|
67
|
|
|
]) |
|
68
|
|
|
|
|
69
|
|
|
# initialise the FiniteStateMachine by call change_state() with the InitialState |
|
70
|
|
|
# if the statechange should trigger an TransitionEvent the Message can be assigned here |
|
71
|
|
|
# if event_msg is None no event will be triggered |
|
72
|
|
|
await mystatemachine.change_state(state1, trans1, f"{mystatemachine._name}: Idle", 300) |
|
73
|
|
|
|
|
74
|
|
|
async with server: |
|
75
|
|
View Code Duplication |
while 1: |
|
|
|
|
|
|
76
|
|
|
await asyncio.sleep(2) |
|
77
|
|
|
await mystatemachine.change_state(state2, trans2, f"{mystatemachine._name}: Loading", 350) |
|
78
|
|
|
await asyncio.sleep(2) |
|
79
|
|
|
await mystatemachine.change_state(state3, trans3, f"{mystatemachine._name}: Initializing", 400) |
|
80
|
|
|
await asyncio.sleep(2) |
|
81
|
|
|
await mystatemachine.change_state(state4, trans4, f"{mystatemachine._name}: Processing", 600) |
|
82
|
|
|
await asyncio.sleep(2) |
|
83
|
|
|
await mystatemachine.change_state(state5, trans5, f"{mystatemachine._name}: Finished", 800) |
|
84
|
|
|
await asyncio.sleep(2) |
|
85
|
|
|
await mystatemachine.change_state(state1, trans1, f"{mystatemachine._name}: Idle", 500) |
|
86
|
|
|
|
|
87
|
|
|
asyncio.run(main()) |
|
88
|
|
|
|