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,253 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from ...variables import VARIABLES
4
+
5
+ class TagsComponents:
6
+
7
+ @classmethod
8
+ def create_tag_form(cls):
9
+ r"""
10
+ Documentation here
11
+ """
12
+ return dash.html.Div(
13
+ [
14
+ dash.dcc.Location(id='tags_page', refresh=False),
15
+ dbc.Accordion(
16
+ [
17
+ dbc.AccordionItem(
18
+ [
19
+ dbc.Row(
20
+ [
21
+ dbc.Col(
22
+ [
23
+ dbc.InputGroup(
24
+ [
25
+ dbc.Input(placeholder="Tag Name", id="tag_name_input")
26
+ ],
27
+ size="md",
28
+ className="mb-3"
29
+ ),
30
+ dbc.InputGroup(
31
+ [
32
+ dbc.InputGroupText("Variable"),
33
+ dbc.Select(
34
+ options=[
35
+ {"label": variable, "value": variable} for variable in VARIABLES.keys()
36
+ ],
37
+ id="variable_input"
38
+ ),
39
+ ],
40
+ size="md",
41
+ className="mb-3"
42
+ ),
43
+ dbc.InputGroup(
44
+ [
45
+ dbc.InputGroupText("Datatype"),
46
+ dbc.Select(
47
+ options=[
48
+ {'label': 'Float', 'value': 'float'},
49
+ {'label': 'Integer', 'value': 'integer'},
50
+ {'label': 'Boolean', 'value': 'boolean'},
51
+ {'label': 'String', 'value': 'string'}
52
+ ],
53
+ id="datatype_input"
54
+ ),
55
+ ],
56
+ size="md"
57
+ )
58
+ ],
59
+ width=12,
60
+ className="col-sm-12 col-md-3"
61
+ ),
62
+
63
+ dbc.Col(
64
+ [
65
+ dbc.InputGroup(
66
+ [
67
+ dbc.InputGroupText("Unit"), dbc.Select(options=[], id="unit_input", disabled=True )
68
+ ],
69
+ size="md",
70
+ className="mb-3"
71
+ ),
72
+ dbc.InputGroup(
73
+ [
74
+ dbc.InputGroupText("Display Unit"), dbc.Select(options=[], id="display_unit_input", disabled=True )
75
+ ],
76
+ size="md",
77
+ className="mb-3"
78
+ ),
79
+ dbc.InputGroup(
80
+ [
81
+ dbc.Input(placeholder="Manufacturer (Optional)", id="manufacturer_input", disabled=True)
82
+ ],
83
+ size="md"
84
+ )
85
+
86
+ ],
87
+ width=12,
88
+ className="col-sm-12 col-md-2"
89
+ ),
90
+
91
+ dbc.Col(
92
+ [
93
+ dbc.InputGroup(
94
+ [
95
+ dbc.InputGroupText(dbc.RadioButton(id="description_radio_button"), class_name="radiobutton-box"),
96
+ dbc.Input(placeholder="Description (Optional)", id="description_input", disabled=True)
97
+ ],
98
+ size="md",
99
+ className="mb-3"
100
+ ),
101
+ dbc.InputGroup(
102
+ [
103
+ dbc.InputGroupText(dbc.RadioButton(id="display_name_radio_button"), className="radiobutton-box"),
104
+ dbc.Input(placeholder="Display Name (Optional)", id="display_name_input", disabled=True)
105
+ ],
106
+ size="md",
107
+ className="mb-3"
108
+ ),
109
+ dbc.InputGroup(
110
+ [
111
+ dbc.InputGroupText(dbc.RadioButton(id="segment_radio_button"), className="radiobutton-box"),
112
+ dbc.Input(placeholder="Segment (Optional)", id="segment_input", disabled=True)
113
+ ],
114
+ size="md"
115
+ )
116
+ ],
117
+ width=12,
118
+ className="col-sm-12 col-md-3"
119
+ ),
120
+
121
+ dbc.Col(
122
+ [
123
+ dbc.InputGroup(
124
+ [
125
+ dbc.InputGroupText("OPCUA"),
126
+ dbc.Select(options=[], id="opcua_address_input")
127
+ ],
128
+ size="md",
129
+ className="mb-3"
130
+ ),
131
+ dbc.InputGroup(
132
+ [
133
+ dbc.InputGroupText("Node"),
134
+ dbc.Select(options=[], id="node_namespace_input", disabled=True)
135
+ ],
136
+ size="md"
137
+ )
138
+ ],
139
+ width=12,
140
+ className="col-sm-12 col-md-2"
141
+ ),
142
+
143
+ dbc.Col(
144
+ [
145
+ dbc.InputGroup(
146
+ [
147
+ dbc.Input(placeholder="Scan Time", type="number", step=500, min=500, max=600000, id="scan_time_input", disabled=True),
148
+ dbc.InputGroupText('ms')
149
+ ],
150
+ size="md",
151
+ className="mb-3"
152
+ ),
153
+ dbc.InputGroup(
154
+ [
155
+ dbc.Input(placeholder="Dead-Band", type="number", step=0.1, id="dead_band_input", disabled=True),
156
+ dbc.InputGroupText('', id="dead_band_unit")
157
+ ],
158
+ size="md"
159
+ )
160
+ ],
161
+ width=12,
162
+ className="col-sm-12 col-md-2"
163
+ ),
164
+
165
+ dbc.Col(
166
+ dbc.Button(
167
+ "Create",
168
+ color="primary",
169
+ outline=True,
170
+ disabled=True,
171
+ id="create_tag_button",
172
+ className="w-100"
173
+ ),
174
+ width="auto",
175
+ className="d-flex justify-content-center align-items-center"
176
+ ),
177
+ ],
178
+ className="form g-3"
179
+ ),
180
+ ],
181
+ title="Create Tag",
182
+ className="my-3"
183
+ )
184
+ ],
185
+ start_collapsed=True,
186
+ )
187
+ ]
188
+ )
189
+
190
+ @classmethod
191
+ def tags_table(cls)->dash.dash_table.DataTable:
192
+ r"""
193
+ Documentation here
194
+ """
195
+ return dbc.Container(
196
+ dbc.Row(
197
+ dbc.Col(
198
+ dash.dash_table.DataTable(
199
+ data=[],
200
+ columns=[
201
+ {'name': 'id', 'id': 'id', 'editable': False},
202
+ {'name': 'name', 'id': 'name'},
203
+ {'name': 'variable', 'id': 'variable', 'presentation': 'dropdown', 'clearable': False},
204
+ {'name': 'unit', 'id': 'unit', 'presentation': 'dropdown'},
205
+ {'name': 'display_unit', 'id': 'display_unit', 'presentation': 'dropdown'},
206
+ {'name': 'data_type', 'id': 'data_type', 'presentation': 'dropdown', 'clearable': False},
207
+ {'name': 'description', 'id': 'description'},
208
+ {'name': 'display_name', 'id': 'display_name'},
209
+ {'name': 'segment', 'id': 'segment', 'presentation': 'dropdown'},
210
+ {'name': 'opcua_address', 'id': 'opcua_address', 'presentation': 'dropdown'},
211
+ {'name': 'node_namespace', 'id': 'node_namespace', 'presentation': 'dropdown'},
212
+ {'name': 'scan_time', 'id': 'scan_time', 'type': 'numeric'},
213
+ {'name': 'dead_band', 'id': 'dead_band', 'type': 'numeric'}
214
+ ],
215
+ id="tags_datatable",
216
+ filter_action="native",
217
+ sort_action="native",
218
+ sort_mode="multi",
219
+ row_deletable=True,
220
+ selected_columns=[],
221
+ dropdown = {
222
+ 'data_type': {
223
+ 'options': [
224
+ {'label': 'Float', 'value': 'float'},
225
+ {'label': 'Integer', 'value': 'integer'},
226
+ {'label': 'Boolean', 'value': 'boolean'},
227
+ {'label': 'String', 'value': 'string'}
228
+ ],
229
+ 'clearable': False
230
+ },
231
+ 'opcua_address': {
232
+ 'options': []
233
+ },
234
+ 'variable': {
235
+ 'options': [{"label": key, "value": key} for key, _ in VARIABLES.items()]
236
+ }
237
+ },
238
+ page_action="native",
239
+ page_current= 0,
240
+ page_size= 10,
241
+ persistence=True,
242
+ editable=True,
243
+ persisted_props=['data'],
244
+ export_format='xlsx',
245
+ export_headers='display',
246
+ style_table={'overflowX': 'auto'},
247
+ ),
248
+ width=12,
249
+ )
250
+ ),
251
+ fluid=True,
252
+ className="mx-0 px-0"
253
+ )
@@ -0,0 +1,66 @@
1
+ import dash
2
+ import plotly.graph_objects as go
3
+
4
+ fig = go.Figure()
5
+
6
+ class TrendsComponents:
7
+
8
+ @classmethod
9
+ def tags(cls)->dash.dcc.Dropdown:
10
+ r"""
11
+ Documentation here
12
+ """
13
+ return dash.dcc.Dropdown(
14
+ options = [],
15
+ multi=True,
16
+ id="trends_tags_dropdown",
17
+ persistence=True
18
+ )
19
+
20
+ @classmethod
21
+ def last_values(cls)->dash.dcc.Dropdown:
22
+ r"""
23
+ Documentation here
24
+ """
25
+ return dash.dcc.Dropdown(
26
+ options=[
27
+ {'label': 'last 10 seconds', 'value': 10},
28
+ {'label': 'last 30 seconds', 'value': 30},
29
+ {'label': 'last minute', 'value': 60},
30
+ {'label': 'last 2 min.', 'value': 2 * 60},
31
+ {'label': 'last 5 min.', 'value': 5 * 60},
32
+ {'label': 'last 10 min.', 'value': 10 * 60}
33
+ ],
34
+ value=10,
35
+ clearable=False,
36
+ id="trends_last_values_dropdown"
37
+ )
38
+
39
+ @classmethod
40
+ def current_value_table(cls)->dash.dash_table.DataTable:
41
+ r"""
42
+ Documentation here
43
+ """
44
+ return dash.dash_table.DataTable(
45
+ data=[],
46
+ columns=[
47
+ {'name': 'tag', 'id': 'tag'},
48
+ {'name': 'value', 'id': 'value'}
49
+ ],
50
+ id="trends_cvt_datatable",
51
+ selected_columns=[],
52
+ page_action="native",
53
+ page_current= 0,
54
+ page_size= 10,
55
+ persistence=True,
56
+ persisted_props=['data']
57
+ )
58
+
59
+ @classmethod
60
+ def plot(cls)->dash.dcc.Graph:
61
+ r"""
62
+ Documentation here
63
+ """
64
+ return dash.dcc.Graph(
65
+ figure=fig,
66
+ id="trends_figure")
@@ -0,0 +1,26 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components import Components
4
+ from automation.pages.components.database import DatabaseComponents
5
+
6
+ dash.register_page(__name__)
7
+
8
+ layout = dbc.Container(
9
+ [
10
+ dbc.Breadcrumb(
11
+ items=[
12
+ {"label": "Home", "href": "/"},
13
+ {"label": "Database", "active": True},
14
+ ],
15
+ ),
16
+ DatabaseComponents.create_db_config_form(),
17
+ Components.modal_error(
18
+ title="Database Connection",
19
+ modal_id="modal-db-connection",
20
+ button_close_id="close-model-db-connection",
21
+ body_id="modal-body-db-connection"
22
+ )
23
+ ],
24
+ fluid=False,
25
+ className="my-3"
26
+ )
@@ -0,0 +1,55 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components import Components
4
+ from automation.pages.components.gaussian_filter import FilterComponents
5
+
6
+ dash.register_page(__name__)
7
+
8
+ layout = dbc.Container(
9
+ [
10
+ dbc.Breadcrumb(
11
+ items=[
12
+ {"label": "Home", "href": "/"},
13
+ {"label": "Tags", "href": "/tags"},
14
+ {"label": "Filter", "active": True},
15
+ ],
16
+ ),
17
+ dash.dcc.Location(id='filter_page', refresh=False),
18
+ dbc.Row(
19
+ [
20
+ dbc.Col(FilterComponents.tags(), width=6, className="col-sm-6 col-md-10"),
21
+ dbc.Col(FilterComponents.last_values(), width=6, className="col-sm-6 col-md-2 ps-0"),
22
+ ],
23
+ className="mb-3"
24
+ ),
25
+ dbc.Row(
26
+ [
27
+ dbc.Col(FilterComponents.current_value_table(), width=12, className="col-sm-12 col-md-12 mb-2"),
28
+ dbc.Col(FilterComponents.plot(), width=12, className="col-sm-12 col-md-12"),
29
+ ],
30
+ className="mb-3"
31
+ ),
32
+ Components.modal_error(
33
+ title="Error",
34
+ modal_id="modal-error-filter-tags",
35
+ button_close_id="close-modal-error-filter",
36
+ body_id="modal-error-filter-tags-body"
37
+ ),
38
+ Components.modal_error(
39
+ title="Success",
40
+ modal_id="modal-success-filter-tags",
41
+ button_close_id="close-modal-success-filter-tags",
42
+ body_id="modal-success--filter-tags-body"
43
+ ),
44
+ Components.modal_confirm(
45
+ title="Confirmation",
46
+ modal_id="modal-update-filter-tags",
47
+ body_id="modal-update-filter-tags-body",
48
+ yes_button_id="update-filter-tags-yes",
49
+ no_button_id="update-filter-tags-no"
50
+ ),
51
+ ],
52
+ fluid=False,
53
+ className="my-3"
54
+ )
55
+
@@ -0,0 +1,20 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components.machines import MachinesComponents
4
+
5
+ dash.register_page(__name__)
6
+
7
+ layout = dbc.Container(
8
+ [
9
+ dbc.Breadcrumb(
10
+ items=[
11
+ {"label": "Home", "href": "/"}, # Primer nivel
12
+ {"label": "Machines", "active": True}, # Página actual (sin enlace)
13
+ ],
14
+ ),
15
+ dash.dcc.Location(id='machines_page', refresh=False),
16
+ MachinesComponents.machines_table()
17
+ ],
18
+ fluid=False,
19
+ className="my-3",
20
+ )
@@ -0,0 +1,41 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components import Components
4
+ from automation.pages.components.machines import MachinesComponents
5
+
6
+ dash.register_page(__name__)
7
+
8
+ layout = dbc.Container(
9
+ [
10
+ dbc.Breadcrumb(
11
+ items=[
12
+ {"label": "Home", "href": "/"}, # Primer nivel
13
+ {"label": "Machines Detailed", "active": True}, # Página actual (sin enlace)
14
+ ],
15
+ ),
16
+ dash.dcc.Location(id='machines_detailed_page', refresh=False),
17
+ MachinesComponents.machines_tabs(),
18
+ Components.modal_error(
19
+ title="Error",
20
+ modal_id="modal-error-subscription",
21
+ button_close_id="close-modal-error-button-subscription",
22
+ body_id="modal-error-body-subscription"
23
+ ),
24
+ Components.modal_confirm(
25
+ title="Confirmation",
26
+ modal_id="modal-question-action-machine",
27
+ body_id="modal-question-body-action-machine",
28
+ yes_button_id="question-action-machine-yes",
29
+ no_button_id="question-action-machine-no"
30
+ ),
31
+ Components.modal_confirm(
32
+ title="Confirmation",
33
+ modal_id="modal-update-attr-machine",
34
+ body_id="modal-update-body-attr-machine",
35
+ yes_button_id="update-attr-machine-yes",
36
+ no_button_id="update-attr-machine-no"
37
+ ),
38
+ ],
39
+ fluid=False,
40
+ className="my-3",
41
+ )
@@ -0,0 +1,63 @@
1
+ import dash
2
+ from ..pages.components import Components
3
+
4
+
5
+ class ConfigView(dash.Dash):
6
+ r"""
7
+ Documentation here
8
+ """
9
+
10
+ def __init__(self, **kwargs):
11
+
12
+ super(ConfigView, self).__init__(__name__, suppress_callback_exceptions=True, **kwargs)
13
+
14
+ self.layout = dash.html.Div([
15
+ dash.dcc.Interval(id='timestamp-interval', interval=1000, n_intervals=0),
16
+ Components.navbar(),
17
+ dash.page_container
18
+ ])
19
+
20
+ def set_automation_app(self, automation_app):
21
+
22
+ self.automation = automation_app
23
+
24
+ def tags_table_data(self):
25
+
26
+ tags = list()
27
+ for tag in self.automation.get_tags():
28
+ if tag["segment"] and tag["manufacturer"]:
29
+ tag.update({
30
+ "segment": f"{tag['manufacturer']}->{tag['segment']}"
31
+ })
32
+ tag.pop('values')
33
+ tag.pop("timestamps")
34
+ tags.append(tag)
35
+
36
+ return tags
37
+
38
+ def alarms_table_data(self):
39
+ data = [{
40
+ "id": alarm["identifier"],
41
+ "tag": alarm["tag"],
42
+ "name": alarm["name"],
43
+ "description": alarm["description"],
44
+ "state": alarm["state"]["state"],
45
+ "alarm_type": alarm["alarm_setpoint"]["type"],
46
+ "trigger_value": alarm["alarm_setpoint"]["value"],
47
+ } for alarm in self.automation.alarm_manager.serialize()]
48
+
49
+ return data
50
+
51
+ def machines_table_data(self):
52
+
53
+ data = [{
54
+ "name": machine["name"],
55
+ "sampling_time": machine["machine_interval"],
56
+ "description": machine["description"],
57
+ "state": machine["state"],
58
+ "criticity": machine["criticity"],
59
+ "priority": machine["priority"],
60
+ "classification": machine["classification"],
61
+ } for machine in self.automation.machine_manager.serialize_machines()]
62
+
63
+ return data
@@ -0,0 +1,28 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components import Components
4
+ from automation.pages.components.opcua_server import OPCUAServerComponents
5
+
6
+ dash.register_page(__name__)
7
+
8
+ layout = dbc.Container(
9
+ [
10
+ dash.dcc.Location(id='opcua_server', refresh=False),
11
+ dbc.Breadcrumb(
12
+ items=[
13
+ {"label": "Communications", "href": "/"},
14
+ {"label": "OPCUA Server", "active": True},
15
+ ],
16
+ ),
17
+ Components.modal_confirm(
18
+ title="Confirmation",
19
+ modal_id="modal-update-opcua-server-centered",
20
+ body_id="modal-update-opcua-server-body",
21
+ yes_button_id="update-opcua-server-yes",
22
+ no_button_id="update-opcua-server-no"
23
+ ),
24
+ OPCUAServerComponents.opcua_server_table()
25
+ ],
26
+ fluid=False,
27
+ className="my-3"
28
+ )
@@ -0,0 +1,40 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components import Components
4
+ from automation.pages.components.tags import TagsComponents
5
+
6
+ dash.register_page(__name__)
7
+
8
+ layout = dbc.Container(
9
+ [
10
+ dbc.Breadcrumb(
11
+ items=[
12
+ {"label": "Home", "href": "/"},
13
+ {"label": "Tags", "active": True},
14
+ ],
15
+ ),
16
+ Components.modal_error(
17
+ title="Error",
18
+ modal_id="modal-centered",
19
+ button_close_id="close-centered",
20
+ body_id="modal-body"
21
+ ),
22
+ Components.modal_error(
23
+ title="Success",
24
+ modal_id="modal-success",
25
+ button_close_id="close-success",
26
+ body_id="modal-success-body"
27
+ ),
28
+ Components.modal_confirm(
29
+ title="Confirmation",
30
+ modal_id="modal-update_delete-centered",
31
+ body_id="modal-update-delete-tag-body",
32
+ yes_button_id="update-delete-tag-yes",
33
+ no_button_id="update-delete-tag-no"
34
+ ),
35
+ TagsComponents.create_tag_form(),
36
+ TagsComponents.tags_table()
37
+ ],
38
+ fluid=False,
39
+ className="my-3"
40
+ )
@@ -0,0 +1,35 @@
1
+ import dash
2
+ import dash_bootstrap_components as dbc
3
+ from automation.pages.components.trends import TrendsComponents
4
+
5
+ dash.register_page(__name__)
6
+
7
+ layout = dbc.Container(
8
+ [
9
+ dbc.Breadcrumb(
10
+ items=[
11
+ {"label": "Home", "href": "/"},
12
+ {"label": "Tags", "href": "/tags"},
13
+ {"label": "Trends", "active": True},
14
+ ],
15
+ ),
16
+ dash.dcc.Location(id='trends_page', refresh=False),
17
+ dbc.Row(
18
+ [
19
+ dbc.Col(TrendsComponents.tags(), width=6, className="col-sm-6 col-md-10"),
20
+ dbc.Col(TrendsComponents.last_values(), width=6, className="col-sm-6 col-md-2 ps-0"),
21
+ ],
22
+ className="mb-3"
23
+ ),
24
+ dbc.Row(
25
+ [
26
+ dbc.Col(TrendsComponents.current_value_table(), width=12, className="col-sm-12 col-md-2 mb-2"),
27
+ dbc.Col(TrendsComponents.plot(), width=12, className="col-sm-12 col-md-10"),
28
+ ],
29
+ className="mb-3"
30
+ ),
31
+ ],
32
+ fluid=False,
33
+ className="my-3"
34
+ )
35
+
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ """pyhades/_singleton.py
3
+
4
+ This module implements a singleton pattern design, a base class for
5
+ inheritance in other classes
6
+ """
7
+ from weakref import WeakValueDictionary
8
+
9
+ class SingletonMeta(type):
10
+ """
11
+ The Singleton class can be implemented in different ways in Python. Some
12
+ possible methods include: base class, decorator, metaclass. We will use the
13
+ metaclass because it is best suited for this purpose.
14
+ """
15
+ _instances = WeakValueDictionary()
16
+
17
+ def __call__(cls, *args, **kwargs):
18
+ if cls not in cls._instances:
19
+ # This variable declaration is required to force a
20
+ # strong reference on the instance.
21
+ instance = super().__call__(*args, **kwargs)
22
+ cls._instances[cls] = instance
23
+ return cls._instances[cls]
24
+
25
+
26
+
27
+ class Singleton(metaclass=SingletonMeta):
28
+ """
29
+ The Singleton with simple class name.
30
+ """