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.
- automation/__init__.py +46 -0
- automation/alarms/__init__.py +563 -0
- automation/alarms/states.py +192 -0
- automation/alarms/trigger.py +64 -0
- automation/buffer.py +132 -0
- automation/core.py +1792 -0
- automation/dbmodels/__init__.py +23 -0
- automation/dbmodels/alarms.py +549 -0
- automation/dbmodels/core.py +86 -0
- automation/dbmodels/events.py +178 -0
- automation/dbmodels/logs.py +155 -0
- automation/dbmodels/machines.py +181 -0
- automation/dbmodels/opcua.py +81 -0
- automation/dbmodels/opcua_server.py +174 -0
- automation/dbmodels/tags.py +921 -0
- automation/dbmodels/users.py +259 -0
- automation/extensions/__init__.py +15 -0
- automation/extensions/api.py +149 -0
- automation/extensions/cors.py +18 -0
- automation/filter/__init__.py +19 -0
- automation/iad/__init__.py +3 -0
- automation/iad/frozen_data.py +54 -0
- automation/iad/out_of_range.py +51 -0
- automation/iad/outliers.py +51 -0
- automation/logger/__init__.py +0 -0
- automation/logger/alarms.py +434 -0
- automation/logger/core.py +265 -0
- automation/logger/datalogger.py +877 -0
- automation/logger/events.py +202 -0
- automation/logger/logdict.py +53 -0
- automation/logger/logs.py +203 -0
- automation/logger/machines.py +248 -0
- automation/logger/opcua_server.py +130 -0
- automation/logger/users.py +96 -0
- automation/managers/__init__.py +4 -0
- automation/managers/alarms.py +455 -0
- automation/managers/db.py +328 -0
- automation/managers/opcua_client.py +186 -0
- automation/managers/state_machine.py +183 -0
- automation/models.py +174 -0
- automation/modules/__init__.py +14 -0
- automation/modules/alarms/__init__.py +0 -0
- automation/modules/alarms/resources/__init__.py +10 -0
- automation/modules/alarms/resources/alarms.py +280 -0
- automation/modules/alarms/resources/summary.py +81 -0
- automation/modules/events/__init__.py +0 -0
- automation/modules/events/resources/__init__.py +10 -0
- automation/modules/events/resources/events.py +85 -0
- automation/modules/events/resources/logs.py +109 -0
- automation/modules/tags/__init__.py +0 -0
- automation/modules/tags/resources/__init__.py +8 -0
- automation/modules/tags/resources/tags.py +254 -0
- automation/modules/users/__init__.py +2 -0
- automation/modules/users/resources/__init__.py +10 -0
- automation/modules/users/resources/models/__init__.py +2 -0
- automation/modules/users/resources/models/roles.py +5 -0
- automation/modules/users/resources/models/users.py +14 -0
- automation/modules/users/resources/roles.py +38 -0
- automation/modules/users/resources/users.py +113 -0
- automation/modules/users/roles.py +121 -0
- automation/modules/users/users.py +335 -0
- automation/opcua/__init__.py +1 -0
- automation/opcua/models.py +541 -0
- automation/opcua/subscription.py +259 -0
- automation/pages/__init__.py +0 -0
- automation/pages/alarms.py +34 -0
- automation/pages/alarms_history.py +21 -0
- automation/pages/assets/styles.css +7 -0
- automation/pages/callbacks/__init__.py +28 -0
- automation/pages/callbacks/alarms.py +218 -0
- automation/pages/callbacks/alarms_summary.py +20 -0
- automation/pages/callbacks/db.py +222 -0
- automation/pages/callbacks/filter.py +238 -0
- automation/pages/callbacks/machines.py +29 -0
- automation/pages/callbacks/machines_detailed.py +581 -0
- automation/pages/callbacks/opcua.py +266 -0
- automation/pages/callbacks/opcua_server.py +244 -0
- automation/pages/callbacks/tags.py +495 -0
- automation/pages/callbacks/trends.py +119 -0
- automation/pages/communications.py +129 -0
- automation/pages/components/__init__.py +123 -0
- automation/pages/components/alarms.py +151 -0
- automation/pages/components/alarms_summary.py +45 -0
- automation/pages/components/database.py +128 -0
- automation/pages/components/gaussian_filter.py +69 -0
- automation/pages/components/machines.py +396 -0
- automation/pages/components/opcua.py +384 -0
- automation/pages/components/opcua_server.py +53 -0
- automation/pages/components/tags.py +253 -0
- automation/pages/components/trends.py +66 -0
- automation/pages/database.py +26 -0
- automation/pages/filter.py +55 -0
- automation/pages/machines.py +20 -0
- automation/pages/machines_detailed.py +41 -0
- automation/pages/main.py +63 -0
- automation/pages/opcua_server.py +28 -0
- automation/pages/tags.py +40 -0
- automation/pages/trends.py +35 -0
- automation/singleton.py +30 -0
- automation/state_machine.py +1674 -0
- automation/tags/__init__.py +2 -0
- automation/tags/cvt.py +1198 -0
- automation/tags/filter.py +55 -0
- automation/tags/tag.py +418 -0
- automation/tests/__init__.py +10 -0
- automation/tests/test_alarms.py +110 -0
- automation/tests/test_core.py +257 -0
- automation/tests/test_unit.py +21 -0
- automation/tests/test_user.py +155 -0
- automation/utils/__init__.py +164 -0
- automation/utils/decorators.py +222 -0
- automation/utils/npw.py +294 -0
- automation/utils/observer.py +21 -0
- automation/utils/units.py +118 -0
- automation/variables/__init__.py +55 -0
- automation/variables/adimentional.py +30 -0
- automation/variables/current.py +71 -0
- automation/variables/density.py +115 -0
- automation/variables/eng_time.py +68 -0
- automation/variables/force.py +90 -0
- automation/variables/length.py +104 -0
- automation/variables/mass.py +80 -0
- automation/variables/mass_flow.py +101 -0
- automation/variables/percentage.py +30 -0
- automation/variables/power.py +113 -0
- automation/variables/pressure.py +93 -0
- automation/variables/temperature.py +168 -0
- automation/variables/volume.py +70 -0
- automation/variables/volumetric_flow.py +100 -0
- automation/workers/__init__.py +2 -0
- automation/workers/logger.py +164 -0
- automation/workers/state_machine.py +207 -0
- automation/workers/worker.py +36 -0
- pyautomationio-1.1.1.dist-info/METADATA +199 -0
- pyautomationio-1.1.1.dist-info/RECORD +138 -0
- pyautomationio-1.1.1.dist-info/WHEEL +5 -0
- pyautomationio-1.1.1.dist-info/licenses/LICENSE +21 -0
- pyautomationio-1.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
from peewee import CharField, IntegerField, ForeignKeyField
|
|
3
|
+
from ..dbmodels.core import BaseModel
|
|
4
|
+
from ..modules.users.users import Users as CVTUsers
|
|
5
|
+
from ..modules.users.roles import Roles as CVTRoles
|
|
6
|
+
from ..modules.users.roles import Role
|
|
7
|
+
from ..modules.users.users import User
|
|
8
|
+
from werkzeug.security import generate_password_hash, check_password_hash
|
|
9
|
+
|
|
10
|
+
users = CVTUsers()
|
|
11
|
+
roles = CVTRoles()
|
|
12
|
+
|
|
13
|
+
class Roles(BaseModel):
|
|
14
|
+
|
|
15
|
+
identifier = CharField(unique=True, max_length=16)
|
|
16
|
+
name = CharField(unique=True, max_length=32)
|
|
17
|
+
level = IntegerField()
|
|
18
|
+
__defaults__ = [
|
|
19
|
+
{"name": "sudo", "level": 0, "identifier": secrets.token_hex(4)},
|
|
20
|
+
{"name": "admin", "level": 1, "identifier": secrets.token_hex(4)},
|
|
21
|
+
{"name": "supervisor", "level": 2, "identifier": secrets.token_hex(4)},
|
|
22
|
+
{"name": "operator", "level": 10, "identifier": secrets.token_hex(4)},
|
|
23
|
+
{"name": "auditor", "level": 100, "identifier": secrets.token_hex(4)},
|
|
24
|
+
{"name": "guest", "level": 256, "identifier": secrets.token_hex(4)}
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def create(cls, name:str, level:int, identifier:str)->tuple:
|
|
29
|
+
|
|
30
|
+
name = name.upper()
|
|
31
|
+
|
|
32
|
+
if cls.name_exist(name):
|
|
33
|
+
|
|
34
|
+
return None, f"role {name} is already used"
|
|
35
|
+
|
|
36
|
+
if cls.identifier_exist(identifier):
|
|
37
|
+
|
|
38
|
+
return None, f"identifier {identifier} is already used"
|
|
39
|
+
|
|
40
|
+
query = cls(name=name, level=level, identifier=identifier)
|
|
41
|
+
query.save()
|
|
42
|
+
|
|
43
|
+
return query, f"Role creation successful"
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def read_by_name(cls, name:str):
|
|
47
|
+
|
|
48
|
+
return cls.get_or_none(name=name.upper())
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def read_by_identifier(cls, identifier:str):
|
|
52
|
+
|
|
53
|
+
return cls.get_or_none(identifier=identifier)
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def name_exist(cls, name:str)->bool:
|
|
57
|
+
|
|
58
|
+
return True if cls.get_or_none(name=name.upper()) else False
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def identifier_exist(cls, identifier:str)->bool:
|
|
62
|
+
|
|
63
|
+
return True if cls.get_or_none(identifier=identifier) else False
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def read_names(cls)->list:
|
|
67
|
+
|
|
68
|
+
return [role.name for role in cls.select()]
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def fill_cvt_roles(cls):
|
|
72
|
+
r"""
|
|
73
|
+
Documentation here
|
|
74
|
+
"""
|
|
75
|
+
for role in cls.select():
|
|
76
|
+
|
|
77
|
+
_role = Role(
|
|
78
|
+
name=role.name,
|
|
79
|
+
level=role.level,
|
|
80
|
+
identifier=role.identifier
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
roles.add(role=_role)
|
|
84
|
+
|
|
85
|
+
def serialize(self)->dict:
|
|
86
|
+
r"""
|
|
87
|
+
Serialize database record to a jsonable object
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
"id": self.id,
|
|
92
|
+
"identifier": self.identifier,
|
|
93
|
+
"name": self.name,
|
|
94
|
+
"level": self.level
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class Users(BaseModel):
|
|
99
|
+
|
|
100
|
+
identifier = CharField(unique=True, max_length=16)
|
|
101
|
+
username = CharField(unique=True, max_length=64)
|
|
102
|
+
role = ForeignKeyField(Roles, backref='users', on_delete='CASCADE')
|
|
103
|
+
email = CharField(unique=True, max_length=128)
|
|
104
|
+
password = CharField()
|
|
105
|
+
token = CharField(null=True)
|
|
106
|
+
name = CharField(max_length=64, null=True)
|
|
107
|
+
lastname = CharField(max_length=64, null=True)
|
|
108
|
+
|
|
109
|
+
@classmethod
|
|
110
|
+
def create(cls, user:User)-> dict:
|
|
111
|
+
|
|
112
|
+
if cls.username_exist(user.username):
|
|
113
|
+
|
|
114
|
+
return None, f"username {user.username} is already used"
|
|
115
|
+
|
|
116
|
+
if cls.email_exist(user.email):
|
|
117
|
+
|
|
118
|
+
return None, f"email {user.email} is already used"
|
|
119
|
+
|
|
120
|
+
if cls.identifier_exist(user.identifier):
|
|
121
|
+
|
|
122
|
+
return None, f"identifier {user.identifier} is already used"
|
|
123
|
+
|
|
124
|
+
query = cls(
|
|
125
|
+
username=user.username,
|
|
126
|
+
role=Roles.read_by_name(name=user.role.name),
|
|
127
|
+
email=user.email,
|
|
128
|
+
password=user.password,
|
|
129
|
+
identifier=user.identifier,
|
|
130
|
+
name=user.name,
|
|
131
|
+
lastname=user.lastname,
|
|
132
|
+
token=user.token
|
|
133
|
+
)
|
|
134
|
+
query.save()
|
|
135
|
+
|
|
136
|
+
return query, f"User creation successful"
|
|
137
|
+
|
|
138
|
+
@classmethod
|
|
139
|
+
def login(cls, password:str, username:str="", email:str=""):
|
|
140
|
+
r"""
|
|
141
|
+
Documentation here
|
|
142
|
+
"""
|
|
143
|
+
if username:
|
|
144
|
+
|
|
145
|
+
user = cls.get_or_none(username=username)
|
|
146
|
+
|
|
147
|
+
if email:
|
|
148
|
+
|
|
149
|
+
user = cls.get_or_none(email=email)
|
|
150
|
+
|
|
151
|
+
if user:
|
|
152
|
+
|
|
153
|
+
if user.decode_password(password):
|
|
154
|
+
|
|
155
|
+
if not user.token:
|
|
156
|
+
|
|
157
|
+
user.token = cls.encode(secrets.token_hex(4))
|
|
158
|
+
user.save()
|
|
159
|
+
|
|
160
|
+
users.login(password=password, token=user.token, username=username, email=email)
|
|
161
|
+
|
|
162
|
+
return user, f"Login successfull"
|
|
163
|
+
|
|
164
|
+
return None, f"Invalid credentials"
|
|
165
|
+
|
|
166
|
+
return None, f"Invalid Username or Email"
|
|
167
|
+
|
|
168
|
+
@classmethod
|
|
169
|
+
def logout(cls, token:str):
|
|
170
|
+
r"""
|
|
171
|
+
Documentation here
|
|
172
|
+
"""
|
|
173
|
+
user = cls.get_or_none(token=token)
|
|
174
|
+
|
|
175
|
+
if user:
|
|
176
|
+
|
|
177
|
+
user.token = None
|
|
178
|
+
user.save()
|
|
179
|
+
|
|
180
|
+
return user, "Logout successfull"
|
|
181
|
+
|
|
182
|
+
return None, "Invalid Token"
|
|
183
|
+
|
|
184
|
+
@classmethod
|
|
185
|
+
def read_by_username(cls, username:str):
|
|
186
|
+
|
|
187
|
+
return cls.get_or_none(username=username)
|
|
188
|
+
|
|
189
|
+
@classmethod
|
|
190
|
+
def read_by_name(cls, name:str):
|
|
191
|
+
|
|
192
|
+
return cls.get_or_none(name=name)
|
|
193
|
+
|
|
194
|
+
@classmethod
|
|
195
|
+
def name_exist(cls, name:str)->bool:
|
|
196
|
+
|
|
197
|
+
return True if cls.get_or_none(name=name) else False
|
|
198
|
+
|
|
199
|
+
@classmethod
|
|
200
|
+
def username_exist(cls, username:str)->bool:
|
|
201
|
+
|
|
202
|
+
return True if cls.get_or_none(username=username) else False
|
|
203
|
+
|
|
204
|
+
@classmethod
|
|
205
|
+
def email_exist(cls, email:str)->bool:
|
|
206
|
+
|
|
207
|
+
return True if cls.get_or_none(email=email) else False
|
|
208
|
+
|
|
209
|
+
@classmethod
|
|
210
|
+
def identifier_exist(cls, identifier:str)->bool:
|
|
211
|
+
|
|
212
|
+
return True if cls.get_or_none(identifier=identifier) else False
|
|
213
|
+
|
|
214
|
+
@classmethod
|
|
215
|
+
def encode(cls, value:str)->str:
|
|
216
|
+
|
|
217
|
+
return generate_password_hash(value)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def decode_password(self, password:str)->str:
|
|
221
|
+
|
|
222
|
+
return check_password_hash(self.password, password)
|
|
223
|
+
|
|
224
|
+
def decode_token(self, token:str)->str:
|
|
225
|
+
|
|
226
|
+
return check_password_hash(self.token, token)
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def fill_cvt_users(cls):
|
|
230
|
+
r"""
|
|
231
|
+
Documentation here
|
|
232
|
+
"""
|
|
233
|
+
for user in cls.select():
|
|
234
|
+
|
|
235
|
+
users.signup(
|
|
236
|
+
username=user.username,
|
|
237
|
+
role_name=user.role.name,
|
|
238
|
+
email=user.email,
|
|
239
|
+
password=user.password,
|
|
240
|
+
name=user.name,
|
|
241
|
+
lastname=user.lastname,
|
|
242
|
+
identifier=user.identifier,
|
|
243
|
+
encode_password=False
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
def serialize(self)-> dict:
|
|
247
|
+
r"""
|
|
248
|
+
Serialize database record to a jsonable object
|
|
249
|
+
"""
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
"id": self.id,
|
|
253
|
+
"identifier": self.identifier,
|
|
254
|
+
"username": self.username,
|
|
255
|
+
"email": self.email,
|
|
256
|
+
"role": self.role.serialize(),
|
|
257
|
+
"name": self.name,
|
|
258
|
+
"lastname": self.lastname
|
|
259
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from .api import Api
|
|
2
|
+
from .cors import Cors
|
|
3
|
+
|
|
4
|
+
_api = Api()
|
|
5
|
+
_cors = Cors()
|
|
6
|
+
|
|
7
|
+
def init_app(app):
|
|
8
|
+
"""
|
|
9
|
+
Application extensions initialization.
|
|
10
|
+
"""
|
|
11
|
+
extensions = ( _api, _cors)
|
|
12
|
+
|
|
13
|
+
for extension in extensions:
|
|
14
|
+
|
|
15
|
+
extension.init_app(app)
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
from flask import Blueprint, request
|
|
2
|
+
from flask_restx import abort
|
|
3
|
+
from flask_restx import Api as API
|
|
4
|
+
from ..singleton import Singleton
|
|
5
|
+
from functools import wraps
|
|
6
|
+
import logging, jwt
|
|
7
|
+
from ..utils.decorators import decorator
|
|
8
|
+
from ..dbmodels.users import Users
|
|
9
|
+
from ..modules.users.users import Users as CVTUsers
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
authorizations = {
|
|
13
|
+
'apikey' : {
|
|
14
|
+
'type' : 'apiKey',
|
|
15
|
+
'in' : 'header',
|
|
16
|
+
'name' : 'X-API-KEY'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
blueprint = Blueprint('api', __name__, url_prefix='/api')
|
|
22
|
+
|
|
23
|
+
api = API(blueprint, version='1.0',
|
|
24
|
+
title='PyAutomation API',
|
|
25
|
+
description="""
|
|
26
|
+
This API groups all namespaces defined in every module's resources for PyAutomation App.
|
|
27
|
+
""",
|
|
28
|
+
doc='/docs',
|
|
29
|
+
authorizations=authorizations
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
users = CVTUsers()
|
|
33
|
+
|
|
34
|
+
class Api(Singleton):
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
|
|
38
|
+
self.app = None
|
|
39
|
+
|
|
40
|
+
def init_app(self, app):
|
|
41
|
+
r"""
|
|
42
|
+
Documentation here
|
|
43
|
+
"""
|
|
44
|
+
self.app = self.create_api(app)
|
|
45
|
+
|
|
46
|
+
return app
|
|
47
|
+
|
|
48
|
+
def create_api(self, app):
|
|
49
|
+
r"""
|
|
50
|
+
Documentation here
|
|
51
|
+
"""
|
|
52
|
+
app.register_blueprint(blueprint)
|
|
53
|
+
|
|
54
|
+
return api
|
|
55
|
+
|
|
56
|
+
@staticmethod
|
|
57
|
+
def verify_tpt(tpt:str):
|
|
58
|
+
r"""
|
|
59
|
+
Verify Third Party Token
|
|
60
|
+
"""
|
|
61
|
+
from .. import server
|
|
62
|
+
try:
|
|
63
|
+
|
|
64
|
+
jwt.decode(tpt, server.config["TPT_TOKEN"], algorithms=["HS256"])
|
|
65
|
+
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
except:
|
|
69
|
+
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def validate_reqparser(cls, reqparser):
|
|
74
|
+
def _validate_reqparser(f):
|
|
75
|
+
|
|
76
|
+
@wraps(f)
|
|
77
|
+
def decorated(*args, **kwargs):
|
|
78
|
+
|
|
79
|
+
reqparser.parse_args()
|
|
80
|
+
result = f(*args, **kwargs)
|
|
81
|
+
return result
|
|
82
|
+
|
|
83
|
+
return decorated
|
|
84
|
+
|
|
85
|
+
return _validate_reqparser
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def token_required(cls, auth:bool=False):
|
|
89
|
+
|
|
90
|
+
def _token_required(f):
|
|
91
|
+
|
|
92
|
+
@wraps(f)
|
|
93
|
+
def decorated(*args, **kwargs):
|
|
94
|
+
try:
|
|
95
|
+
|
|
96
|
+
if auth:
|
|
97
|
+
|
|
98
|
+
token = None
|
|
99
|
+
|
|
100
|
+
if 'X-API-KEY' in request.headers:
|
|
101
|
+
|
|
102
|
+
token = request.headers['X-API-KEY']
|
|
103
|
+
|
|
104
|
+
elif 'Authorization' in request.headers:
|
|
105
|
+
|
|
106
|
+
token = request.headers['Authorization'].split('Token ')[-1]
|
|
107
|
+
|
|
108
|
+
if not token:
|
|
109
|
+
|
|
110
|
+
return {'message' : 'Key is missing.'}, 401
|
|
111
|
+
|
|
112
|
+
user = Users.get_or_none(token=token)
|
|
113
|
+
|
|
114
|
+
if user:
|
|
115
|
+
|
|
116
|
+
return f(*args, **kwargs)
|
|
117
|
+
|
|
118
|
+
if Api.verify_tpt(tpt=token):
|
|
119
|
+
|
|
120
|
+
return f(*args, **kwargs)
|
|
121
|
+
|
|
122
|
+
return {'message' : 'Invalid token'}, 401
|
|
123
|
+
|
|
124
|
+
except Exception as err:
|
|
125
|
+
logger = logging.getLogger("pyautomation")
|
|
126
|
+
logger.error(str(err))
|
|
127
|
+
|
|
128
|
+
return decorated
|
|
129
|
+
|
|
130
|
+
return _token_required
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def get_current_user(cls):
|
|
134
|
+
|
|
135
|
+
token = None
|
|
136
|
+
|
|
137
|
+
if 'X-API-KEY' in request.headers:
|
|
138
|
+
|
|
139
|
+
token = request.headers['X-API-KEY']
|
|
140
|
+
|
|
141
|
+
elif 'Authorization' in request.headers:
|
|
142
|
+
|
|
143
|
+
token = request.headers['Authorization'].split('Token ')[-1]
|
|
144
|
+
|
|
145
|
+
if token:
|
|
146
|
+
|
|
147
|
+
return users.get_active_user(token=token)
|
|
148
|
+
|
|
149
|
+
return None
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from flask_cors import CORS
|
|
2
|
+
from ..singleton import Singleton
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Cors(Singleton):
|
|
6
|
+
|
|
7
|
+
def __init__(self):
|
|
8
|
+
|
|
9
|
+
self.app = None
|
|
10
|
+
|
|
11
|
+
def init_app(self, app):
|
|
12
|
+
r"""
|
|
13
|
+
Documentation here
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
self.app = CORS(app, resources={r"/*": {"origins": "*"}})
|
|
17
|
+
|
|
18
|
+
return app
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from ..utils.decorators import decorator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
@decorator
|
|
5
|
+
def filter(func, args, kwargs):
|
|
6
|
+
r"""
|
|
7
|
+
Documentation here
|
|
8
|
+
"""
|
|
9
|
+
cvt = args[0]
|
|
10
|
+
tag_id = kwargs["id"]
|
|
11
|
+
value = kwargs["value"]
|
|
12
|
+
tag = cvt.get_tag(id=tag_id)
|
|
13
|
+
if tag.gaussian_filter:
|
|
14
|
+
|
|
15
|
+
kwargs["value"] = tag.filter(value, threshold=tag.gaussian_filter_threshold, r_value=tag.gaussian_filter_r_value)
|
|
16
|
+
|
|
17
|
+
return func(*args, **kwargs)
|
|
18
|
+
|
|
19
|
+
return func(*args, **kwargs)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from ..utils.decorators import decorator
|
|
2
|
+
from ..buffer import Buffer
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
data = dict()
|
|
6
|
+
|
|
7
|
+
def __iad(data:Buffer, tag_name:str):
|
|
8
|
+
r"""
|
|
9
|
+
Frozen Data Algorithm
|
|
10
|
+
"""
|
|
11
|
+
from ..managers.alarms import AlarmManager
|
|
12
|
+
alarm_manager = AlarmManager()
|
|
13
|
+
alarm = alarm_manager.get_alarm_by_name(name=f"alarm.iad.{tag_name}")
|
|
14
|
+
|
|
15
|
+
if alarm:
|
|
16
|
+
if alarm.state.alarm_status.lower() == "not active":
|
|
17
|
+
|
|
18
|
+
mean = sum(data) / len(data)
|
|
19
|
+
variance = sum((x - mean) ** 2 for x in data) / len(data)
|
|
20
|
+
std_dev = math.sqrt(variance)
|
|
21
|
+
|
|
22
|
+
if abs(std_dev) < 0.001:
|
|
23
|
+
|
|
24
|
+
alarm.description = f"Frozen data anomaly"
|
|
25
|
+
alarm.abnormal_condition()
|
|
26
|
+
|
|
27
|
+
else:
|
|
28
|
+
|
|
29
|
+
alarm.description = ""
|
|
30
|
+
alarm.normal_condition()
|
|
31
|
+
|
|
32
|
+
@decorator
|
|
33
|
+
def iad_frozen_data(func, args, kwargs):
|
|
34
|
+
r"""
|
|
35
|
+
Documentation here
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
cvt = args[0]
|
|
39
|
+
tag_id = kwargs["id"]
|
|
40
|
+
value = kwargs["value"]
|
|
41
|
+
tag = cvt.get_tag(id=tag_id)
|
|
42
|
+
if tag.frozen_data_detection:
|
|
43
|
+
|
|
44
|
+
if tag.name not in data:
|
|
45
|
+
|
|
46
|
+
data[tag.name] = Buffer()
|
|
47
|
+
|
|
48
|
+
data[tag.name](value)
|
|
49
|
+
# Apply IAD logic
|
|
50
|
+
if len(data[tag.name]) >= data[tag.name].size:
|
|
51
|
+
|
|
52
|
+
__iad(data[tag.name], tag_name=tag.name)
|
|
53
|
+
|
|
54
|
+
return func(*args, **kwargs)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from ..utils.decorators import decorator
|
|
2
|
+
from ..buffer import Buffer
|
|
3
|
+
|
|
4
|
+
data = dict()
|
|
5
|
+
|
|
6
|
+
def __iad(data:Buffer, tag_name:str):
|
|
7
|
+
r"""
|
|
8
|
+
Out Of Range Algorithm
|
|
9
|
+
"""
|
|
10
|
+
from ..managers.alarms import AlarmManager
|
|
11
|
+
alarm_manager = AlarmManager()
|
|
12
|
+
alarm = alarm_manager.get_alarm_by_name(name=f"alarm.iad.{tag_name}")
|
|
13
|
+
if alarm:
|
|
14
|
+
if alarm.state.alarm_status.lower() == "not active":
|
|
15
|
+
|
|
16
|
+
mean = sum(data) / len(data)
|
|
17
|
+
# variance = sum((x - mean) ** 2 for x in data) / len(data)
|
|
18
|
+
# std_dev = math.sqrt(variance)
|
|
19
|
+
|
|
20
|
+
# if abs(std_dev) < 0.01:
|
|
21
|
+
|
|
22
|
+
# alarm.description = f"Out Of Range anomaly"
|
|
23
|
+
# alarm.abnormal_condition()
|
|
24
|
+
|
|
25
|
+
# else:
|
|
26
|
+
|
|
27
|
+
# alarm.description = ""
|
|
28
|
+
# alarm.normal_condition()
|
|
29
|
+
|
|
30
|
+
@decorator
|
|
31
|
+
def iad_out_of_range(func, args, kwargs):
|
|
32
|
+
r"""
|
|
33
|
+
Documentation here
|
|
34
|
+
"""
|
|
35
|
+
cvt = args[0]
|
|
36
|
+
tag_id = kwargs["id"]
|
|
37
|
+
value = kwargs["value"]
|
|
38
|
+
tag = cvt.get_tag(id=tag_id)
|
|
39
|
+
if tag.out_of_range_detection:
|
|
40
|
+
|
|
41
|
+
if tag.name not in data:
|
|
42
|
+
|
|
43
|
+
data[tag.name] = Buffer()
|
|
44
|
+
|
|
45
|
+
data[tag.name](value)
|
|
46
|
+
# Apply IAD logic
|
|
47
|
+
if len(data[tag.name]) >= data[tag.name].size:
|
|
48
|
+
|
|
49
|
+
__iad(data[tag.name], tag_name=tag.name)
|
|
50
|
+
|
|
51
|
+
return func(*args, **kwargs)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from ..utils.decorators import decorator
|
|
2
|
+
from ..buffer import Buffer
|
|
3
|
+
|
|
4
|
+
data = dict()
|
|
5
|
+
|
|
6
|
+
def __iad(data:Buffer, tag_name:str):
|
|
7
|
+
r"""
|
|
8
|
+
Outliers Algorithm
|
|
9
|
+
"""
|
|
10
|
+
from ..managers.alarms import AlarmManager
|
|
11
|
+
alarm_manager = AlarmManager()
|
|
12
|
+
alarm = alarm_manager.get_alarm_by_name(name=f"alarm.iad.{tag_name}")
|
|
13
|
+
if alarm:
|
|
14
|
+
if alarm.state.alarm_status.lower() == "not active":
|
|
15
|
+
|
|
16
|
+
mean = sum(data) / len(data)
|
|
17
|
+
# variance = sum((x - mean) ** 2 for x in data) / len(data)
|
|
18
|
+
# std_dev = math.sqrt(variance)
|
|
19
|
+
|
|
20
|
+
# if abs(std_dev) < 0.01:
|
|
21
|
+
|
|
22
|
+
# alarm.description = f"Outlier anomaly"
|
|
23
|
+
# alarm.abnormal_condition()
|
|
24
|
+
|
|
25
|
+
# else:
|
|
26
|
+
|
|
27
|
+
# alarm.description = ""
|
|
28
|
+
# alarm.normal_condition()
|
|
29
|
+
|
|
30
|
+
@decorator
|
|
31
|
+
def iad_outlier(func, args, kwargs):
|
|
32
|
+
r"""
|
|
33
|
+
Documentation here
|
|
34
|
+
"""
|
|
35
|
+
cvt = args[0]
|
|
36
|
+
tag_id = kwargs["id"]
|
|
37
|
+
value = kwargs["value"]
|
|
38
|
+
tag = cvt.get_tag(id=tag_id)
|
|
39
|
+
if tag.outlier_detection:
|
|
40
|
+
|
|
41
|
+
if tag.name not in data:
|
|
42
|
+
|
|
43
|
+
data[tag.name] = Buffer()
|
|
44
|
+
|
|
45
|
+
data[tag.name](value)
|
|
46
|
+
# Apply IAD logic
|
|
47
|
+
if len(data[tag.name]) >= data[tag.name].size:
|
|
48
|
+
|
|
49
|
+
__iad(data[tag.name], tag_name=tag.name)
|
|
50
|
+
|
|
51
|
+
return func(*args, **kwargs)
|
|
File without changes
|