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,581 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.models import StringType, IntegerType, FloatType
4
+ from ..components.machines import MachinesComponents
5
+ from ...variables import *
6
+
7
+ def init_callback(app:dash.Dash):
8
+
9
+ @app.callback(
10
+ dash.Output('machines_detailed_tabs', 'children'),
11
+ dash.Output('machines_detailed_tabs', 'active_tab'),
12
+ dash.Output("machine_detailed_content", "children"),
13
+ dash.Input('machines_detailed_page', 'pathname'),
14
+ prevent_initial_call=True
15
+ )
16
+ def display_page(pathname):
17
+ r"""
18
+ Documentation here
19
+ """
20
+ tabs = list()
21
+ active_tab = None
22
+ machine_tab_content = dash.html.P("This shouldn't ever be displayed...")
23
+ if pathname=="/machines-detailed":
24
+ for machine, _, _ in app.automation.get_machines():
25
+
26
+ if hasattr(machine, "classification"):
27
+
28
+ if machine.classification.value.lower()=="opc ua server":
29
+
30
+ continue
31
+
32
+ elif machine.classification.value.lower()=="data acquisition system":
33
+
34
+ continue
35
+
36
+ internal_variables = machine.get_internal_process_type_variables()
37
+ if internal_variables:
38
+
39
+ tabs.append(dbc.Tab(label=f"{machine.name.value}", tab_id=f"tab-{machine.name.value}"))
40
+ if not active_tab:
41
+
42
+ active_tab = f"tab-{machine.name.value}"
43
+ machine_tab_content = MachinesComponents.machine_tab_content(app=app.automation, machine_name=machine.name.value)
44
+
45
+ return tabs, active_tab, machine_tab_content
46
+
47
+ @app.callback(
48
+ dash.Output('machines_detailed_datatable', 'data', allow_duplicate=True),
49
+ dash.Input('timestamp-interval', 'n_intervals'),
50
+ dash.State('machines_detailed_tabs', 'active_tab'),
51
+ prevent_initial_call=False
52
+ )
53
+ def update_table( n_intervals, active_tab:str):
54
+ machine_name = active_tab.split("-")[-1]
55
+ def flatten_dict(d, parent_key='', sep='.'):
56
+ items = []
57
+ for k, v in d.items():
58
+
59
+ new_key = f"{parent_key}{sep}{k}" if parent_key else k
60
+ if isinstance(v, dict):
61
+ items.extend(flatten_dict(v, new_key, sep=sep).items())
62
+ else:
63
+ items.append((new_key, v))
64
+
65
+ return dict(items)
66
+
67
+ machine = app.automation.get_machine(name=StringType(machine_name))
68
+ data = list()
69
+ serialized_data = machine.serialize()
70
+ flattened_data = flatten_dict(serialized_data)
71
+ for key, value in flattened_data.items():
72
+
73
+ if isinstance(value, (bool, int, str, float)):
74
+
75
+ data.append({"name": key, "value": value})
76
+
77
+ return data
78
+
79
+ @app.callback(
80
+ dash.Output('subscribed_tag_machine_input', 'options', allow_duplicate=True),
81
+ dash.Output('field_tag_input', 'options', allow_duplicate=True),
82
+ dash.Output('internal_tag_input', 'options', allow_duplicate=True),
83
+ dash.Input('machines_detailed_tabs', 'active_tab'),
84
+ prevent_initial_call=False
85
+ )
86
+ def update_subscription_form(active_tab:str):
87
+ machine_name = active_tab.split("-")[-1]
88
+ machine = app.automation.get_machine(name=StringType(machine_name))
89
+ internal_variables = machine.get_read_only_process_type_variables()
90
+ subscribed_tags_machine = [{"label": "", "value": ""}]
91
+ not_subscribed = [{"label": "", "value": ""}]
92
+ available_tags = [{"label": "", "value": ""}]
93
+ tags = app.automation.cvt._cvt.get_cuasi_field_tags_names()
94
+ for _tag_name, value in internal_variables.items():
95
+
96
+ if value.tag:
97
+ subscribed_tags_machine.append({
98
+ "label": f"{value.tag.name}->{_tag_name}", "value": value.tag.name
99
+ })
100
+ if value.tag.name in tags:
101
+ tags.remove(value.tag.name)
102
+
103
+ else:
104
+
105
+ not_subscribed.append({
106
+ "label": _tag_name, "value": _tag_name
107
+ })
108
+
109
+ for tag in tags:
110
+
111
+ available_tags.append({
112
+ "label": tag, "value": tag
113
+ })
114
+ return subscribed_tags_machine, available_tags, not_subscribed
115
+
116
+ @app.callback(
117
+ dash.Output("machine_threshold_input", "placeholder", allow_duplicate=True),
118
+ dash.Output("machine_threshold_input", "disabled", allow_duplicate=True),
119
+ dash.Output("threshold_input_text", 'children', allow_duplicate=True),
120
+ dash.Output("machine_interval_input", 'placeholder', allow_duplicate=True),
121
+ dash.Output("buffer_size_input", 'placeholder', allow_duplicate=True),
122
+ dash.Output("buffer_size_input", 'disabled', allow_duplicate=True),
123
+ dash.Output("on_delay_input", 'placeholder', allow_duplicate=True),
124
+ dash.Output("machine_threshold_input", "value", allow_duplicate=True),
125
+ dash.Output("machine_interval_input", 'value', allow_duplicate=True),
126
+ dash.Output("buffer_size_input", 'value', allow_duplicate=True),
127
+ dash.Output("on_delay_input", 'value', allow_duplicate=True),
128
+ dash.Input('machines_detailed_tabs', 'active_tab'),
129
+ prevent_initial_call=False
130
+ )
131
+ def update_attributes_form(active_tab:str):
132
+ machine_name = active_tab.split("-")[-1]
133
+ machine = app.automation.get_machine(name=StringType(machine_name))
134
+ machine_interval = machine.get_interval()
135
+ threshold = machine.threshold
136
+ on_delay = machine.on_delay
137
+ machine_threshold_place = f"Current threshold {threshold.value}"
138
+ machine_interval = f"Current machine interval {machine_interval}"
139
+ threshold_input_text = threshold.unit
140
+ buffer_size = f"Buffer Size"
141
+ disable = True
142
+ if hasattr(machine, "buffer_size"):
143
+ disable = False
144
+ buffer_size = machine.buffer_size
145
+ buffer_size = f"Current buffer size: {buffer_size.value}"
146
+ if "pfm" in machine_name.lower():
147
+ disable = True
148
+ elif "observer" in machine_name.lower():
149
+ disable = True
150
+ on_delay = f"Current on delay: {on_delay.value}"
151
+
152
+ return machine_threshold_place, disable, threshold_input_text, machine_interval, buffer_size, disable, on_delay, "", "", "", ""
153
+
154
+ @app.callback(
155
+ dash.Output('machine_state_input', 'children'),
156
+ dash.Input('timestamp-interval', 'n_intervals'),
157
+ dash.State('machines_detailed_tabs', 'active_tab'),
158
+ dash.State('machine_state_input', 'children'),
159
+ prevent_initial_call=False
160
+ )
161
+ def update_state( n_intervals, active_tab:str, previous_machine_state):
162
+ r"""
163
+ Documentation here
164
+ """
165
+ machine_name = active_tab.split("-")[-1]
166
+ machine = app.automation.get_machine(name=StringType(machine_name))
167
+ state = machine.current_state.value
168
+
169
+ if state!=previous_machine_state:
170
+ actions = [{"label": "", "value": ""}]
171
+ for action in machine.get_allowed_actions():
172
+ actions.append({"label": action, "value": action})
173
+ dash.set_props("machine_actions_input", {
174
+ 'options': actions
175
+ })
176
+
177
+ return state
178
+
179
+ return previous_machine_state
180
+
181
+ @app.callback(
182
+ dash.Input("field_tag_input", "value"),
183
+ dash.Input("internal_tag_input", "value"),
184
+ )
185
+ def enable_subscribe_button(
186
+ field_tag:str,
187
+ internal_tag:str
188
+ )->str:
189
+ r"""
190
+ Documentation here
191
+ """
192
+ if field_tag and internal_tag:
193
+
194
+ dash.set_props("subscribe_tag_machine_button", {'disabled': False})
195
+
196
+ else:
197
+
198
+ dash.set_props("subscribe_tag_machine_button", {'disabled': True})
199
+
200
+ @app.callback(
201
+ dash.Input("subscribed_tag_machine_input", "value")
202
+ )
203
+ def enable_unsubscribe_button(
204
+ tag_machine:str
205
+ )->str:
206
+ r"""
207
+ Documentation here
208
+ """
209
+ if tag_machine:
210
+
211
+ dash.set_props("unsubscribe_tag_machine_button", {'disabled': False})
212
+
213
+ else:
214
+
215
+ dash.set_props("unsubscribe_tag_machine_button", {'disabled': True})
216
+
217
+ @app.callback(
218
+ dash.Output("field_tag_input", "value", allow_duplicate=True),
219
+ dash.Output("internal_tag_input", "value", allow_duplicate=True),
220
+ dash.Output('subscribed_tag_machine_input', 'value', allow_duplicate=True),
221
+ dash.Output("field_tag_input", "options", allow_duplicate=True),
222
+ dash.Output("internal_tag_input", "options", allow_duplicate=True),
223
+ dash.Output('subscribed_tag_machine_input', 'options'),
224
+ dash.Input('subscribe_tag_machine_button', 'n_clicks'),
225
+ dash.State("field_tag_input", "value"),
226
+ dash.State("internal_tag_input", "value"),
227
+ dash.State('machines_detailed_tabs', 'active_tab'),
228
+ dash.State('subscribed_tag_machine_input', 'options'),
229
+ dash.State("field_tag_input", "options"),
230
+ dash.State("internal_tag_input", "options"),
231
+ prevent_initial_call=True
232
+ )
233
+ def subscribed_on_click(
234
+ btn1,
235
+ field_tag_input:str,
236
+ internal_tag_input:str,
237
+ active_tab:str,
238
+ tags_machine_options:list,
239
+ field_tag_options:list,
240
+ internal_tag_options:list,
241
+ ):
242
+ r"""
243
+ Documentation here
244
+ """
245
+ if "subscribe_tag_machine_button" == dash.ctx.triggered_id:
246
+
247
+ machine_name = active_tab.split("-")[-1]
248
+ machine = app.automation.get_machine(name=StringType(machine_name))
249
+ field_tag = app.automation.cvt._cvt.get_tag_by_name(name=field_tag_input)
250
+
251
+ subscribed, message = machine.subscribe_to(tag=field_tag, default_tag_name=internal_tag_input)
252
+
253
+ if subscribed:
254
+
255
+ tags_machine_options.append({
256
+ "label": f"{field_tag_input}->{internal_tag_input}", "value": internal_tag_input
257
+ })
258
+ field_tag_options.remove({
259
+ "label": field_tag_input, "value": field_tag_input
260
+ })
261
+ internal_tag_options.remove({
262
+ "label": internal_tag_input, "value": internal_tag_input
263
+ })
264
+
265
+ return "", "", "", field_tag_options, internal_tag_options, tags_machine_options
266
+
267
+ @app.callback(
268
+ dash.Output('subscribed_tag_machine_input', 'value', allow_duplicate=True),
269
+ dash.Output('subscribed_tag_machine_input', 'options', allow_duplicate=True),
270
+ dash.Output("field_tag_input", "options", allow_duplicate=True),
271
+ dash.Output("internal_tag_input", "options", allow_duplicate=True),
272
+ dash.Input('unsubscribe_tag_machine_button', 'n_clicks'),
273
+ dash.State('subscribed_tag_machine_input', 'value'),
274
+ dash.State('machines_detailed_tabs', 'active_tab'),
275
+ dash.State('subscribed_tag_machine_input', 'options'),
276
+ dash.State("field_tag_input", "options"),
277
+ dash.State("internal_tag_input", "options"),
278
+ prevent_initial_call=True
279
+ )
280
+ def unsubscribed_on_click(
281
+ btn1,
282
+ tag_name:str,
283
+ active_tab:str,
284
+ tags_machine_options:list,
285
+ field_tags_options:list,
286
+ internal_tags_options:list
287
+ ):
288
+ r"""
289
+ Documentation here
290
+ """
291
+ if "unsubscribe_tag_machine_button" == dash.ctx.triggered_id:
292
+
293
+ machine_name = active_tab.split("-")[-1]
294
+ machine = app.automation.get_machine(name=StringType(machine_name))
295
+ tag = app.automation.get_tag_by_name(name=tag_name)
296
+ if machine.unsubscribe_to(tag=tag):
297
+
298
+ for tag_machine in tags_machine_options:
299
+ _tag_machine = tag_machine["label"].split("->")
300
+ _tag_name = _tag_machine[0]
301
+ _internal_tag = _tag_machine[-1]
302
+ if _tag_name==tag_name:
303
+
304
+ break
305
+
306
+ tags_machine_options.remove(tag_machine)
307
+ field_tags_options.append({"label": _tag_name, "value": _tag_name})
308
+ internal_tags_options.append({ "label": _internal_tag, "value": _internal_tag})
309
+
310
+ return "", tags_machine_options, field_tags_options, internal_tags_options
311
+
312
+ @app.callback(
313
+ dash.Input('machine_actions_input', 'value'),
314
+ dash.State('machines_detailed_tabs', 'active_tab'),
315
+ prevent_initial_call=True
316
+ )
317
+ def dropdown_actions(action:str, active_tab:str,):
318
+ r"""
319
+ documentation here
320
+ """
321
+ if action:
322
+
323
+ machine_name = active_tab.split("-")[-1]
324
+ message = f'are you sure you want to {action} {machine_name} state machine?'
325
+ dash.set_props("modal-question-body-action-machine", {"children": message})
326
+ dash.set_props("modal-question-action-machine", {'is_open': True})
327
+
328
+ @app.callback(
329
+ dash.Output("modal-error-subscription", "is_open"),
330
+ dash.Input("close-modal-error-button-subscription", "n_clicks"),
331
+ [dash.State("modal-error-subscription", "is_open")],
332
+ )
333
+ def close_error_button(n, is_open):
334
+ r"""
335
+ Documentation here
336
+ """
337
+ if n:
338
+
339
+ return not is_open
340
+
341
+ return is_open
342
+
343
+ @app.callback(
344
+ dash.Output("modal-question-action-machine", "is_open"),
345
+ dash.Output("question-action-machine-yes", "n_clicks"),
346
+ dash.Output("question-action-machine-no", "n_clicks"),
347
+ dash.Input("question-action-machine-yes", "n_clicks"),
348
+ dash.Input("question-action-machine-no", "n_clicks"),
349
+ dash.Input('machine_actions_input', 'value'),
350
+ dash.State('machines_detailed_tabs', 'active_tab'),
351
+ dash.State("modal-question-action-machine", "is_open"),
352
+ prevent_initial_call=True
353
+ )
354
+ def question_action_machine_yes_or_no(yes_n, no_n, action:str, active_tab:str, is_open):
355
+ r"""
356
+ Documentation here
357
+ """
358
+ if action:
359
+
360
+ if yes_n:
361
+
362
+ machine_name = active_tab.split("-")[-1]
363
+ machine = app.automation.get_machine(name=StringType(machine_name))
364
+
365
+ if action=="confirm_restart":
366
+ machine.transition(to='wait')
367
+ elif action=="confirm_reset":
368
+ machine.transition(to='start')
369
+ elif action=="deny_restart":
370
+ machine.transition(to=machine.last_state)
371
+ elif action=="deny_reset":
372
+ machine.transition(to=machine.last_state)
373
+ else:
374
+ machine.transition(to=action)
375
+
376
+ return not is_open, 0, 0
377
+
378
+ elif no_n:
379
+
380
+ return not is_open, 0, 0
381
+
382
+ else:
383
+
384
+ return True, 0, 0
385
+
386
+ else:
387
+
388
+ return False, 0, 0
389
+
390
+ @app.callback(
391
+ dash.Output('machine_threshold_input', "n_submit"),
392
+ dash.Input('machine_threshold_input', "n_submit"),
393
+ dash.State('machine_threshold_input', 'value'),
394
+ dash.State('machines_detailed_tabs', 'active_tab'),
395
+ prevent_initial_call=True
396
+ )
397
+ def update_threshold(n, threshold:float, active_tab:str):
398
+ r"""
399
+ Documentation here
400
+ """
401
+ try:
402
+ threshold = float(threshold)
403
+ except Exception as err:
404
+ return 0
405
+ machine_name = active_tab.split("-")[-1]
406
+ machine = app.automation.get_machine(name=StringType(machine_name))
407
+ machine_threshold = machine.threshold.value
408
+ if hasattr(machine_threshold, "value"):
409
+
410
+ machine_threshold = machine_threshold.value
411
+
412
+ if threshold != machine_threshold:
413
+
414
+ message = f'Do you want to change machine {machine_name} threshold from [{machine_threshold}] to: {threshold}?'
415
+ dash.set_props("modal-update-body-attr-machine", {"children": message})
416
+ dash.set_props("modal-update-attr-machine", {'is_open': True})
417
+
418
+ return 0
419
+
420
+ @app.callback(
421
+ dash.Output('machine_interval_input', "n_submit"),
422
+ dash.Input('machine_interval_input', "n_submit"),
423
+ dash.State('machine_interval_input', 'value'),
424
+ dash.State('machines_detailed_tabs', 'active_tab'),
425
+ prevent_initial_call=True
426
+ )
427
+ def update_machine_interval(n, interval:float, active_tab:str):
428
+ r"""
429
+ Documentation here
430
+ """
431
+ try:
432
+ interval = float(interval)
433
+ except Exception as err:
434
+ return 0
435
+ machine_name = active_tab.split("-")[-1]
436
+ machine = app.automation.get_machine(name=StringType(machine_name))
437
+
438
+ if interval != machine.get_interval():
439
+
440
+ message = f'Do you want to change machine {machine_name} interval from [{machine.get_interval()}] to: {interval}?'
441
+ dash.set_props("modal-update-body-attr-machine", {"children": message})
442
+ dash.set_props("modal-update-attr-machine", {'is_open': True})
443
+
444
+ return 0
445
+
446
+ @app.callback(
447
+ dash.Output('buffer_size_input', "n_submit"),
448
+ dash.Input('buffer_size_input', "n_submit"),
449
+ dash.State('buffer_size_input', 'value'),
450
+ dash.State('machines_detailed_tabs', 'active_tab'),
451
+ prevent_initial_call=True
452
+ )
453
+ def update_buffer_size(n, buffer_size:int, active_tab:str):
454
+ r"""
455
+ Documentation here
456
+ """
457
+ try:
458
+ buffer_size = int(buffer_size)
459
+ except Exception as err:
460
+ return 0
461
+ machine_name = active_tab.split("-")[-1]
462
+ machine = app.automation.get_machine(name=StringType(machine_name))
463
+
464
+ if buffer_size != machine.buffer_size.value:
465
+
466
+ message = f'Do you want to change machine {machine_name} buffer size from [{machine.buffer_size.value}] to: {buffer_size}?'
467
+ dash.set_props("modal-update-body-attr-machine", {"children": message})
468
+ dash.set_props("modal-update-attr-machine", {'is_open': True})
469
+
470
+ return 0
471
+
472
+ @app.callback(
473
+ dash.Output('on_delay_input', "n_submit"),
474
+ dash.Input('on_delay_input', "n_submit"),
475
+ dash.State('on_delay_input', 'value'),
476
+ dash.State('machines_detailed_tabs', 'active_tab'),
477
+ prevent_initial_call=True
478
+ )
479
+ def update_on_delay(n, on_delay:int, active_tab:str):
480
+ r"""
481
+ Documentation here
482
+ """
483
+ try:
484
+ on_delay = int(on_delay)
485
+ except Exception as err:
486
+ return 0
487
+ machine_name = active_tab.split("-")[-1]
488
+ machine = app.automation.get_machine(name=StringType(machine_name))
489
+
490
+ if on_delay != machine.on_delay.value:
491
+
492
+ message = f'Do you want to change machine {machine_name} on delay from [{machine.on_delay.value}] to: {on_delay}?'
493
+ dash.set_props("modal-update-body-attr-machine", {"children": message})
494
+ dash.set_props("modal-update-attr-machine", {'is_open': True})
495
+
496
+ return 0
497
+
498
+ @app.callback(
499
+ dash.Output("modal-update-attr-machine", "is_open"),
500
+ dash.Output("update-attr-machine-yes", "n_clicks"),
501
+ dash.Output("update-attr-machine-no", "n_clicks"),
502
+ dash.Output('machine_threshold_input', "value"),
503
+ dash.Output('machine_interval_input', "value"),
504
+ dash.Output('buffer_size_input', "value"),
505
+ dash.Output('on_delay_input', "value"),
506
+ dash.Input("update-attr-machine-yes", "n_clicks"),
507
+ dash.Input("update-attr-machine-no", "n_clicks"),
508
+ dash.State('machines_detailed_tabs', 'active_tab'),
509
+ dash.State("modal-update-attr-machine", "is_open"),
510
+ dash.State('machine_threshold_input', 'value'),
511
+ dash.State('machine_interval_input', 'value'),
512
+ dash.State('buffer_size_input', 'value'),
513
+ dash.State('on_delay_input', 'value'),
514
+ prevent_initial_call=True
515
+ )
516
+ def update_attr_machine_yes_or_no(
517
+ yes_n,
518
+ no_n,
519
+ active_tab:str,
520
+ is_open,
521
+ threshold:float=None,
522
+ interval:int=None,
523
+ buffer_size:int=None,
524
+ on_delay:int=None
525
+ ):
526
+ r"""
527
+ Documentation here
528
+ """
529
+ machine_name = active_tab.split("-")[-1]
530
+ machine = app.automation.get_machine(name=StringType(machine_name))
531
+ if yes_n:
532
+
533
+ if threshold:
534
+
535
+ if "leak detection" in machine.classification.value.lower():
536
+
537
+ if machine_name.lower()=="npw":
538
+
539
+ if threshold > 100:
540
+
541
+ threshold = 100
542
+
543
+ elif threshold < 0:
544
+
545
+ threshold = 0
546
+
547
+ machine.wavelet.threshold_iqr = threshold
548
+
549
+ machine.threshold.value.value = threshold
550
+ # UPDATE DB
551
+ if app.automation.is_db_connected():
552
+ app.automation.machines_engine.put(name=StringType(machine_name), threshold=FloatType(threshold))
553
+ dash.set_props("machine_threshold_input", {"placeholder": f"Current threshold {machine.threshold.value.value}"})
554
+
555
+ elif interval:
556
+
557
+ machine.set_interval(interval=IntegerType(interval))
558
+ # UPDATE DB
559
+ if app.automation.is_db_connected():
560
+ app.automation.machines_engine.put(name=StringType(machine_name), machine_interval=IntegerType(interval))
561
+ dash.set_props("machine_interval_input", {"placeholder": f"Current machine interval {machine.get_interval()}"})
562
+
563
+ elif buffer_size:
564
+
565
+ machine.set_buffer_size(size=buffer_size)
566
+ machine.transition(to="restart")
567
+ if app.automation.is_db_connected():
568
+ app.automation.machines_engine.put(name=StringType(machine_name), buffer_size=IntegerType(buffer_size))
569
+ machine.transition(to="wait")
570
+ # UPDATE DB
571
+ dash.set_props("buffer_size_input", {"placeholder": f"Current buffer size {machine.buffer_size.value}"})
572
+
573
+ elif on_delay:
574
+
575
+ machine.on_delay.value = on_delay
576
+ if app.automation.is_db_connected():
577
+ app.automation.machines_engine.put(name=StringType(machine_name), on_delay=IntegerType(on_delay))
578
+ # UPDATE DB
579
+ dash.set_props("on_delay_input", {"placeholder": f"Current on delay {machine.on_delay.value}"})
580
+
581
+ return not is_open, 0, 0, "", "", "", ""