PyAutomationIO 0.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. automation/__init__.py +46 -0
  2. automation/alarms/__init__.py +563 -0
  3. automation/alarms/states.py +192 -0
  4. automation/alarms/trigger.py +64 -0
  5. automation/buffer.py +132 -0
  6. automation/core.py +1775 -0
  7. automation/dbmodels/__init__.py +23 -0
  8. automation/dbmodels/alarms.py +524 -0
  9. automation/dbmodels/core.py +86 -0
  10. automation/dbmodels/events.py +153 -0
  11. automation/dbmodels/logs.py +155 -0
  12. automation/dbmodels/machines.py +181 -0
  13. automation/dbmodels/opcua.py +81 -0
  14. automation/dbmodels/opcua_server.py +174 -0
  15. automation/dbmodels/tags.py +921 -0
  16. automation/dbmodels/users.py +259 -0
  17. automation/extensions/__init__.py +15 -0
  18. automation/extensions/api.py +149 -0
  19. automation/extensions/cors.py +18 -0
  20. automation/filter/__init__.py +19 -0
  21. automation/iad/__init__.py +3 -0
  22. automation/iad/frozen_data.py +54 -0
  23. automation/iad/out_of_range.py +51 -0
  24. automation/iad/outliers.py +51 -0
  25. automation/logger/__init__.py +0 -0
  26. automation/logger/alarms.py +426 -0
  27. automation/logger/core.py +265 -0
  28. automation/logger/datalogger.py +646 -0
  29. automation/logger/events.py +194 -0
  30. automation/logger/logdict.py +53 -0
  31. automation/logger/logs.py +203 -0
  32. automation/logger/machines.py +248 -0
  33. automation/logger/opcua_server.py +130 -0
  34. automation/logger/users.py +96 -0
  35. automation/managers/__init__.py +4 -0
  36. automation/managers/alarms.py +455 -0
  37. automation/managers/db.py +328 -0
  38. automation/managers/opcua_client.py +186 -0
  39. automation/managers/state_machine.py +183 -0
  40. automation/models.py +174 -0
  41. automation/modules/__init__.py +14 -0
  42. automation/modules/alarms/__init__.py +0 -0
  43. automation/modules/alarms/resources/__init__.py +10 -0
  44. automation/modules/alarms/resources/alarms.py +280 -0
  45. automation/modules/alarms/resources/summary.py +79 -0
  46. automation/modules/events/__init__.py +0 -0
  47. automation/modules/events/resources/__init__.py +10 -0
  48. automation/modules/events/resources/events.py +83 -0
  49. automation/modules/events/resources/logs.py +109 -0
  50. automation/modules/tags/__init__.py +0 -0
  51. automation/modules/tags/resources/__init__.py +8 -0
  52. automation/modules/tags/resources/tags.py +201 -0
  53. automation/modules/users/__init__.py +2 -0
  54. automation/modules/users/resources/__init__.py +10 -0
  55. automation/modules/users/resources/models/__init__.py +2 -0
  56. automation/modules/users/resources/models/roles.py +5 -0
  57. automation/modules/users/resources/models/users.py +14 -0
  58. automation/modules/users/resources/roles.py +38 -0
  59. automation/modules/users/resources/users.py +113 -0
  60. automation/modules/users/roles.py +121 -0
  61. automation/modules/users/users.py +335 -0
  62. automation/opcua/__init__.py +1 -0
  63. automation/opcua/models.py +541 -0
  64. automation/opcua/subscription.py +259 -0
  65. automation/pages/__init__.py +0 -0
  66. automation/pages/alarms.py +34 -0
  67. automation/pages/alarms_history.py +21 -0
  68. automation/pages/assets/styles.css +7 -0
  69. automation/pages/callbacks/__init__.py +28 -0
  70. automation/pages/callbacks/alarms.py +218 -0
  71. automation/pages/callbacks/alarms_summary.py +20 -0
  72. automation/pages/callbacks/db.py +222 -0
  73. automation/pages/callbacks/filter.py +238 -0
  74. automation/pages/callbacks/machines.py +29 -0
  75. automation/pages/callbacks/machines_detailed.py +581 -0
  76. automation/pages/callbacks/opcua.py +266 -0
  77. automation/pages/callbacks/opcua_server.py +244 -0
  78. automation/pages/callbacks/tags.py +495 -0
  79. automation/pages/callbacks/trends.py +119 -0
  80. automation/pages/communications.py +129 -0
  81. automation/pages/components/__init__.py +123 -0
  82. automation/pages/components/alarms.py +151 -0
  83. automation/pages/components/alarms_summary.py +45 -0
  84. automation/pages/components/database.py +128 -0
  85. automation/pages/components/gaussian_filter.py +69 -0
  86. automation/pages/components/machines.py +396 -0
  87. automation/pages/components/opcua.py +384 -0
  88. automation/pages/components/opcua_server.py +53 -0
  89. automation/pages/components/tags.py +253 -0
  90. automation/pages/components/trends.py +66 -0
  91. automation/pages/database.py +26 -0
  92. automation/pages/filter.py +55 -0
  93. automation/pages/machines.py +20 -0
  94. automation/pages/machines_detailed.py +41 -0
  95. automation/pages/main.py +63 -0
  96. automation/pages/opcua_server.py +28 -0
  97. automation/pages/tags.py +40 -0
  98. automation/pages/trends.py +35 -0
  99. automation/singleton.py +30 -0
  100. automation/state_machine.py +1672 -0
  101. automation/tags/__init__.py +2 -0
  102. automation/tags/cvt.py +1198 -0
  103. automation/tags/filter.py +55 -0
  104. automation/tags/tag.py +418 -0
  105. automation/tests/__init__.py +10 -0
  106. automation/tests/test_alarms.py +110 -0
  107. automation/tests/test_core.py +257 -0
  108. automation/tests/test_unit.py +21 -0
  109. automation/tests/test_user.py +155 -0
  110. automation/utils/__init__.py +164 -0
  111. automation/utils/decorators.py +222 -0
  112. automation/utils/npw.py +294 -0
  113. automation/utils/observer.py +21 -0
  114. automation/utils/units.py +118 -0
  115. automation/variables/__init__.py +55 -0
  116. automation/variables/adimentional.py +30 -0
  117. automation/variables/current.py +71 -0
  118. automation/variables/density.py +115 -0
  119. automation/variables/eng_time.py +68 -0
  120. automation/variables/force.py +90 -0
  121. automation/variables/length.py +104 -0
  122. automation/variables/mass.py +80 -0
  123. automation/variables/mass_flow.py +101 -0
  124. automation/variables/percentage.py +30 -0
  125. automation/variables/power.py +113 -0
  126. automation/variables/pressure.py +93 -0
  127. automation/variables/temperature.py +168 -0
  128. automation/variables/volume.py +70 -0
  129. automation/variables/volumetric_flow.py +100 -0
  130. automation/workers/__init__.py +2 -0
  131. automation/workers/logger.py +164 -0
  132. automation/workers/state_machine.py +207 -0
  133. automation/workers/worker.py +36 -0
  134. pyautomationio-0.0.0.dist-info/METADATA +198 -0
  135. pyautomationio-0.0.0.dist-info/RECORD +138 -0
  136. pyautomationio-0.0.0.dist-info/WHEEL +5 -0
  137. pyautomationio-0.0.0.dist-info/licenses/LICENSE +21 -0
  138. pyautomationio-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,328 @@
