Passed
Pull Request — master (#348)
by
unknown
02:22
created

ProgramStateMachineTypeClass.Resume()   A

Complexity

Conditions 2

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
'''
2
https://reference.opcfoundation.org/v104/Core/docs/Part10/
3
https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.1/
4
5
Basic statemachines described in OPC UA Spec.:
6
StateMachineType
7
FiniteStateMachineType
8
ExclusiveLimitStateMachineType
9
FileTransferStateMachineType
10
ProgramStateMachineType
11
ShelvedStateMachineType
12
13
Relevant information:
14
Overview - https://reference.opcfoundation.org/v104/Core/docs/Part10/5.2.3/#5.2.3.1
15
States - https://reference.opcfoundation.org/v104/Core/docs/Part10/5.2.3/#5.2.3.2
16
Transitions - https://reference.opcfoundation.org/v104/Core/docs/Part10/5.2.3/#5.2.3.3
17
Events - https://reference.opcfoundation.org/v104/Core/docs/Part10/5.2.5/
18
'''
19
import asyncio, logging
20
21
#FIXME 
22
# -change to relativ imports!
23
# -remove unused imports
24
from asyncua import Server, ua, Node
25
from asyncua.common.instantiate_util import instantiate
26
27
class StateMachineTypeClass(object):
28
    '''
29
    Implementation of an StateMachineType (most basic type)
30
    '''
31
    def __init__(self, server=None, parent=None, idx=None, name=None):
32
        if not server: raise ValueError #FIXME change to check instance type
33
        if not parent: raise ValueError #FIXME change to check instance type
34
        if idx == None:
35
            idx = parent.nodeid.NamespaceIndex
36
        if name == None:
37
            name = "StateMachine"
38
        self._server = server
39
        self._parent = parent
40
        self._state_machine_node = None
41
        self._state_machine_type = ua.NodeId(2299, 0)
42
        self._name = name
43
        self._idx = idx
44
        self._optionals = False
45
        self._current_state_node = None
46
        self._current_state_id_node = None
47
        self._last_transition_node = None
48
        self._last_transition_id_node = None
49
50
    async def install(self, optionals=False):
51
        '''
52
        setup adressspace
53
        '''
54
        self._optionals = optionals
55
        self._state_machine_node = await self._parent.add_object(
56
            self._idx, 
57
            self._name, 
58
            objecttype=self._state_machine_type, 
59
            instantiate_optional=optionals
60
            )
61
        await self.init(self._state_machine_node)
62
    
63
    async def init(self, statemachine):
64
        '''
65
        initialize subnodes
66
        '''
67
        #check for childrens typdefinitions which matches statemachine
68
        self._current_state_node = await statemachine.get_child(["CurrentState"])
69
        self._current_state_id_node = await statemachine.get_child(["CurrentState","Id"])
70
        if self._optionals:
71
            self._last_transition_node = await statemachine.get_child(["LastTransition"])
72
            self._last_transition_id_node = await statemachine.get_child(["LastTransition","Id"])
73
74
        #FIXME initialise values
75
        '''
76
        maybe its smart to check parents children for a initial state instance (InitialStateType) 
77
        and initialize it with its id but if no state instance is provided ... i will log a 
78
        warning
79
        '''
80
81
    async def change_state(self, state_name, state_node, transition_name=None, transition_node=None):
82
        '''
83
        method to change the state of the statemachine
84
        state_name: ua.LocalizedText()
85
        state: ua.NodeId() <- StateType node
86
        transition_name: ua.LocalizedText()
87
        transition: ua.NodeId() <- TransitionType node
88
        '''
89
        #FIXME check StateType exist
90
        #FIXME check TransitionTypeType exist
91
        await self.write_state(state_name, state_node)
92
        if self._optionals and transition_name and transition_node:
93
            await self.write_transition(transition_name, transition_node)
94
        #FIXME trigger TransitionEventType
95
96
    async def write_state(self, state_name, state_node):
97
        #FIXME check types/class
98
        await self._current_state_node.write_value(state_name)
99
        await self._current_state_id_node.write_value(state_node)
100
101
    async def write_transition(self, transition_name, transition_node):
102
        #FIXME check types/class
103
        await self._last_transition_node.write_value(transition_name)
104
        await self._last_transition_id_node.write_value(transition_node)
105
    
106
    async def add_state(self, name, state_type=ua.NodeId(2307, 0), optionals=False):
107
        '''
108
        initial state -> ua.NodeId(2309, 0)
109
        state -> ua.NodeId(2307, 0)
110
        '''
111
        #FIXME check types/class
112
        return await self._state_machine_node.add_object(
113
            self._idx, 
114
            name, 
115
            objecttype=state_type, 
116
            instantiate_optional=optionals
117
            )
118
119
    async def add_transition(self, name, transition_type=ua.NodeId(2310, 0), optionals=False):
120
        #FIXME check types/class
121
        return await self._state_machine_node.add_object(
122
            self._idx, 
123
            name, 
124
            objecttype=transition_type, 
125
            instantiate_optional=optionals
126
            )
127
128
    # async def remove(self):
129
    #     #FIXME
130
    #     raise NotImplementedError
131
132
    # async def add_substate(self):
133
    #     #FIXME
134
    #     raise NotImplementedError
135
136
    # async def add_subtransition(self):
137
    #     #FIXME
138
    #     raise NotImplementedError
139
140
class FiniteStateMachineTypeClass(StateMachineTypeClass):
141
    '''
142
    Implementation of an FiniteStateMachineType a little more advanced than the basic one
143
    if you need to know the avalible states and transition from clientside
144
    '''
145
    def __init__(self, server=None, parent=None, idx=None, name=None):
146
        super().__init__(server, parent, idx, name)
147
        if name == None:
148
            name = "FiniteStateMachine"
149
        self._state_machine_type = ua.NodeId(2771, 0)
150
        self._avalible_states_node = None
151
        self._avalible_transitions_node = None
152
153
    async def install(self, avalible_states, avalible_transitions, optionals=False):
154
        '''
155
        setup adressspace and initialize 
156
        '''
157
        self._optionals = optionals
158
        self._state_machine_node = await self._parent.add_object(
159
            self._idx, 
160
            self._name, 
161
            objecttype=self._state_machine_type, 
162
            instantiate_optional=optionals
163
            )
164
        #FIXME get children and map children
165
        await self.set_avalible_states(avalible_states)
166
        await self.set_avalible_transitions(avalible_transitions)
167
168
    async def set_avalible_states(self, states):
169
        #check if its list
170
        await self._avalible_states_node.write_value(states, varianttype=ua.VariantType.NodeId)
171
172
    async def set_avalible_transitions(self, transitions):
173
        await self._avalible_transitions_node.write_value(transitions, varianttype=ua.VariantType.NodeId)
174
175
class ExclusiveLimitStateMachineTypeClass(FiniteStateMachineTypeClass):
176
    '''
177
    NOT IMPLEMENTED "ExclusiveLimitStateMachineType"
178
    '''
179
    def __init__(self, server=None, parent=None, idx=None, name=None):
180
        super().__init__(server, parent, idx, name)
181
        if name == None:
182
            name = "ExclusiveLimitStateMachine"
183
        self._state_machine_type = ua.NodeId(9318, 0)
184
        raise NotImplementedError
185
186
class FileTransferStateMachineTypeClass(FiniteStateMachineTypeClass):
187
    '''
188
    NOT IMPLEMENTED "FileTransferStateMachineType"
189
    '''
190
    def __init__(self, server=None, parent=None, idx=None, name=None):
191
        super().__init__(server, parent, idx, name)
192
        if name == None:
193
            name = "FileTransferStateMachine"
194
        self._state_machine_type = ua.NodeId(15803, 0)
195
        raise NotImplementedError
196
197
class ProgramStateMachineTypeClass(FiniteStateMachineTypeClass):
198
    '''
199
    https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.3/
200
    Implementation of an ProgramStateMachine its quite a complex statemachine with the 
201
    optional possibility to make the statchange from clientside via opcua-methods
202
    '''
203
    def __init__(self, server=None, parent=None, idx=None, name=None):
204
        super().__init__(server, parent, idx, name)
205
        if name == None:
206
            name = "ProgramStateMachine"
207
        self._state_machine_type = ua.NodeId(2391, 0)
208
209
        # 5.2.3.2 ProgramStateMachineType states
210
        self._ready_state_node = None #State node
211
        self._halted_state_node = None #State node
212
        self._running_state_node = None #State node
213
        self._suspended_state_node = None #State node
214
215
        # 5.2.3.3 ProgramStateMachineType transitions
216
        self._halted_to_ready_node = None #Transition node
217
        self._ready_to_running_node = None #Transition node
218
        self._running_to_halted_node = None #Transition node
219
        self._running_to_ready_node = None #Transition node
220
        self._running_to_suspended_node = None #Transition node
221
        self._suspended_to_running_node = None #Transition node
222
        self._suspended_to_halted_node = None #Transition node
223
        self._suspended_to_ready_node = None #Transition node
224
        self._ready_to_halted_node = None #Transition node
225
226
        # 5.2.3.2 ProgramStateMachineType states
227
        self._halted_state_id_node = None #State property (StateNumber value 11)
228
        self._ready_state_id_node = None #State property (StateNumber value 12)
229
        self._running_state_id_node = None #State property (StateNumber value 13)
230
        self._suspended_state_id_node = None #State property (StateNumber value 14)
231
232
        # 5.2.3.3 ProgramStateMachineType transitions
233
        self._halted_to_ready_id_node = None #Transition property (TransitionNumber value 1)
234
        self._ready_to_running_id_node = None #Transition property (TransitionNumber value 2)
235
        self._running_to_halted_id_node = None #Transition property (TransitionNumber value 3)
236
        self._running_to_ready_id_node = None #Transition property (TransitionNumber value 4)
237
        self._running_to_suspended_id_node = None #Transition property (TransitionNumber value 5)
238
        self._suspended_to_running_id_node = None #Transition property (TransitionNumber value 6)
239
        self._suspended_to_halted_id_node = None #Transition property (TransitionNumber value 7)
240
        self._suspended_to_ready_id_node = None #Transition property (TransitionNumber value 8)
241
        self._ready_to_halted_id_node = None #Transition property (TransitionNumber value 9)
242
243
        # 4.2.7 Program Control Methods (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.7/)
244
        self._halt_method_node = None #uamethod node
245
        self._reset_method_node = None #uamethod node
246
        self._resume_method_node = None #uamethod node
247
        self._start_method_node = None #uamethod node
248
        self._suspend_method_node = None #uamethod node
249
250
        #can be overwritten if you want a different language
251
        self.localizedtext_ready = ua.LocalizedText("Ready", "en-US")
252
        self.localizedtext_running = ua.LocalizedText("Running", "en-US")
253
        self.localizedtext_halted = ua.LocalizedText("Halted", "en-US")
254
        self.localizedtext_suspended= ua.LocalizedText("Suspended", "en-US")
255
        self.localizedtext_halted_to_ready = ua.LocalizedText("HaltedToReady", "en-US")
256
        self.localizedtext_ready_to_running = ua.LocalizedText("ReadyToRunning", "en-US")
257
        self.localizedtext_running_to_halted = ua.LocalizedText("RunningToHalted", "en-US")
258
        self.localizedtext_running_to_ready = ua.LocalizedText("RunningToReady", "en-US")
259
        self.localizedtext_running_to_suspended = ua.LocalizedText("RunningToSuspended", "en-US")
260
        self.localizedtext_suspended_to_running = ua.LocalizedText("SuspendedToRunning", "en-US")
261
        self.localizedtext_suspended_to_halted = ua.LocalizedText("SuspendedToHalted", "en-US")
262
        self.localizedtext_suspended_to_ready = ua.LocalizedText("SuspendedToReady", "en-US")
263
        self.localizedtext_ready_to_halted = ua.LocalizedText("ReadyToHalted", "en-US")
264
265
    async def install(self, optionals=False):
266
        '''
267
        setup adressspace and initialize 
268
        '''
269
        self._optionals = optionals
270
        self._state_machine_node = await self._parent.add_object(
271
            self._idx, 
272
            self._name, 
273
            objecttype=self._state_machine_type, 
274
            instantiate_optional=optionals
275
            )
276
        #FIXME get children and map children
277
278
    #Transition
279
    async def HaltedToReady(self):
280
        await self._current_state.write_value(
281
            self.localizedtext_ready,
282
            varianttype=ua.VariantType.LocalizedText
283
            ) 
284
        await self._current_state_id.write_value(
285
            self._ready_state.nodeid, 
286
            varianttype=ua.VariantType.NodeId
287
            )
288
        await self._last_transition.write_value(
289
            self.localizedtext_halted_to_ready,
290
            varianttype=ua.VariantType.LocalizedText
291
            ) 
292
        await self._last_transition_id.write_value(
293
            self._halted_to_ready.nodeid,
294
            varianttype=ua.VariantType.NodeId
295
            )
296
        #FIXME 
297
        # trigger ProgramTransitionEventType and 
298
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
299
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
300
301
    #Transition
302
    async def ReadyToRunning(self):
303
        await self._current_state.write_value(
304
            self.localizedtext_running,
305
            varianttype=ua.VariantType.LocalizedText
306
            ) 
307
        await self._current_state_id.write_value(
308
            self._running_state.nodeid, 
309
            varianttype=ua.VariantType.NodeId
310
            )
311
        await self._last_transition.write_value(
312
            self.localizedtext_ready_to_running,
313
            varianttype=ua.VariantType.LocalizedText
314
            ) 
315
        await self._last_transition_id.write_value(
316
            self._ready_to_running.nodeid, 
317
            varianttype=ua.VariantType.NodeId
318
            )
319
        #FIXME 
320
        # trigger ProgramTransitionEventType and 
321
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
322
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
323
324
    #Transition
325
    async def RunningToHalted(self):
326
        await self._current_state.write_value(
327
            self.localizedtext_halted,
328
            varianttype=ua.VariantType.LocalizedText
329
            ) 
330
        await self._current_state_id.write_value(
331
            self._halted_state.nodeid, 
332
            varianttype=ua.VariantType.NodeId
333
            )
334
        await self._last_transition.write_value(
335
            self.localizedtext_running_to_halted,
336
            varianttype=ua.VariantType.LocalizedText
337
            ) 
338
        await self._last_transition_id.write_value(
339
            self._running_to_halted.nodeid, 
340
            varianttype=ua.VariantType.NodeId
341
            )
342
        #FIXME 
343
        # trigger ProgramTransitionEventType and 
344
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
345
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
346
347
    #Transition
348
    async def RunningToReady(self):
349
        await self._current_state.write_value(
350
            self.localizedtext_ready,
351
            varianttype=ua.VariantType.LocalizedText
352
            ) 
353
        await self._current_state_id.write_value(
354
            self._ready_state.nodeid, 
355
            varianttype=ua.VariantType.NodeId
356
            )
357
        await self._last_transition.write_value(
358
            self.localizedtext_running_to_ready,
359
            varianttype=ua.VariantType.LocalizedText
360
            ) 
361
        await self._last_transition_id.write_value(
362
            self._running_to_ready.nodeid, 
363
            varianttype=ua.VariantType.NodeId
364
            )
365
        #FIXME 
366
        # trigger ProgramTransitionEventType and 
367
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
368
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
369
370
    #Transition
371
    async def RunningToSuspended(self):
372
        await self._current_state.write_value(
373
            self.localizedtext_suspended,
374
            varianttype=ua.VariantType.LocalizedText
375
            ) 
376
        await self._current_state_id.write_value(
377
            self._suspended_state.nodeid, 
378
            varianttype=ua.VariantType.NodeId
379
            )
380
        await self._last_transition.write_value(
381
            self.localizedtext_running_to_suspended,
382
            varianttype=ua.VariantType.LocalizedText
383
            ) 
384
        await self._last_transition_id.write_value(
385
            self._running_to_suspended.nodeid, 
386
            varianttype=ua.VariantType.NodeId
387
            )
388
        #FIXME 
389
        # trigger ProgramTransitionEventType and 
390
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
391
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
392
393
    #Transition 
394
    async def SuspendedToRunning(self):
395
        await self._current_state.write_value(
396
            self.localizedtext_running,
397
            varianttype=ua.VariantType.LocalizedText
398
            ) 
399
        await self._current_state_id.write_value(
400
            self._running_state.nodeid, 
401
            varianttype=ua.VariantType.NodeId
402
            )
403
        await self._last_transition.write_value(
404
            self.localizedtext_suspended_to_running,
405
            varianttype=ua.VariantType.LocalizedText
406
            )
407
        await self._last_transition_id.write_value(
408
            self._suspended_to_running.nodeid, 
409
            varianttype=ua.VariantType.NodeId
410
            )
411
        #FIXME 
412
        # trigger ProgramTransitionEventType and 
413
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
414
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
415
416
    #Transition
417
    async def SuspendedToHalted(self):
418
        await self._current_state.write_value(
419
            self.localizedtext_halted,
420
            varianttype=ua.VariantType.LocalizedText
421
            ) 
422
        await self._current_state_id.write_value(
423
            self._halted_state.nodeid, 
424
            varianttype=ua.VariantType.NodeId
425
            )
426
        await self._last_transition.write_value(
427
            self.localizedtext_suspended_to_halted,
428
            varianttype=ua.VariantType.LocalizedText
429
            ) 
430
        await self._last_transition_id.write_value(
431
            self._suspended_to_halted.nodeid, 
432
            varianttype=ua.VariantType.NodeId
433
            )
434
        #FIXME 
435
        # trigger ProgramTransitionEventType and 
436
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
437
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
438
439
    #Transition
440
    async def SuspendedToReady(self):
441
        await self._current_state.write_value(
442
            self.localizedtext_ready,
443
            varianttype=ua.VariantType.LocalizedText
444
            ) 
445
        await self._current_state_id.write_value(
446
            self._ready_state.nodeid, 
447
            varianttype=ua.VariantType.NodeId
448
            )
449
        await self._last_transition.write_value(
450
            self.localizedtext_suspended_to_ready,
451
            varianttype=ua.VariantType.LocalizedText
452
            ) 
453
        await self._last_transition_id.write_value(
454
            self._suspended_to_ready.nodeid, 
455
            varianttype=ua.VariantType.NodeId
456
            )
457
        #FIXME 
458
        # trigger ProgramTransitionEventType and 
459
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
460
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
461
462
    #Transition 
463
    async def ReadyToHalted(self):
464
        await self._current_state.write_value(
465
            self.localizedtext_halted,
466
            varianttype=ua.VariantType.LocalizedText
467
            ) 
468
        await self._current_state_id.write_value(
469
            self._halted_state.nodeid, 
470
            varianttype=ua.VariantType.NodeId
471
            )
472
        await self._last_transition.write_value(
473
            self.localizedtext_ready_to_halted,
474
            varianttype=ua.VariantType.LocalizedText
475
            ) 
476
        await self._last_transition_id.write_value(
477
            self._ready_to_halted.nodeid, 
478
            varianttype=ua.VariantType.NodeId
479
            )
480
        #FIXME 
481
        # trigger ProgramTransitionEventType and 
482
        # AuditUpdateMethodEvents/AuditProgramTransitionEventType (https://reference.opcfoundation.org/v104/Core/docs/Part10/4.2.2/)
483
        return ua.StatusCode(ua.status_codes.StatusCodes.Good)
484
485
    #method to be linked to uamethod
486
    async def Start(self):
487
        if await self._current_state.read_value() == self.localizedtext_ready:
488
            return await ReadyToRunning()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ReadyToRunning does not seem to be defined.
Loading history...
489
        else:
490
            return ua.StatusCode(ua.status_codes.StatusCodes.BadNotExecutable)
491
492
    #method to be linked to uamethod
493
    async def Suspend(self):
494
        if await self._current_state.read_value() == self.localizedtext_running:
495
            return await RunningToSuspended()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable RunningToSuspended does not seem to be defined.
Loading history...
496
        else:
497
            return ua.StatusCode(ua.status_codes.StatusCodes.BadNotExecutable)
498
499
    #method to be linked to uamethod
500
    async def Resume(self):
501
        if await self._current_state.read_value() == self.localizedtext_suspended:
502
            return await SuspendedToRunning()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable SuspendedToRunning does not seem to be defined.
Loading history...
503
        else:
504
            return ua.StatusCode(ua.status_codes.StatusCodes.BadNotExecutable)
505
506
    #method to be linked to uamethod
507
    async def Halt(self):
508
        if await self._current_state.read_value() == self.localizedtext_ready:
509
            return await ReadyToHalted()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ReadyToHalted does not seem to be defined.
Loading history...
510
        elif await self._current_state.read_value() == self.localizedtext_running:
511
            return await RunningToHalted()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable RunningToHalted does not seem to be defined.
Loading history...
512
        elif await self._current_state.read_value() == self.localizedtext_suspended:
513
            return await SuspendedToHalted()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable SuspendedToHalted does not seem to be defined.
Loading history...
514
        else:
515
            return ua.StatusCode(ua.status_codes.StatusCodes.BadNotExecutable)
516
517
    #method to be linked to uamethod
518
    async def Reset(self):
519
        if await self._current_state.read_value() == self.localizedtext_halted:
520
            return await HaltedToReady()
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable HaltedToReady does not seem to be defined.
Loading history...
521
        else:
522
            return ua.StatusCode(ua.status_codes.StatusCodes.BadNotExecutable)
523
524
class ShelvedStateMachineTypeClass(FiniteStateMachineTypeClass):
525
    '''
526
    NOT IMPLEMENTED "ShelvedStateMachineType"
527
    '''
528
    def __init__(self, server=None, parent=None, idx=None, name=None):
529
        super().__init__(server, parent, idx, name)
530
        if name == None:
531
            name = "ShelvedStateMachine"
532
        self._state_machine_type = ua.NodeId(2929, 0)
533
        raise NotImplementedError
534
535
536
537
#FIXME REMOVE BEFOR MERGE
538
#Devtest / Workbench
539
if __name__ == "__main__":
540
    async def main():
541
        logging.basicConfig(level=logging.INFO)
542
        _logger = logging.getLogger('asyncua')
543
544
        server = Server()
545
        await server.init()
546
547
        sm = StateMachineTypeClass(server, server.nodes.objects, 0, "StateMachine")
548
        await sm.install(True)
549
        await sm.add_state("Initstate", ua.NodeId(2309, 0))
550
        await sm.add_state("State1")
551
        await sm.add_state("State2")
552
        await sm.add_state("State3")
553
        await sm.add_state("State4")
554
        await sm.add_transition("Transition1")
555
        await sm.add_transition("Transition2")
556
        await sm.add_transition("Transition3")
557
        await sm.add_transition("Transition4")
558
        await sm.add_transition("Transition5")
559
        await sm.change_state(
560
            ua.LocalizedText("Test3", "en-US"), 
561
            server.get_node("ns=0;i=2253").nodeid,
562
            ua.LocalizedText("Test4", "en-US"), 
563
            server.get_node("ns=0;i=2253").nodeid
564
            )
565
566
        # fsm = FiniteStateMachineTypeClass(server, server.nodes.objects, 0, "FiniteStateMachine")
567
        # await fsm.install(True)
568
        # pfsm = ProgramStateMachineTypeClass(server, server.nodes.objects, 0, "ProgramStateMachine")
569
        # await pfsm.install(True)
570
571
        async with server:
572
            while 1:
573
                await asyncio.sleep(0)
574
575
    asyncio.run(main())
576