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,426 @@
1
+ # -*- coding: utf-8 -*-
2
+ """pyhades/logger/alarms.py
3
+ """
4
+ from datetime import datetime
5
+ from ..dbmodels import Alarms, AlarmSummary, AlarmTypes, AlarmStates
6
+ from .core import BaseEngine, BaseLogger
7
+ from ..alarms.trigger import TriggerType
8
+ from ..alarms.states import AlarmState
9
+ from ..utils.decorators import db_rollback
10
+
11
+
12
+ class AlarmsLogger(BaseLogger):
13
+
14
+ def __init__(self):
15
+
16
+ super(AlarmsLogger, self).__init__()
17
+
18
+ @db_rollback
19
+ def create_tables(self, tables):
20
+ r"""
21
+ Documentation here
22
+ """
23
+ if not self.check_connectivity():
24
+
25
+ return
26
+
27
+ self._db.create_tables(tables, safe=True)
28
+ self.__init_default_alarms_schema()
29
+
30
+ @db_rollback
31
+ def __init_default_alarms_schema(self):
32
+ r"""
33
+ Documentation here
34
+ """
35
+ ## Alarm Types
36
+ for alarm_type in TriggerType:
37
+
38
+ AlarmTypes.create(name=alarm_type.value)
39
+
40
+ ## Alarm States
41
+ for alarm_state in AlarmState._states:
42
+ name = alarm_state.state
43
+ mnemonic = alarm_state.mnemonic
44
+ condition = alarm_state.process_condition
45
+ status = alarm_state.alarm_status
46
+ AlarmStates.create(name=name, mnemonic=mnemonic, condition=condition, status=status)
47
+
48
+ @db_rollback
49
+ def create(
50
+ self,
51
+ id:str,
52
+ name:str,
53
+ tag:str,
54
+ trigger_type:str,
55
+ trigger_value:float,
56
+ description:str):
57
+ r"""
58
+ Documentation here
59
+ """
60
+ if not self.check_connectivity():
61
+
62
+ return
63
+
64
+ Alarms.create(
65
+ identifier=id,
66
+ name=name,
67
+ tag=tag,
68
+ trigger_type=trigger_type,
69
+ trigger_value=trigger_value,
70
+ description=description
71
+ )
72
+
73
+ @db_rollback
74
+ def get_alarms(self):
75
+ r"""
76
+ Documentation here
77
+ """
78
+ if not self.check_connectivity():
79
+
80
+ return list()
81
+
82
+ alarms = Alarms.read_all()
83
+
84
+ if alarms:
85
+
86
+ return alarms
87
+
88
+ @db_rollback
89
+ def get_alarm_by_name(self, name:str)->Alarms|None:
90
+ r"""
91
+ Documentation here
92
+ """
93
+ if not self.check_connectivity():
94
+
95
+ return None
96
+
97
+ return Alarms.read_by_name(name=name)
98
+
99
+ @db_rollback
100
+ def get_lasts(self, lasts:int=10):
101
+ r"""
102
+ Documentation here
103
+ """
104
+ if not self.is_history_logged:
105
+
106
+ return list()
107
+
108
+ if not self.check_connectivity():
109
+
110
+ return list()
111
+
112
+ return AlarmSummary.read_lasts(lasts=lasts)
113
+
114
+ @db_rollback
115
+ def filter_alarm_summary_by(
116
+ self,
117
+ states:list[str]=None,
118
+ names:list[str]=None,
119
+ tags:list[str]=None,
120
+ greater_than_timestamp:datetime=None,
121
+ less_than_timestamp:datetime=None,
122
+ timezone:str="UTC"
123
+ ):
124
+ r"""
125
+ Documentation here
126
+ """
127
+ if not self.is_history_logged:
128
+
129
+ return None
130
+
131
+ if not self.check_connectivity():
132
+
133
+ return list()
134
+
135
+ return AlarmSummary.filter_by(
136
+ states=states,
137
+ names=names,
138
+ tags=tags,
139
+ greater_than_timestamp=greater_than_timestamp,
140
+ less_than_timestamp=less_than_timestamp,
141
+ timezone=timezone
142
+ )
143
+
144
+ @db_rollback
145
+ def put(
146
+ self,
147
+ id:str,
148
+ name:str=None,
149
+ tag:str=None,
150
+ description:str=None,
151
+ alarm_type:str=None,
152
+ trigger_value:str=None,
153
+ state:str=None
154
+ ):
155
+ if not self.check_connectivity():
156
+
157
+ return None
158
+
159
+ fields = dict()
160
+ alarm = Alarms.read_by_identifier(identifier=id)
161
+ if alarm:
162
+ if name:
163
+ fields["name"] = name
164
+ if tag:
165
+ fields["tag"] = tag
166
+ if description:
167
+ fields["description"] = description
168
+ if alarm_type:
169
+ alarm_type = AlarmTypes.read_by_name(name=alarm_type)
170
+ fields["trigger_type"] = alarm_type
171
+ if trigger_value:
172
+ fields["trigger_value"] = trigger_value
173
+ if state:
174
+ alarm_state = AlarmStates.get_or_none(name=state)
175
+ fields["state"] = alarm_state
176
+ query = Alarms.put(
177
+ id=alarm.id,
178
+ **fields
179
+ )
180
+
181
+ return query
182
+
183
+ @db_rollback
184
+ def delete(self, id:str):
185
+ r"""
186
+ Documentation here
187
+ """
188
+ if not self.check_connectivity():
189
+
190
+ return None
191
+
192
+ alarm_state = AlarmStates.get_or_none(name="Out Of Service")
193
+ alarm = Alarms.read_by_identifier(identifier=id)
194
+ Alarms.put(
195
+ id=alarm.id,
196
+ state=alarm_state
197
+ )
198
+
199
+ @db_rollback
200
+ def create_record_on_alarm_summary(self, name:str, state:str, timestamp:datetime, ack_timestamp:datetime=None):
201
+ r"""
202
+ Documentation here
203
+ """
204
+ if not self.is_history_logged:
205
+
206
+ return None
207
+
208
+ if self.check_connectivity():
209
+
210
+ AlarmSummary.create(name=name, state=state, timestamp=timestamp, ack_timestamp=ack_timestamp)
211
+
212
+ @db_rollback
213
+ def put_record_on_alarm_summary(self, name:str, state:str=None, ack_timestamp:datetime=None):
214
+ r"""
215
+ Documentation here
216
+ """
217
+ if not self.check_connectivity():
218
+
219
+ return None
220
+
221
+ if not self.is_history_logged:
222
+
223
+ return None
224
+
225
+ fields = dict()
226
+ alarm = AlarmSummary.read_by_name(name=name)
227
+
228
+ if alarm:
229
+
230
+ if ack_timestamp:
231
+ fields["ack_time"] = ack_timestamp
232
+ if state:
233
+ alarm_state = AlarmStates.get_or_none(name=state)
234
+ fields["state"] = alarm_state
235
+
236
+ if fields:
237
+ query = AlarmSummary.put(
238
+ id=alarm.id,
239
+ **fields
240
+ )
241
+
242
+ return query
243
+
244
+ @db_rollback
245
+ def get_alarm_summary(self):
246
+ r"""
247
+ Documentation here
248
+ """
249
+ if not self.is_history_logged:
250
+
251
+ return None
252
+
253
+ if not self.check_connectivity():
254
+
255
+ return list()
256
+
257
+ return AlarmSummary.read_all()
258
+
259
+
260
+ class AlarmsLoggerEngine(BaseEngine):
261
+ r"""
262
+ Alarms logger Engine class for Tag thread-safe database logging.
263
+
264
+ """
265
+
266
+ def __init__(self):
267
+
268
+ super(AlarmsLoggerEngine, self).__init__()
269
+ self.logger = AlarmsLogger()
270
+
271
+ def create(
272
+ self,
273
+ id:str,
274
+ name:str,
275
+ tag:str,
276
+ trigger_type:str,
277
+ trigger_value:float,
278
+ description:str
279
+ ):
280
+
281
+ _query = dict()
282
+ _query["action"] = "create"
283
+ _query["parameters"] = dict()
284
+ _query["parameters"]["id"] = id
285
+ _query["parameters"]["name"] = name
286
+ _query["parameters"]["tag"] = tag
287
+ _query["parameters"]["trigger_type"] = trigger_type
288
+ _query["parameters"]["trigger_value"] = trigger_value
289
+ _query["parameters"]["description"] = description
290
+
291
+ return self.query(_query)
292
+
293
+ def get_lasts(
294
+ self,
295
+ lasts:int=1
296
+ ):
297
+
298
+ _query = dict()
299
+ _query["action"] = "get_lasts"
300
+ _query["parameters"] = dict()
301
+ _query["parameters"]["lasts"] = lasts
302
+
303
+ return self.query(_query)
304
+
305
+ def get_alarms(self):
306
+
307
+ _query = dict()
308
+ _query["action"] = "get_alarms"
309
+ _query["parameters"] = dict()
310
+
311
+ return self.query(_query)
312
+
313
+ def get_alarm_by_name(self, name:str):
314
+
315
+ _query = dict()
316
+ _query["action"] = "get_alarm_by_name"
317
+ _query["parameters"] = dict()
318
+ _query["parameters"]["name"] = name
319
+
320
+ return self.query(_query)
321
+
322
+ def filter_alarm_summary_by(
323
+ self,
324
+ names:list[str]=None,
325
+ states:list[int]=None,
326
+ tags:list[int]=None,
327
+ greater_than_timestamp:datetime=None,
328
+ less_than_timestamp:datetime=None,
329
+ timezone:str='UTC'
330
+ ):
331
+
332
+ _query = dict()
333
+ _query["action"] = "filter_alarm_summary_by"
334
+ _query["parameters"] = dict()
335
+ _query["parameters"]["names"] = names
336
+ _query["parameters"]["states"] = states
337
+ _query["parameters"]["tags"] = tags
338
+ _query["parameters"]["greater_than_timestamp"] = greater_than_timestamp
339
+ _query["parameters"]["less_than_timestamp"] = less_than_timestamp
340
+ _query["parameters"]["timezone"] = timezone
341
+
342
+ return self.query(_query)
343
+
344
+ def create_record_on_alarm_summary(self, name:str, state:str, timestamp:datetime, ack_timestamp:datetime=None):
345
+
346
+ _query = dict()
347
+ _query["action"] = "create_record_on_alarm_summary"
348
+ _query["parameters"] = dict()
349
+ _query["parameters"]["name"] = name
350
+ _query["parameters"]["state"] = state
351
+ _query["parameters"]["timestamp"] = timestamp
352
+ _query["parameters"]["ack_timestamp"] = ack_timestamp
353
+
354
+ return self.query(_query)
355
+
356
+ def put_record_on_alarm_summary(
357
+ self,
358
+ name:str,
359
+ state:str=None,
360
+ ack_timestamp:datetime=None
361
+ ):
362
+ _query = dict()
363
+ _query["action"] = "put_record_on_alarm_summary"
364
+ _query["parameters"] = dict()
365
+ _query["parameters"]["name"] = name
366
+ _query["parameters"]["state"] = state
367
+ _query["parameters"]["ack_timestamp"] = ack_timestamp
368
+
369
+ return self.query(_query)
370
+
371
+ def put(
372
+ self,
373
+ id:str,
374
+ name:str=None,
375
+ tag:str=None,
376
+ description:str=None,
377
+ alarm_type:str=None,
378
+ trigger_value:str=None,
379
+ state:str=None
380
+ ):
381
+ _query = dict()
382
+ _query["action"] = "put"
383
+ _query["parameters"] = dict()
384
+ _query["parameters"]["id"] = id
385
+ _query["parameters"]["name"] = name
386
+ _query["parameters"]["tag"] = tag
387
+ _query["parameters"]["description"] = description
388
+ _query["parameters"]["alarm_type"] = alarm_type
389
+ _query["parameters"]["trigger_value"] = trigger_value
390
+ _query["parameters"]["state"] = state
391
+
392
+ return self.query(_query)
393
+
394
+ def delete(self, id:str):
395
+ r"""
396
+ Documentation here
397
+ """
398
+ _query = dict()
399
+ _query["action"] = "delete"
400
+ _query["parameters"] = dict()
401
+ _query["parameters"]["id"] = id
402
+ return self.query(_query)
403
+
404
+ def get_alarm_summary(self):
405
+ r"""
406
+ Documentation here
407
+ """
408
+ _query = dict()
409
+ _query["action"] = "get_alarm_summary"
410
+ _query["parameters"] = dict()
411
+
412
+ return self.query(_query)
413
+
414
+ def create_tables(self, tables):
415
+ r"""
416
+ Create default PyHades database tables
417
+
418
+ ['TagTrend', 'TagValue']
419
+
420
+ **Parameters**
421
+
422
+ * **tables** (list) list of database model
423
+
424
+ **Returns** `None`
425
+ """
426
+ self.logger.create_tables(tables)
@@ -0,0 +1,265 @@
1
+ import threading, logging
2
+ from ..singleton import Singleton
3
+ from ..dbmodels import (
4
+ Variables,
5
+ Units,
6
+ DataTypes
7
+ )
8
+ from ..variables import VARIABLES, DATATYPES
9
+
10
+ class BaseLogger(Singleton):
11
+
12
+ def __init__(self):
13
+
14
+ self._db = None
15
+ self.is_history_logged = True
16
+
17
+ def set_db(self, db):
18
+ r"""Documentation here
19
+ """
20
+ self._db = db
21
+
22
+ def get_db(self):
23
+ r"""
24
+ Documentation here
25
+ """
26
+ return self._db
27
+
28
+ def check_connectivity(self):
29
+
30
+ try:
31
+
32
+ if self._db:
33
+
34
+ self._db.execute_sql('SELECT 1;')
35
+
36
+ return True
37
+
38
+ return False
39
+
40
+ except:
41
+
42
+ return False
43
+
44
+ def set_is_history_logged(self, value:bool=False):
45
+ r"""Documentation here
46
+ """
47
+ self.is_history_logged = value
48
+
49
+ def stop_db(self):
50
+ r""""
51
+ Documentation here
52
+ """
53
+ try:
54
+ if self._db:
55
+ self._db.close()
56
+ self._db = None
57
+ except:
58
+
59
+ pass
60
+
61
+ def create_tables(self, tables):
62
+ r"""
63
+ Documentation here
64
+ """
65
+ if not self._db:
66
+
67
+ return
68
+
69
+ self._db.create_tables(tables, safe=True)
70
+ self.__init_default_variables_schema()
71
+ self.__init_default_datatypes_schema()
72
+ self.__init_default_roles_schema()
73
+
74
+ def __init_default_roles_schema(self):
75
+ r"""
76
+ Documentatio here
77
+ """
78
+ from ..dbmodels import Roles
79
+ for role in Roles.__defaults__:
80
+
81
+ if not Roles.name_exist(name=role['name']):
82
+
83
+ Roles.create(**role)
84
+
85
+ def __init_default_variables_schema(self):
86
+ r"""
87
+ Documentation here
88
+ """
89
+ for variable, units in VARIABLES.items():
90
+
91
+ if not Variables.name_exist(variable):
92
+
93
+ Variables.create(name=variable)
94
+
95
+ for name, unit in units.items():
96
+
97
+ if not Units.name_exist(unit):
98
+
99
+ Units.create(name=name, unit=unit, variable=variable)
100
+
101
+ def __init_default_datatypes_schema(self):
102
+ r"""
103
+ Documentation here
104
+ """
105
+ for datatype in DATATYPES:
106
+
107
+ DataTypes.create(name=datatype["value"])
108
+
109
+ def drop_tables(self, tables):
110
+ r"""
111
+ Documentation here
112
+ """
113
+ if not self._db:
114
+
115
+ return
116
+
117
+ self._db.drop_tables(tables, safe=True)
118
+
119
+ class BaseEngine(Singleton):
120
+ r"""
121
+ Alarms logger Engine class for Tag thread-safe database logging.
122
+ """
123
+ logger = BaseLogger()
124
+
125
+ def __init__(self):
126
+
127
+ super(BaseEngine, self).__init__()
128
+ self._request_lock = threading.Lock()
129
+ self._response_lock = threading.Lock()
130
+ self._response = None
131
+ self._response_lock.acquire()
132
+
133
+ def set_db(self, db):
134
+ r"""
135
+ Sets the database, it supports SQLite and Postgres,
136
+ in case of SQLite, the filename must be provided.
137
+
138
+ if app mode is "Development" you must use SQLite Databse
139
+
140
+ **Parameters:**
141
+
142
+ * **dbfile** (str): a path to database file.
143
+ * *drop_table** (bool): If you want to drop table.
144
+ * **cascade** (bool): if there are some table dependency, drop it as well
145
+ * **kwargs**: Same attributes to a postgres connection.
146
+
147
+ **Returns:** `None`
148
+
149
+ Usage:
150
+
151
+ ```python
152
+ >>> app.set_db(dbfile="app.db")
153
+ ```
154
+ """
155
+ self.logger.set_db(db)
156
+
157
+ def stop_db(self):
158
+ r"""
159
+ Documentation here
160
+ """
161
+ self.logger.stop_db()
162
+
163
+ def get_db(self):
164
+ r"""
165
+ Returns a DB object
166
+ """
167
+ return self.logger.get_db()
168
+
169
+ def query(self, query:dict)->dict:
170
+ r"""
171
+ Documentation here
172
+ """
173
+ self.request(query)
174
+ result = self.response()
175
+ if result["result"]:
176
+ return result["response"]
177
+
178
+ def request(self, query:dict):
179
+ r"""Documentation here
180
+
181
+ # Parameters
182
+
183
+ -
184
+
185
+ # Returns
186
+
187
+ -
188
+ """
189
+ self._request_lock.acquire()
190
+ action = query["action"]
191
+ error_msg = f"Error in BaseEngine: {action}"
192
+
193
+ try:
194
+
195
+ if hasattr(self.logger, action):
196
+
197
+ method = getattr(self.logger, action)
198
+
199
+ if 'parameters' in query:
200
+
201
+ resp = method(**query["parameters"])
202
+
203
+ else:
204
+
205
+ resp = method()
206
+
207
+ self.__true_response(resp)
208
+
209
+ except Exception as e:
210
+
211
+ self.__log_error(e, error_msg)
212
+
213
+ self._response_lock.release()
214
+
215
+ def __log_error(self, e:Exception, msg:str):
216
+ r"""
217
+ Documentation here
218
+ """
219
+ logger = logging.getLogger("pyautomation")
220
+ logger.error(f"{e} Message: {msg}")
221
+ self._response = {
222
+ "result": False,
223
+ "response": None
224
+ }
225
+
226
+ def response(self):
227
+ r"""Documentation here
228
+
229
+ # Parameters
230
+
231
+ -
232
+
233
+ # Returns
234
+
235
+ -
236
+ """
237
+ self._response_lock.acquire()
238
+ result = self._response
239
+ self._request_lock.release()
240
+ return result
241
+
242
+ def __true_response(self, resp):
243
+ r"""
244
+ Documentation here
245
+ """
246
+ self._response = {
247
+ "result": True,
248
+ "response": resp
249
+ }
250
+
251
+ def __getstate__(self):
252
+
253
+ self._response_lock.release()
254
+ state = self.__dict__.copy()
255
+ del state['_request_lock']
256
+ del state['_response_lock']
257
+ return state
258
+
259
+ def __setstate__(self, state):
260
+
261
+ self.__dict__.update(state)
262
+ self._request_lock = threading.Lock()
263
+ self._response_lock = threading.Lock()
264
+
265
+ self._response_lock.acquire()