1
+ # -*- coding: utf-8 -*-
2
+ """pyhades/managers/logger.py
3
+
4
+ This module implements Logger Manager.
5
+ """
6
+ import logging, queue
7
+ from ..singleton import Singleton
8
+ from ..logger.datalogger import DataLoggerEngine
9
+ from ..logger.logdict import LogTable
10
+ from ..logger.alarms import AlarmsLoggerEngine
11
+ from ..logger.events import EventsLoggerEngine
12
+ from ..logger.users import UsersLoggerEngine
13
+ from ..logger.logs import LogsLoggerEngine
14
+ from ..logger.machines import MachinesLoggerEngine
15
+ from ..logger.opcua_server import OPCUAServerLoggerEngine
16
+ from ..tags import CVTEngine, TagObserver
17
+ from ..modules.users.users import User
18
+ from ..utils.decorators import logging_error_handler
19
+ from ..dbmodels import (
20
+ Manufacturer,
21
+ Segment,
22
+ Tags,
23
+ TagValue,
24
+ AlarmTypes,
25
+ AlarmStates,
26
+ Alarms,
27
+ AlarmSummary,
28
+ Variables,
29
+ Units,
30
+ DataTypes,
31
+ OPCUA,
32
+ Users,
33
+ Roles,
34
+ Events,
35
+ Logs,
36
+ Machines,
37
+ TagsMachines,
38
+ AccessType,
39
+ OPCUAServer,
40
+ BaseModel
41
+ )
42
+
43
+
44
+ class DBManager(Singleton):
45
+ r"""
46
+ Database Manager class for database logging settings.
47
+ """
48
+
49
+ def __init__(self, period:float=1.0, delay:float=1.0, drop_tables:bool=False):
50
+
51
+ self._period = period
52
+ self._delay = delay
53
+ self._drop_tables = drop_tables
54
+ self._tag_queue = queue.Queue()
55
+ self.engine = CVTEngine()
56
+ self._logging_tags = LogTable()
57
+ self._logger = DataLoggerEngine()
58
+ self.alarms_logger = AlarmsLoggerEngine()
59
+ self.events_logger = EventsLoggerEngine()
60
+ self.users_logger = UsersLoggerEngine()
61
+ self.logs_logger = LogsLoggerEngine()
62
+ self.machines_logger = MachinesLoggerEngine()
63
+ self.opcuaserver_logger = OPCUAServerLoggerEngine()
64
+ self._tables = [
65
+ Manufacturer,
66
+ Segment,
67
+ Variables,
68
+ Units,
69
+ DataTypes,
70
+ Tags,
71
+ TagValue,
72
+ AlarmTypes,
73
+ AlarmStates,
74
+ Alarms,
75
+ AlarmSummary,
76
+ OPCUA,
77
+ Roles,
78
+ Users,
79
+ Events,
80
+ Logs,
81
+ Machines,
82
+ TagsMachines,
83
+ AccessType,
84
+ OPCUAServer
85
+ ]
86
+
87
+ self._extra_tables = []
88
+
89
+ def get_queue(self)->queue.Queue:
90
+ r"""
91
+ Documentation here
92
+ """
93
+ return self._tag_queue
94
+
95
+ def set_db(self, db, is_history_logged:bool=False):
96
+ r"""
97
+ Initialize a new DB Object SQLite - Postgres - MySQL
98
+
99
+ **Parameters**
100
+
101
+ * **db** (db object): Sqlite - Postgres or MySql db object
102
+
103
+ **Returns** `None`
104
+ """
105
+ self._logger.set_db(db)
106
+ self._logger.logger.set_is_history_logged(value=is_history_logged)
107
+ self.alarms_logger.set_db(db)
108
+ self.alarms_logger.logger.set_is_history_logged(value=is_history_logged)
109
+ self.events_logger.set_db(db)
110
+ self.events_logger.logger.set_is_history_logged(value=is_history_logged)
111
+ self.users_logger.set_db(db)
112
+ self.logs_logger.set_db(db)
113
+ self.logs_logger.logger.set_is_history_logged(value=is_history_logged)
114
+ self.machines_logger.set_db(db)
115
+ self.opcuaserver_logger.logger.set_db(db)
116
+
117
+ def get_db(self):
118
+ r"""
119
+ Returns a DB object
120
+ """
121
+ return self._logger.get_db()
122
+
123
+ def set_dropped(self, drop_tables:bool):
124
+ r"""
125
+ Allows to you set a flag variable to drop database tables when run app.
126
+
127
+ **Parameters**
128
+
129
+ * **drop_tables** (bool) If True, drop all tables define in the app an initialized it in blank.
130
+
131
+ **Returns**
132
+
133
+ * **None**
134
+ """
135
+ self._drop_tables = drop_tables
136
+
137
+ def get_dropped(self)->bool:
138
+ r"""
139
+ Gets flag variables to drop tables when initialize the app
140
+
141
+ **Return**
142
+
143
+ * **drop_tables** (bool) Flag variables to drop table
144
+ """
145
+ return self._drop_tables
146
+
147
+ def register_table(self, cls:BaseModel):
148
+ r"""
149
+ Allows to you register a new database model
150
+
151
+ **Parameters**
152
+
153
+ * **cls* (BaseModel): A class that inherit from BaseModel
154
+
155
+ """
156
+ self._tables.append(cls)
157
+
158
+ def get_db_table(self, tablename:str):
159
+ r"""
160
+ Documentation here
161
+ """
162
+ for table in self._tables:
163
+
164
+ if table._meta.table_name.lower()==tablename.lower():
165
+
166
+ return table
167
+
168
+ return None
169
+
170
+ def create_tables(self):
171
+ r"""
172
+ Creates default tables and tables registered with method *register_table*
173
+ """
174
+ self._tables.extend(self._extra_tables)
175
+ self._logger.create_tables(self._tables)
176
+ self.alarms_logger.create_tables(self._tables)
177
+
178
+ def drop_tables(self):
179
+ r"""
180
+ Drop all tables defined
181
+ """
182
+ tables = self._tables
183
+
184
+ self._logger.drop_tables(tables)
185
+
186
+ def clear_default_tables(self):
187
+ r"""
188
+ If you want initialize any PyHades app without default tables, you can use this method
189
+ """
190
+ self._tables = []
191
+
192
+ def get_tags(self)->dict:
193
+ r"""
194
+ Gets all tag defined in tag's repository
195
+ """
196
+ return self._logger.get_tags()
197
+
198
+ def get_alarms(self)->dict:
199
+ r"""
200
+ Gets all tag defined in tag's repository
201
+ """
202
+
203
+ return self.alarms_logger.get_alarms()
204
+
205
+ @logging_error_handler
206
+ def set_tag(
207
+ self,
208
+ tag:str,
209
+ unit:str,
210
+ data_type:str,
211
+ description:str,
212
+ display_name:str="",
213
+ min_value:float=None,
214
+ max_value:float=None,
215
+ tcp_source_address:str=None,
216
+ node_namespace:str=None):
217
+ r"""
218
+ Sets tag to Database
219
+
220
+ **Parameters**
221
+
222
+ * **tag** (str):
223
+ * **unit** (str):
224
+ * **data_type** (str):
225
+ * **description** (str):
226
+ * **min_value** (float)[Optional]:
227
+ * **max_value** (float)[Optional]:
228
+ * **tcp_source_address** (str)[Optional]:
229
+ * **node_namespace** (str)[Optional]:
230
+ """
231
+ self._logger.set_tag(
232
+ tag=tag,
233
+ unit=unit,
234
+ data_type=data_type,
235
+ description=description,
236
+ display_name=display_name,
237
+ min_value=min_value,
238
+ max_value=max_value,
239
+ tcp_source_address=tcp_source_address,
240
+ node_namespace=node_namespace
241
+ )
242
+
243
+ def set_tags(self):
244
+ r"""
245
+ Allows to you define all tags added with *add_tag* method
246
+ """
247
+ for period in self._logging_tags.get_groups():
248
+
249
+ tags = self._logging_tags.get_tags(period)
250
+
251
+ for tag, unit, data_type, description, display_name, min_value, max_value, tcp_source_address, node_namespace in tags:
252
+
253
+ self.set_tag(
254
+ tag=tag,
255
+ unit=unit,
256
+ data_type=data_type,
257
+ description=description,
258
+ display_name=display_name,
259
+ min_value=min_value,
260
+ max_value=max_value,
261
+ tcp_source_address=tcp_source_address,
262
+ node_namespace=node_namespace)
263
+
264
+ def init_database(self):
265
+ r"""
266
+ Initializes all databases.
267
+ """
268
+ if self.get_dropped():
269
+ try:
270
+ self.drop_tables()
271
+ except Exception as e:
272
+ error = str(e)
273
+ logger = logging.getLogger("pyautomation")
274
+ logger.error("Database:{}".format(error))
275
+
276
+ self.create_tables()
277
+
278
+ def stop_database(self):
279
+ r"""
280
+ Documentation here
281
+ """
282
+ self._logger.stop_db()
283
+
284
+ def get_opcua_clients(self):
285
+ r"""
286
+ Documentation here
287
+ """
288
+ return OPCUA.read_all()
289
+
290
+ # USERS METHODS
291
+ def set_role(self, name:str, level:int, identifier:str):
292
+ r"""
293
+ Documentation here
294
+ """
295
+ return self.users_logger.set_role(name=name, level=level, identifier=identifier)
296
+
297
+ def set_user(self, user:User):
298
+ r"""
299
+ Documentation here
300
+ """
301
+ return self.users_logger.set_user(user=user)
302
+
303
+ def login(self, password:str, username:str="", email:str=""):
304
+ r"""
305
+ Documentation here
306
+ """
307
+ return self.users_logger.login(password=password, username=username, email=email)
308
+
309
+ def summary(self)->dict:
310
+ r"""
311
+ Get database manager summary
312
+
313
+ **Returns**
314
+
315
+ * **summary** (dict): Database summary
316
+ """
317
+ result = dict()
318
+
319
+ result["period"] = self.get_period()
320
+ result["tags"] = self.get_tags()
321
+ result["delay"] = self.get_delay()
322
+
323
+ return result
324
+
325
+ def attach(self, tag_name:str):
326
+
327
+ observer = TagObserver(self._tag_queue)
328
+ self.engine.attach(name=tag_name, observer=observer)
@@ -0,0 +1,186 @@
1
+ from ..opcua.models import Client
2
+ from ..dbmodels import OPCUA
3
+ from ..logger.datalogger import DataLoggerEngine
4
+ from ..tags import CVTEngine
5
+ from ..opcua.subscription import DAS
6
+
7
+ class OPCUAClientManager:
8
+ r"""
9
+ Documentation here
10
+ """
11
+
12
+ def __init__(self):
13
+ r"""
14
+ Documentation here
15
+ """
16
+ self._clients = dict()
17
+ self.logger = DataLoggerEngine()
18
+ self.cvt = CVTEngine()
19
+ self.das = DAS()
20
+
21
+ def discovery(self, host:str='127.0.0.1', port:int=4840)->list[dict]:
22
+ r"""
23
+ Documentation here
24
+ """
25
+ return Client.find_servers(host, port)
26
+
27
+ def add(self, client_name:str, host:str, port:int):
28
+ r"""
29
+ Documentation here
30
+ """
31
+ endpoint_url = f"opc.tcp://{host}:{port}"
32
+ if client_name in self._clients:
33
+
34
+ return True, f"Client Name {client_name} duplicated"
35
+
36
+ opcua_client = Client(endpoint_url, client_name=client_name)
37
+
38
+ message, status_connection = opcua_client.connect()
39
+ if status_connection==200:
40
+
41
+ self._clients[client_name] = opcua_client
42
+
43
+ # DATABASE PERSISTENCY
44
+ if self.logger.get_db():
45
+
46
+ OPCUA.create(client_name=client_name, host=host, port=port)
47
+
48
+ # RECONNECT TO SUBSCRIPTION
49
+ for tag in self.cvt.get_tags():
50
+
51
+ if tag["opcua_address"]==endpoint_url:
52
+
53
+ if not tag["scan_time"]:
54
+
55
+ subscription = opcua_client.create_subscription(1000, self.das)
56
+ node_id = opcua_client.get_node_id_by_namespace(tag["node_namespace"])
57
+ self.das.subscribe(subscription=subscription, client_name=client_name, node_id=node_id)
58
+
59
+ self.das.restart_buffer(tag=self.cvt.get_tag(id=tag["id"]))
60
+
61
+ return True, message
62
+
63
+ return False, message
64
+
65
+ def remove(self, client_name:str):
66
+ r"""
67
+ Documentation here
68
+ """
69
+ if client_name in self._clients:
70
+ try:
71
+ opcua_client = self._clients.pop(client_name)
72
+ opcua_client.disconnect()
73
+ # DATABASE PERSISTENCY
74
+ opcua = OPCUA.get_by_client_name(client_name=client_name)
75
+ if opcua:
76
+ if self.logger.get_db():
77
+ query = OPCUA.delete().where(OPCUA.client_name == client_name)
78
+ query.execute()
79
+
80
+ return True
81
+ except Exception as err:
82
+
83
+ return False
84
+
85
+ return False
86
+
87
+ def connect(self, client_name:str)->dict:
88
+ r"""
89
+ Documentation here
90
+ """
91
+ if client_name in self._clients:
92
+
93
+ self._clients[client_name].connect()
94
+
95
+ def disconnect(self, client_name:str)->dict:
96
+ r"""
97
+ Documentation here
98
+ """
99
+ if client_name in self._clients:
100
+
101
+ self._clients[client_name].disconnect()
102
+
103
+ def get(self, client_name:str)->Client:
104
+ r"""
105
+ Documentation here
106
+ """
107
+ if client_name in self._clients:
108
+
109
+ return self._clients[client_name]
110
+
111
+ def get_opcua_tree(self, client_name):
112
+ r"""
113
+ Documentation here
114
+ """
115
+ client = self.get(client_name=client_name)
116
+ if client.is_connected():
117
+ root_node = client.get_root_node()
118
+ _tree = client.browse_tree(root_node)
119
+ result = {
120
+ "Objects": _tree[0]["children"]
121
+ }
122
+ return result, 200
123
+
124
+ return {}, 400
125
+
126
+ def get_node_values(self, client_name:str, namespaces:list)->list:
127
+
128
+ if client_name in self._clients:
129
+
130
+ client = self._clients[client_name]
131
+ if client.is_conneted():
132
+ return client.get_nodes_values(namespaces=namespaces)
133
+
134
+ def get_client_by_address(self, opcua_address:str)->Client|None:
135
+ r"""
136
+ Obtiene el cliente OPC UA correspondiente a una dirección
137
+
138
+ Args:
139
+ opcua_address: Dirección del servidor OPC UA (ej: "opc.tcp://localhost:4840")
140
+
141
+ Returns:
142
+ Client: Cliente OPC UA si existe y está conectado, None en caso contrario
143
+ """
144
+ for client_name, client in self._clients.items():
145
+ if opcua_address == client.serialize()["server_url"]:
146
+ if client.is_connected():
147
+ return client
148
+ return None
149
+
150
+ def get_node_value_by_opcua_address(self, opcua_address:str, namespace:str)->list:
151
+ r"""
152
+ Documentation here
153
+ """
154
+ for client_name, client in self._clients.items():
155
+
156
+ if opcua_address==client.serialize()["server_url"]:
157
+ if client.is_connected():
158
+ return self.get_node_attributes(client_name=client_name, namespaces=[namespace])
159
+
160
+ def get_node_attributes(self, client_name:str, namespaces:list)->list:
161
+
162
+ result = list()
163
+
164
+ if client_name in self._clients:
165
+
166
+ client = self._clients[client_name]
167
+
168
+ for namespace in namespaces:
169
+ if client.is_connected():
170
+ result.append(client.get_node_attributes(node_namespace=namespace))
171
+
172
+ return result
173
+
174
+ def serialize(self, client_name:str=None)->dict:
175
+ r"""
176
+ Documentation here
177
+ """
178
+ if client_name:
179
+
180
+ if client_name in self._clients:
181
+
182
+ opcua_client = self._clients[client_name]
183
+
184
+ return opcua_client.serialize()
185
+
186
+ return {client_name: client.serialize() for client_name, client in self._clients.items()}
@@ -0,0 +1,183 @@
1
+ # -*- coding: utf-8 -*-
2
+ """broker/managers/state_machine.py
3
+
4
+ This module implements Function Manager.
5
+ """
6
+ from statemachine import StateMachine
7
+ from ..models import StringType
8
+ from ..tags import TagObserver, CVTEngine, Tag
9
+ import queue
10
+
11
+ class StateMachineManager:
12
+ r"""
13
+ Handles and manager the state machines defined in the application in a store defined by a list of tuples
14
+
15
+ Its structure is [(machine_1, interval_1, mode_1), (machine_2, interval_2, mode_2), ... (machine_n, interval_n, mode_n)]
16
+ """
17
+
18
+ def __init__(self):
19
+
20
+ self._machines = list()
21
+ self._tag_queue = queue.Queue()
22
+
23
+ def get_queue(self)->queue.Queue:
24
+ r"""Documentation here
25
+
26
+ # Parameters
27
+
28
+ -
29
+
30
+ # Returns
31
+
32
+ -
33
+ """
34
+ return self._tag_queue
35
+
36
+ def append_machine(self, machine:StateMachine):
37
+ r"""
38
+ Appends machines to the store
39
+
40
+ **Parameters**
41
+
42
+ * **machine:** (PyHadesStateMachine) instance
43
+ * **interval:** (float) Execution interval in seconds
44
+ * **mode:** (str) Thread mode of the state machine, allowed mode ('sync', 'async')
45
+
46
+ **Returns** `None`
47
+
48
+ Usage
49
+
50
+ ```python
51
+ >>> manager = app.get_state_machine_manager()
52
+ >>> manager.append_machine(machine, interval, mode)
53
+ ```
54
+ """
55
+
56
+ self._machines.append(machine)
57
+
58
+ def get_machines(self)->list:
59
+ r"""
60
+ Gets state machines
61
+
62
+ **Returns**
63
+
64
+ * **machines** (list of tuples)
65
+
66
+ Usage
67
+
68
+ ```python
69
+ >>> manager = app.get_state_machine_manager()
70
+ >>> machines = manager.get_machines()
71
+ [(machine_1, interval_1, mode_1), (machine_2, interval_2, mode_2), ... (machine_n, interval_n, mode_n)]
72
+ ```
73
+ """
74
+ result = self._machines
75
+
76
+ return result
77
+
78
+ def serialize_machines(self):
79
+ r"""
80
+ Documentation here
81
+ """
82
+
83
+ return [machine.serialize() for machine, _, _ in self.get_machines()]
84
+
85
+ def get_machine(self, name:StringType)->StateMachine:
86
+ r"""
87
+ Gets state machine by its name
88
+
89
+ **Parameters**
90
+
91
+ * **name:** (str) State machine name
92
+
93
+ **Returns**
94
+
95
+ * **machine:** (PyHadesStateMachine) instance
96
+
97
+ Usage
98
+
99
+ ```python
100
+ >>> manager = app.get_state_machine_manager()
101
+ >>> machine = manager.get_machine(state_machine_name)
102
+ ```
103
+ """
104
+ for machine, _, _ in self._machines:
105
+
106
+ if name.value == machine.name.value:
107
+
108
+ return machine
109
+
110
+ def drop(self, name:str):
111
+ r"""
112
+ Documentation here
113
+ """
114
+ index = 0
115
+ for machine, _, _ in self._machines:
116
+
117
+ if name == machine.name.value:
118
+
119
+ machine_to_revome_from_worker = self._machines.pop(index)
120
+ break
121
+
122
+ index += 1
123
+
124
+ if machine_to_revome_from_worker:
125
+
126
+ return machine_to_revome_from_worker
127
+
128
+ def unsubscribe_tag(self, tag:Tag):
129
+ r"""
130
+ Documentation here
131
+ """
132
+ machine_to_revome_from_worker = (None, None, None)
133
+ for machine, _, _ in self._machines:
134
+
135
+ if hasattr(machine, "unsubscribe_to"):
136
+
137
+ machine.unsubscribe_to(tag=tag)
138
+
139
+ if machine.classification.value.lower()=="data acquisition system":
140
+
141
+ if not machine.get_subscribed_tags():
142
+
143
+ machine_to_revome_from_worker = self.drop(name=machine.name.value)
144
+ break
145
+
146
+ if machine_to_revome_from_worker:
147
+
148
+ return machine_to_revome_from_worker
149
+
150
+ def summary(self)->dict:
151
+ r"""
152
+ Get a summary of the state machine defined
153
+
154
+ **Returns**
155
+
156
+ * **summary:** (dict) with keys ('length' (int) - 'state_machines' (list of state machine names))
157
+ """
158
+ result = dict()
159
+ machines = [machine.name for machine, _, _ in self.get_machines()]
160
+
161
+ result["length"] = len(machines)
162
+ result["state_machines"] = machines
163
+
164
+ return result
165
+
166
+ def exist_machines(self)->bool:
167
+ r"""
168
+ Checks if exist state machines defined
169
+
170
+ **Returns**
171
+
172
+ * **Bool**
173
+
174
+ Usage
175
+
176
+ ```python
177
+ >>> manager = app.get_state_machine_manager()
178
+ >>> manager.exist_machines()
179
+ ```
180
+ """
181
+ return len(self._machines) > 0
182
+
183
+