PyAutomationIO 1.1.1__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 +1792 -0
  7. automation/dbmodels/__init__.py +23 -0
  8. automation/dbmodels/alarms.py +549 -0
  9. automation/dbmodels/core.py +86 -0
  10. automation/dbmodels/events.py +178 -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 +434 -0
  27. automation/logger/core.py +265 -0
  28. automation/logger/datalogger.py +877 -0
  29. automation/logger/events.py +202 -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 +81 -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 +85 -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 +254 -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 +1674 -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-1.1.1.dist-info/METADATA +199 -0
  135. pyautomationio-1.1.1.dist-info/RECORD +138 -0
  136. pyautomationio-1.1.1.dist-info/WHEEL +5 -0
  137. pyautomationio-1.1.1.dist-info/licenses/LICENSE +21 -0
  138. pyautomationio-1.1.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,257 @@
1
+ import unittest, os
2
+ from datetime import datetime
3
+ from .. import PyAutomation
4
+ from ..alarms import Alarm, AlarmState
5
+
6
+
7
+ class TestCore(unittest.TestCase):
8
+
9
+ def setUp(self) -> None:
10
+ file_path = os.path.join(".", "db", "test.db")
11
+ if os.path.exists(file_path):
12
+ os.remove(file_path)
13
+ self.app = PyAutomation()
14
+ self.app.run(debug=True, test=True, create_tables=True)
15
+ return super().setUp()
16
+
17
+ def tearDown(self) -> None:
18
+ self.app.safe_stop()
19
+ return super().tearDown()
20
+
21
+ def test_tags(self):
22
+
23
+ # CREATE TAGS
24
+ _tag1 = {
25
+ "name": "P1",
26
+ "unit": "Pa",
27
+ "variable": "Pressure"
28
+ }
29
+ tag1, _ = self.app.create_tag(**_tag1)
30
+ with self.subTest("Test tag in cvt"):
31
+
32
+ tag_in_cvt = self.app.cvt.get_tag_by_name(name=_tag1['name'])
33
+ self.assertEqual(tag1, tag_in_cvt)
34
+
35
+ # GET TAGS
36
+ _tag2 = {
37
+ "name": "T1",
38
+ "unit": "C",
39
+ "variable": "Temperature"
40
+ }
41
+ tag2, _ = self.app.create_tag(**_tag2)
42
+
43
+ # SET TAG VALUES
44
+ timestamp = datetime.now()
45
+ value = 35
46
+ self.app.cvt.set_value(id=tag2.id, value=value, timestamp=timestamp)
47
+ with self.subTest("Test Value in CVT"):
48
+
49
+ self.assertEqual(self.app.cvt.get_value(id=tag2.id), value)
50
+
51
+ # UPDATE TAGS
52
+ name = "TT"
53
+ updated_tag, _ = self.app.update_tag(id=tag2.id, name=name)
54
+ with self.subTest("Test update tag name"):
55
+
56
+ self.assertEqual(name, updated_tag.name)
57
+
58
+ with self.subTest("Test update tag name from DB"):
59
+
60
+ updated_tag = self.app.logger_engine.get_tag_by_name(name=name)
61
+ self.assertEqual(name, updated_tag.name)
62
+
63
+ unit = "K"
64
+ updated_tag, _ = self.app.update_tag(id=tag2.id, unit=unit)
65
+ with self.subTest("Test update tag unit"):
66
+
67
+ self.assertEqual(unit, updated_tag.unit)
68
+
69
+ with self.subTest("Test update tag unit from DB"):
70
+
71
+ updated_tag = self.app.logger_engine.get_tag_by_name(name=tag2.name)
72
+ self.assertEqual(unit, updated_tag.unit.unit)
73
+
74
+ # DELETE TAG
75
+ self.app.delete_tag(id=tag2.id)
76
+ with self.subTest("Test delete tag"):
77
+
78
+ self.assertIsNone(self.app.get_tag_by_name(name=tag2.name))
79
+
80
+ with self.subTest("Test delete tag from DB"):
81
+ tag = self.app.logger_engine.get_tag_by_name(name=tag2.name)
82
+ self.assertFalse(tag.active)
83
+
84
+ # DELETE TAG BY NAME
85
+ self.app.delete_tag_by_name(name=tag1.name)
86
+ with self.subTest("Test delete tag by name"):
87
+
88
+ self.assertIsNone(self.app.get_tag_by_name(name=tag1.name))
89
+
90
+ with self.subTest("Test delete tag by name from DB"):
91
+ tag = self.app.logger_engine.get_tag_by_name(name=tag1.name)
92
+ self.assertFalse(tag.active)
93
+
94
+ def test_alarms(self):
95
+ r"""
96
+ Documentation here
97
+ """
98
+
99
+ tag_payload = {
100
+ "name": "T2",
101
+ "unit": "C",
102
+ "variable": "Temperature"
103
+ }
104
+ tag, _ = self.app.create_tag(**tag_payload)
105
+
106
+ alarm_LL_payload = {
107
+ "name": "alarm_LL",
108
+ "tag": tag.name,
109
+ "alarm_type": "LOW-LOW",
110
+ "trigger_value": 10.0,
111
+ }
112
+
113
+ # CREATE ALARM
114
+ alarm_LL, _ = self.app.create_alarm(**alarm_LL_payload)
115
+ with self.subTest("Test create alarm instance"):
116
+
117
+ self.assertIsInstance(alarm_LL, Alarm)
118
+
119
+ with self.subTest("Test create alarm in alarm manager"):
120
+
121
+ self.assertEqual(alarm_LL, self.app.alarm_manager.get_alarm_by_name(name=alarm_LL.name))
122
+
123
+ alarm_L_payload = {
124
+ "name": "alarm_L",
125
+ "tag": tag.name,
126
+ "alarm_type": "LOW",
127
+ "trigger_value": 20.0,
128
+ }
129
+ alarm_L, _ = self.app.create_alarm(**alarm_L_payload)
130
+ with self.subTest("Test create alarm instance"):
131
+
132
+ self.assertIsInstance(alarm_L, Alarm)
133
+
134
+ with self.subTest("Test create alarm in alarm manager"):
135
+
136
+ self.assertEqual(alarm_L, self.app.alarm_manager.get_alarm_by_name(name=alarm_L.name))
137
+
138
+ alarm_H_payload = {
139
+ "name": "alarm_H",
140
+ "tag": tag.name,
141
+ "alarm_type": "HIGH",
142
+ "trigger_value": 30.0,
143
+ }
144
+ alarm_H, _ = self.app.create_alarm(**alarm_H_payload)
145
+ with self.subTest("Test create alarm instance"):
146
+
147
+ self.assertIsInstance(alarm_H, Alarm)
148
+
149
+ with self.subTest("Test create alarm in alarm manager"):
150
+
151
+ self.assertEqual(alarm_H, self.app.alarm_manager.get_alarm_by_name(name=alarm_H.name))
152
+
153
+ alarm_HH_payload = {
154
+ "name": "alarm_HH",
155
+ "tag": tag.name,
156
+ "alarm_type": "HIGH-HIGH",
157
+ "trigger_value": 40.0,
158
+ }
159
+ alarm_HH, _ = self.app.create_alarm(**alarm_HH_payload)
160
+ with self.subTest("Test create alarm instance"):
161
+
162
+ self.assertIsInstance(alarm_HH, Alarm)
163
+
164
+ with self.subTest("Test create alarm in alarm manager"):
165
+
166
+ self.assertEqual(alarm_HH, self.app.alarm_manager.get_alarm_by_name(name=alarm_HH.name))
167
+
168
+ # UPDATE ALARM DEFINITION
169
+ self.app.update_alarm(id=alarm_HH.identifier, trigger_value=50)
170
+ with self.subTest("Test update alarm in Alarm Manager"):
171
+
172
+ self.assertEqual(alarm_HH.alarm_setpoint.value, 50)
173
+
174
+ with self.subTest("Test update alarm in DB"):
175
+ alarm = self.app.alarms_engine.get_alarm_by_name(name=alarm_HH.name)
176
+ self.assertEqual(alarm.trigger_value, 50)
177
+
178
+ # TRIGGER ALARMS
179
+ timestamp = datetime.now()
180
+ self.app.cvt.set_value(id=tag.id, value=35, timestamp=timestamp)
181
+ with self.subTest("Test Trigger HIGH Alarm"):
182
+
183
+ self.assertEqual(alarm_H.state.alarm_status, "Active")
184
+
185
+ with self.subTest("Test check UNACK alarm state"):
186
+
187
+ self.assertEqual(alarm_H.state, AlarmState.UNACK)
188
+
189
+ with self.subTest("Test aknowledge alarm"):
190
+ alarm_H.acknowledge()
191
+ self.assertEqual(alarm_H.state, AlarmState.ACKED)
192
+
193
+ with self.subTest("Test not Trigger HIGH-HIGH Alarm"):
194
+
195
+ self.assertEqual(alarm_HH.state.alarm_status, "Not Active")
196
+
197
+ self.app.cvt.set_value(id=tag.id, value=0, timestamp=timestamp)
198
+ with self.subTest("Test Trigger LOW Alarm"):
199
+
200
+ self.assertEqual(alarm_L.state.alarm_status, "Active")
201
+
202
+ with self.subTest("Test Trigger LOW-LOW Alarm"):
203
+
204
+ self.assertEqual(alarm_LL.state.alarm_status, "Active")
205
+
206
+ with self.subTest("Test check UNACK alarm LL state"):
207
+
208
+ self.assertEqual(alarm_LL.state, AlarmState.UNACK)
209
+
210
+ with self.subTest("Test check UNACK alarm L state"):
211
+
212
+ self.assertEqual(alarm_L.state, AlarmState.UNACK)
213
+
214
+ self.app.cvt.set_value(id=tag.id, value=15, timestamp=timestamp)
215
+ with self.subTest("Test check UNACK alarm LL state"):
216
+
217
+ self.assertEqual(alarm_LL.state, AlarmState.RTNUN)
218
+
219
+ with self.subTest("Test aknowledge LL alarm"):
220
+ alarm_LL.acknowledge()
221
+ self.assertEqual(alarm_LL.state, AlarmState.NORM)
222
+
223
+ with self.subTest("Test aknowledge L alarm"):
224
+ alarm_L.acknowledge()
225
+ self.assertEqual(alarm_L.state, AlarmState.ACKED)
226
+
227
+
228
+ # Boolean Alarm
229
+ tag_payload = {
230
+ "name": "Bool1",
231
+ "unit": "adim",
232
+ "variable": "Adimentional"
233
+ }
234
+ tag, _ = self.app.create_tag(**tag_payload)
235
+ alarm_B_payload = {
236
+ "name": "alarm_B",
237
+ "tag": tag.name,
238
+ "alarm_type": "BOOL",
239
+ "trigger_value": True,
240
+ }
241
+ alarm_B, _ = self.app.create_alarm(**alarm_B_payload)
242
+
243
+ with self.subTest("Test Not Trigger BOOL Alarm"):
244
+
245
+ self.assertEqual(alarm_B.state.alarm_status, "Not Active")
246
+
247
+ self.app.cvt.set_value(id=tag.id, value=True, timestamp=timestamp)
248
+ with self.subTest("Test Trigger BOOL Alarm"):
249
+
250
+ self.assertEqual(alarm_B.state.alarm_status, "Active")
251
+
252
+ # DELETE TAG
253
+ self.app.delete_alarm(id=alarm_LL.identifier)
254
+ self.app.delete_alarm(id=alarm_L.identifier)
255
+ self.app.delete_alarm(id=alarm_H.identifier)
256
+ self.app.delete_alarm(id=alarm_HH.identifier)
257
+ self.app.delete_tag(id=tag.id)
@@ -0,0 +1,21 @@
1
+ import unittest
2
+ from ..variables import (Pressure)
3
+
4
+ class TestConversions(unittest.TestCase):
5
+
6
+ def setUp(self) -> None:
7
+
8
+ return super().setUp()
9
+
10
+ def tearDown(self) -> None:
11
+
12
+ return super().tearDown()
13
+
14
+ def test_pressure_conversions(self):
15
+
16
+ value = 10
17
+ from_unit = "atm"
18
+ to_unit = "psi"
19
+ expected = 146.959
20
+
21
+ self.assertAlmostEqual(Pressure.convert_value(value, from_unit=from_unit, to_unit=to_unit), expected, delta=0.001)
@@ -0,0 +1,155 @@
1
+ import unittest
2
+ from . import assert_dict_contains_subset
3
+ from ..modules.users.users import Users, User
4
+ from ..modules.users.roles import roles, Role
5
+
6
+ USERNAME = "user1"
7
+ ROLE_NAME = "admin"
8
+ EMAIL = "jhon.doe@gmail.com"
9
+ PASSWORD = "123456"
10
+ NAME = "Jhon"
11
+ LASTNAME = "Doe"
12
+
13
+ USERNAME2 = "user2"
14
+ EMAIL2 = "jhon.doe2@gmail.com"
15
+
16
+ class TestUsers(unittest.TestCase):
17
+
18
+ def setUp(self) -> None:
19
+
20
+ self.roles = roles
21
+ self.roles._delete_all()
22
+ self.users = Users()
23
+ self.users._delete_all()
24
+
25
+ return super().setUp()
26
+
27
+ def tearDown(self) -> None:
28
+ delattr(self, "roles")
29
+ delattr(self, "users")
30
+ return super().tearDown()
31
+
32
+ def test_create_role(self):
33
+
34
+ admin = Role(name="admin", level=0)
35
+ expected = {
36
+ "name": "admin",
37
+ "level": 0
38
+ }
39
+ assert_dict_contains_subset(expected, admin.serialize())
40
+
41
+ def test_add_role_to_repo(self):
42
+
43
+ admin = Role(name="admin", level=0)
44
+ self.roles.add(role=admin)
45
+ self.assertIn(admin, self.roles.roles.values())
46
+
47
+ def test_get_role(self):
48
+
49
+ admin = Role(name="admin", level=0)
50
+ admin_id, _ = self.roles.add(role=admin)
51
+ self.assertEqual(admin, self.roles.get(id=admin_id))
52
+
53
+ def test_get_role_by_name(self):
54
+
55
+ admin = Role(name="admin", level=0)
56
+ self.roles.add(role=admin)
57
+ self.assertEqual(admin, self.roles.get_by_name(name=admin.name))
58
+
59
+ def test_get_role_names(self):
60
+
61
+ roles = ["sudo", "admin", "operator"]
62
+ for role in roles:
63
+ _role = Role(name=role, level=0)
64
+ self.roles.add(role=_role)
65
+
66
+ self.assertListEqual(roles, self.roles.get_names())
67
+
68
+ def test_put_role(self):
69
+
70
+ role = Role(name="admin", level=0)
71
+ role_id, _ = self.roles.add(role=role)
72
+ self.roles.put(id=role_id, name="sudo")
73
+ self.assertEqual(role.name, "sudo")
74
+
75
+ def test_delete_role(self):
76
+
77
+ roles = ["sudo", "admin", "operator"]
78
+ for role in roles:
79
+ _role = Role(name=role, level=0)
80
+ role_id = self.roles.add(role=_role)
81
+ role = self.roles.get(id=role_id)
82
+ self.roles.delete(id=role_id)
83
+ self.assertNotIn(role, self.roles.roles.values())
84
+
85
+ def test_signup(self):
86
+
87
+ role = Role(name=ROLE_NAME, level=0)
88
+ self.roles.add(role=role)
89
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
90
+ self.assertIsInstance(user, User)
91
+
92
+ def test_login_logout(self):
93
+
94
+ role = Role(name=ROLE_NAME, level=0)
95
+ self.roles.add(role=role)
96
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
97
+ with self.subTest("Test Login"):
98
+
99
+ self.assertTrue(self.users.login(password="123456", username="user1"))
100
+
101
+ with self.subTest("Test Active user"):
102
+
103
+ self.assertEqual(user, self.users.get_active_user(token=user.token))
104
+
105
+ with self.subTest("Test Logout"):
106
+
107
+ self.users.logout(user.token)
108
+ self.assertIsNone(self.users.get_active_user(token=user.token))
109
+
110
+ def test_login_fail(self):
111
+
112
+ role = Role(name=ROLE_NAME, level=0)
113
+ self.roles.add(role=role)
114
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
115
+ self.assertFalse(self.users.login(password=user.password, username="user1"))
116
+
117
+ def test_get_user(self):
118
+
119
+ role = Role(name=ROLE_NAME, level=0)
120
+ self.roles.add(role=role)
121
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
122
+ self.assertEqual(user, self.users.get(identifier=user.identifier))
123
+
124
+ def test_get_by_username(self):
125
+
126
+ role = Role(name=ROLE_NAME, level=0)
127
+ self.roles.add(role=role)
128
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
129
+ self.assertEqual(user, self.users.get_by_username(username=USERNAME))
130
+
131
+ def test_get_by_email(self):
132
+
133
+ role = Role(name=ROLE_NAME, level=0)
134
+ self.roles.add(role=role)
135
+ user, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
136
+ self.assertEqual(user, self.users.get_by_email(email=EMAIL))
137
+
138
+ def test_get_active_user(self):
139
+
140
+ role = Role(name=ROLE_NAME, level=0)
141
+ self.roles.add(role=role)
142
+ user1, _ = self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
143
+ self.users.signup(username=USERNAME2, role_name=ROLE_NAME, email=EMAIL2, password=PASSWORD, name=NAME, lastname=LASTNAME)
144
+ self.users.login(password=PASSWORD, username=USERNAME)
145
+ self.assertEqual(user1, self.users.get_active_user(token=user1.token))
146
+
147
+ def test_get_not_active_user(self):
148
+
149
+ role = Role(name=ROLE_NAME, level=0)
150
+ self.roles.add(role=role)
151
+ self.users.signup(username=USERNAME, role_name=ROLE_NAME, email=EMAIL, password=PASSWORD, name=NAME, lastname=LASTNAME)
152
+ user2, _ = self.users.signup(username=USERNAME2, role_name=ROLE_NAME, email=EMAIL2, password=PASSWORD, name=NAME, lastname=LASTNAME)
153
+ self.users.login(password=PASSWORD, username=USERNAME)
154
+ self.assertIsNone(self.users.get_active_user(token=user2.token))
155
+
@@ -0,0 +1,164 @@
1
+ import logging
2
+ from .observer import Observer
3
+ from ..variables import VARIABLES
4
+ from ..alarms.states import ACTIONS
5
+
6
+ def log_detailed(e, message):
7
+ logger = logging.getLogger("pyautomation")
8
+ logger.error(message)
9
+ logger.error(e, exc_info=True)
10
+
11
+ def chunks(lst, n):
12
+ for i in range(0, len(lst), n):
13
+ yield lst[i:i + n]
14
+
15
+ def find_differences_between_lists(prev_list, curr_list):
16
+ r"""
17
+ Documentation here
18
+ """
19
+
20
+ differences = []
21
+
22
+ for prev_dict, curr_dict in zip(prev_list, curr_list):
23
+ diff = {'id': prev_dict['id']}
24
+ for key in prev_dict:
25
+ if prev_dict[key] != curr_dict[key]:
26
+ diff[key] = curr_dict[key]
27
+ if len(diff) > 1: # Only add if there are differences other than 'id'
28
+ differences.append(diff)
29
+
30
+ return differences
31
+
32
+ def find_differences_between_lists_opcua_server(prev_list, curr_list):
33
+ r"""
34
+ Documentation here
35
+ """
36
+
37
+ differences = []
38
+
39
+ for prev_dict, curr_dict in zip(prev_list, curr_list):
40
+ diff = {'name': prev_dict['name'], 'namespace': prev_dict['namespace']}
41
+
42
+ for key in prev_dict:
43
+ if prev_dict[key] != curr_dict[key]:
44
+ diff[key] = curr_dict[key]
45
+ if len(diff) > 2: # Only add if there are differences other than 'id'
46
+ differences.append(diff)
47
+
48
+ return differences
49
+
50
+ def find_keys_values_by_unit(d, unit):
51
+ r"""
52
+ Documentation here
53
+ """
54
+ result = []
55
+
56
+ for _, sub_dict in d.items():
57
+
58
+ if unit in sub_dict.values():
59
+
60
+ for k, v in sub_dict.items():
61
+
62
+ result.append({'label': k, 'value': v})
63
+
64
+ return result
65
+
66
+ def generate_dropdown_conditional():
67
+ r"""
68
+ Documentation here
69
+ """
70
+ from .. import PyAutomation
71
+ app = PyAutomation()
72
+ data = VARIABLES
73
+ dropdown_conditional = []
74
+ # dropdown conditional for unit column in table
75
+ for variable, sub_dict in data.items():
76
+
77
+ for unit in sub_dict.values():
78
+
79
+ options = find_keys_values_by_unit(data, unit)
80
+
81
+ dropdown_conditional.append({
82
+ 'if': {'column_id': 'unit', 'filter_query': f'{{variable}} eq "{variable}"'},
83
+ 'options': options,
84
+ 'clearable': False
85
+ })
86
+
87
+ dropdown_conditional.append({
88
+ 'if': {'column_id': 'display_unit', 'filter_query': f'{{variable}} eq "{variable}"'},
89
+ 'options': options,
90
+ 'clearable': False
91
+ })
92
+
93
+ # dropdown conditional for node_namespace column in table
94
+ dropdown_conditional.append({
95
+ 'if': {'column_id': 'node_namespace', 'filter_query': f'{{opcua_address}} eq ""'},
96
+ 'options': []
97
+ })
98
+ for client_name, info in app.get_opcua_clients().items():
99
+
100
+ tree = app.get_opcua_tree(client_name=client_name)
101
+ options = list()
102
+ for node in tree[0]["Objects"][0]["children"]:
103
+ options.append({
104
+ "label": node["title"],
105
+ "value": node["key"]
106
+ })
107
+ server = info['server_url']
108
+ dropdown_conditional.append({
109
+ 'if': {'column_id': 'node_namespace', 'filter_query': f'{{opcua_address}} eq "{server}"'},
110
+ 'options': options
111
+ })
112
+
113
+ return dropdown_conditional
114
+
115
+ def get_nodes_info(selected_files:list):
116
+ r"""
117
+ Documentation here
118
+ """
119
+ to_get_node_values = dict()
120
+ for file in selected_files:
121
+
122
+ if file:
123
+
124
+ info = file[0].split("/")
125
+ client_name = info[0]
126
+ namespace = info[1]
127
+
128
+ if client_name in to_get_node_values:
129
+
130
+ to_get_node_values[client_name].append(namespace)
131
+
132
+ else:
133
+
134
+ to_get_node_values[client_name] = [namespace]
135
+
136
+ return to_get_node_values
137
+
138
+ def get_data_to_update_into_opcua_table(app, to_get_node_values:dict):
139
+ r"""
140
+ Documentation here
141
+ """
142
+ data = list()
143
+ for client_name, namespaces in to_get_node_values.items():
144
+
145
+ infos = app.automation.get_node_attributes(client_name=client_name, namespaces=namespaces)
146
+
147
+ if infos:
148
+
149
+ for info in infos:
150
+ _info = info[0]
151
+ namespace = _info["Namespace"]
152
+ data.append(
153
+ {
154
+ "server": client_name,
155
+ "namespace": namespace,
156
+ "data_type": _info["DataType"],
157
+ "display_name": _info["DisplayName"],
158
+ "value": _info["Value"],
159
+ "source_timestamp": _info["DataValue"].SourceTimestamp,
160
+ "status_code": _info["DataValue"].StatusCode.name
161
+ }
162
+ )
163
+
164
+ return data