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,153 @@
1
+ import pytz
2
+ from peewee import CharField, TimestampField, ForeignKeyField, IntegerField, fn
3
+ from ..dbmodels.core import BaseModel
4
+ from datetime import datetime
5
+ from .users import Users
6
+ from ..modules.users.users import User
7
+
8
+ DATETIME_FORMAT = "%m/%d/%Y, %H:%M:%S.%f"
9
+
10
+
11
+ class Events(BaseModel):
12
+
13
+ timestamp = TimestampField(utc=True)
14
+ message = CharField(max_length=256)
15
+ description = CharField(max_length=256, null=True)
16
+ classification = CharField(max_length=128, null=True)
17
+ priority = IntegerField(null=True)
18
+ criticity = IntegerField(null=True)
19
+ user = ForeignKeyField(Users, backref='events')
20
+
21
+ @classmethod
22
+ def create(
23
+ cls,
24
+ message:str,
25
+ user:User,
26
+ description:str=None,
27
+ classification:str=None,
28
+ priority:int=None,
29
+ criticity:int=None,
30
+ timestamp:datetime=None
31
+ )->tuple:
32
+
33
+ if not isinstance(user, User):
34
+
35
+ return None, f"User {user} - {type(user)} must be an User Object"
36
+
37
+ user = Users.read_by_username(username=user.username)
38
+
39
+ if not timestamp:
40
+
41
+ timestamp = datetime.now(pytz.UTC)
42
+
43
+ if not isinstance(timestamp, datetime):
44
+
45
+ return None, f"Timestamp must be a datetime Object"
46
+
47
+ query = cls(
48
+ message=message,
49
+ user=user,
50
+ description=description,
51
+ classification=classification,
52
+ priority=priority,
53
+ criticity=criticity,
54
+ timestamp=timestamp
55
+ )
56
+ query.save()
57
+
58
+ return query, f"Event creation successful"
59
+
60
+ @classmethod
61
+ def read_lasts(cls, lasts:int=1):
62
+ r"""
63
+ Documentation here
64
+ """
65
+ events = cls.select().order_by(cls.id.desc()).limit(lasts)
66
+
67
+ return [event.serialize() for event in events]
68
+
69
+ @classmethod
70
+ def filter_by(
71
+ cls,
72
+ usernames:list[str]=None,
73
+ priorities:list[int]=None,
74
+ criticities:list[int]=None,
75
+ greater_than_timestamp:datetime=None,
76
+ less_than_timestamp:datetime=None,
77
+ description:str="",
78
+ message:str="",
79
+ classification:str="",
80
+ timezone:str='UTC'):
81
+ r"""
82
+ Documentation here
83
+ """
84
+ _timezone = pytz.timezone(timezone)
85
+ query = cls.select()
86
+
87
+ if usernames:
88
+ subquery = Users.select(Users.id).where(Users.username.in_(usernames))
89
+ query = query.join(Users).where(Users.id.in_(subquery))
90
+
91
+ if priorities:
92
+ query = query.where(cls.priority.in_(priorities))
93
+
94
+ if criticities:
95
+ query = query.where(cls.criticity.in_(criticities))
96
+
97
+ if description:
98
+ query = query.where(fn.LOWER(cls.description).contains(description.lower()))
99
+
100
+ if message:
101
+ query = query.where(fn.LOWER(cls.message).contains(message.lower()))
102
+
103
+ if classification:
104
+ query = query.where(fn.LOWER(cls.classification).contains(classification.lower()))
105
+
106
+ if greater_than_timestamp:
107
+ greater_than_timestamp = _timezone.localize(datetime.strptime(greater_than_timestamp, '%Y-%m-%d %H:%M:%S.%f')).astimezone(pytz.UTC)
108
+ query = query.where(cls.timestamp > greater_than_timestamp)
109
+
110
+ if less_than_timestamp:
111
+ less_than_timestamp = _timezone.localize(datetime.strptime(less_than_timestamp, '%Y-%m-%d %H:%M:%S.%f')).astimezone(pytz.UTC)
112
+ query = query.where(cls.timestamp < less_than_timestamp)
113
+
114
+ query = query.order_by(cls.id.desc())
115
+
116
+ if not query.exists():
117
+
118
+ return []
119
+
120
+ return [event.serialize() for event in query]
121
+
122
+ @classmethod
123
+ def get_comments(cls, id:int):
124
+ r"""
125
+ Documentation here
126
+ """
127
+ query = cls.read(id=id)
128
+
129
+ return [comment.serialize() for comment in query.logs]
130
+
131
+ def serialize(self)-> dict:
132
+ from .. import TIMEZONE, MANUFACTURER, SEGMENT
133
+ timestamp = self.timestamp
134
+ if timestamp:
135
+
136
+ timestamp = timestamp.astimezone(TIMEZONE)
137
+ timestamp = timestamp.strftime(DATETIME_FORMAT)
138
+
139
+ return {
140
+ "id": self.id,
141
+ "timestamp": timestamp,
142
+ "user": self.user.serialize(),
143
+ "message": self.message,
144
+ "description": self.description,
145
+ "classification": self.classification,
146
+ "priority": self.priority,
147
+ "criticity": self.criticity,
148
+ "segment": SEGMENT,
149
+ "manufacturer": MANUFACTURER,
150
+ "has_comments": True if self.logs else False
151
+ }
152
+
153
+
@@ -0,0 +1,155 @@
1
+ import pytz
2
+ from peewee import CharField, TimestampField, ForeignKeyField, fn
3
+ from ..dbmodels.core import BaseModel
4
+ from datetime import datetime
5
+ from .users import Users
6
+ from .events import Events
7
+ from .alarms import AlarmSummary, Alarms
8
+ from ..modules.users.users import User
9
+
10
+ DATETIME_FORMAT = "%m/%d/%Y, %H:%M:%S.%f"
11
+
12
+
13
+ class Logs(BaseModel):
14
+
15
+ timestamp = TimestampField(utc=True)
16
+ message = CharField(max_length=256)
17
+ description = CharField(max_length=256, null=True)
18
+ classification = CharField(max_length=128, null=True)
19
+ user = ForeignKeyField(Users, backref='logs', on_delete='CASCADE')
20
+ alarm = ForeignKeyField(AlarmSummary, null=True, backref='logs', on_delete='CASCADE')
21
+ event = ForeignKeyField(Events, null=True, backref='logs', on_delete='CASCADE')
22
+
23
+ @classmethod
24
+ def create(
25
+ cls,
26
+ message:str,
27
+ user:User,
28
+ description:str=None,
29
+ classification:str=None,
30
+ alarm_summary_id:int=None,
31
+ event_id:int=None,
32
+ timestamp:datetime=None
33
+ )->tuple:
34
+ if not isinstance(user, User):
35
+
36
+ return None, f"User {user} - {type(user)} must be an User Object"
37
+
38
+ _user = Users.read_by_username(username=user.username)
39
+
40
+ if not timestamp:
41
+
42
+ timestamp = datetime.now()
43
+
44
+ if not isinstance(timestamp, datetime):
45
+
46
+ return None, f"Timestamp must be a datetime Object"
47
+
48
+ query = cls(
49
+ message=message,
50
+ user=_user,
51
+ description=description,
52
+ classification=classification,
53
+ timestamp=timestamp,
54
+ event=Events.get_or_none(id=event_id),
55
+ alarm=AlarmSummary.get_or_none(id=alarm_summary_id)
56
+ )
57
+ query.save()
58
+
59
+ return query, f"Event creation successful"
60
+
61
+ @classmethod
62
+ def read_lasts(cls, lasts:int=1):
63
+ r"""
64
+ Documentation here
65
+ """
66
+ logs = cls.select().order_by(cls.id.desc()).limit(lasts)
67
+
68
+ return [log.serialize() for log in logs]
69
+
70
+ @classmethod
71
+ def filter_by(
72
+ cls,
73
+ usernames:list[str]=None,
74
+ alarm_names:list[str]=None,
75
+ event_ids:list[int]=None,
76
+ description:str="",
77
+ message:str="",
78
+ classification:str="",
79
+ greater_than_timestamp:datetime=None,
80
+ less_than_timestamp:datetime=None,
81
+ timezone:str='UTC'
82
+ ):
83
+ r"""
84
+ Documentation here
85
+ """
86
+ _timezone = pytz.timezone(timezone)
87
+ query = cls.select()
88
+
89
+ if usernames:
90
+ subquery = Users.select(Users.id).where(Users.username.in_(usernames))
91
+ query = query.join(Users).where(Users.id.in_(subquery))
92
+
93
+ if event_ids:
94
+ subquery = Events.select(Events.id).where(Events.id.in_(event_ids))
95
+ query = query.join(Events).where(Events.id.in_(subquery))
96
+
97
+ if alarm_names:
98
+ subquery = Alarms.select(Alarms.id).where(Alarms.name.in_(alarm_names))
99
+ alarm_subquery = AlarmSummary.select(AlarmSummary.id).join(Alarms).where(Alarms.id.in_(subquery))
100
+ query = query.join(AlarmSummary).where(AlarmSummary.id.in_(alarm_subquery))
101
+
102
+ if description:
103
+ query = query.where(fn.LOWER(cls.description).contains(description.lower()))
104
+
105
+ if message:
106
+ query = query.where(fn.LOWER(cls.message).contains(message.lower()))
107
+
108
+ if classification:
109
+ query = query.where(fn.LOWER(cls.classification).contains(classification.lower()))
110
+
111
+ if greater_than_timestamp:
112
+ greater_than_timestamp = _timezone.localize(datetime.strptime(greater_than_timestamp, '%Y-%m-%d %H:%M:%S.%f')).astimezone(pytz.UTC)
113
+ query = query.where(cls.timestamp > greater_than_timestamp)
114
+
115
+ if less_than_timestamp:
116
+ less_than_timestamp = _timezone.localize(datetime.strptime(less_than_timestamp, '%Y-%m-%d %H:%M:%S.%f')).astimezone(pytz.UTC)
117
+ query = query.where(cls.timestamp < less_than_timestamp)
118
+
119
+ query = query.order_by(cls.id.desc())
120
+
121
+ if not query.exists():
122
+
123
+ return []
124
+
125
+ return [log.serialize() for log in query]
126
+
127
+ def serialize(self)-> dict:
128
+ from .. import MANUFACTURER, SEGMENT, TIMEZONE
129
+ timestamp = self.timestamp
130
+ if timestamp:
131
+ timestamp = pytz.UTC.localize(timestamp).astimezone(TIMEZONE)
132
+ timestamp = timestamp.strftime(DATETIME_FORMAT)
133
+
134
+ _event = None
135
+ if self.event:
136
+
137
+ _event = self.event.serialize()
138
+
139
+ _alarm = None
140
+ if self.alarm:
141
+
142
+ _alarm = self.alarm.serialize()
143
+
144
+ return {
145
+ "id": self.id,
146
+ "timestamp": timestamp,
147
+ "user": self.user.serialize(),
148
+ "message": self.message,
149
+ "description": self.description,
150
+ "classification": self.classification,
151
+ "event": _event,
152
+ "alarm": _alarm,
153
+ "segment": SEGMENT,
154
+ "manufacturer": MANUFACTURER
155
+ }
@@ -0,0 +1,181 @@
1
+ from peewee import CharField, IntegerField, ForeignKeyField, FloatField
2
+ from .core import BaseModel
3
+ from .tags import Tags
4
+
5
+
6
+ class Machines(BaseModel):
7
+
8
+ identifier = CharField(unique=True)
9
+ name = CharField(unique=True)
10
+ interval = FloatField()
11
+ threshold = FloatField(null=True)
12
+ on_delay = IntegerField(null=True)
13
+ description = CharField(max_length=128)
14
+ classification = CharField(max_length=128)
15
+ buffer_size = IntegerField()
16
+ buffer_roll_type = CharField(max_length=16)
17
+ criticity = IntegerField()
18
+ priority = IntegerField()
19
+
20
+ @classmethod
21
+ def create(
22
+ cls,
23
+ identifier:str,
24
+ name:str,
25
+ interval:int,
26
+ description:str,
27
+ classification:str,
28
+ buffer_size:int,
29
+ buffer_roll_type:str,
30
+ criticity:int,
31
+ priority:int,
32
+ threshold:float=None,
33
+ on_delay:int=None
34
+ )-> dict:
35
+
36
+ result = dict()
37
+ data = dict()
38
+
39
+ if not cls.name_exist(name):
40
+
41
+ query = cls(
42
+ identifier=identifier,
43
+ name=name,
44
+ interval=interval,
45
+ description=description,
46
+ classification=classification,
47
+ buffer_size=buffer_size,
48
+ buffer_roll_type=buffer_roll_type,
49
+ criticity=criticity,
50
+ priority=priority,
51
+ threshold=threshold,
52
+ on_delay=on_delay
53
+ )
54
+ query.save()
55
+
56
+ message = f"Machine {name} created successfully"
57
+ data.update(query.serialize())
58
+
59
+ result.update(
60
+ {
61
+ 'message': message,
62
+ 'data': data
63
+ }
64
+ )
65
+ return result
66
+
67
+ message = f"Machine {name} is already into database"
68
+ result.update(
69
+ {
70
+ 'message': message,
71
+ 'data': data
72
+ }
73
+ )
74
+ return result
75
+
76
+ @classmethod
77
+ def read_by_name(cls, name:str)->bool:
78
+ query = cls.get_or_none(name=name)
79
+
80
+ if query is not None:
81
+
82
+ return query
83
+
84
+ return None
85
+
86
+ @classmethod
87
+ def read_config(cls):
88
+ r"""
89
+ Select all records
90
+
91
+ You can use this method to retrieve all instances matching in the database.
92
+
93
+ This method is a shortcut that calls Model.select() with the given query.
94
+
95
+ **Parameters**
96
+
97
+ **Returns**
98
+
99
+ * **result:** (dict) --> {'message': (str), 'data': (list) row serialized}
100
+ """
101
+ return {f"{query.name}": query.serialize() for query in cls.select()}
102
+
103
+ @classmethod
104
+ def name_exist(cls, name:str)->bool:
105
+ r"""
106
+ Verify is a name exist into database
107
+
108
+ **Parameters**
109
+
110
+ * **name:** (str) Variable name
111
+
112
+ **Returns**
113
+
114
+ * **bool:** If True, name exist into database
115
+ """
116
+ query = cls.get_or_none(name=name)
117
+
118
+ if query is not None:
119
+
120
+ return True
121
+
122
+ return False
123
+
124
+ def get_tags(self):
125
+
126
+ return self.tags
127
+
128
+ def serialize(self)-> dict:
129
+ r"""
130
+ Serialize database record to a jsonable object
131
+ """
132
+
133
+ return {
134
+ "id": self.id,
135
+ "identifier": self.identifier,
136
+ "name": self.name,
137
+ "interval": self.interval,
138
+ "description": self.description,
139
+ "classification": self.classification,
140
+ "buffer_size": self.buffer_size,
141
+ "buffer_roll_type": self.buffer_roll_type,
142
+ "criticity": self.criticity,
143
+ "priority": self.priority,
144
+ "threshold": self.threshold,
145
+ "on_delay": self.on_delay
146
+ }
147
+
148
+
149
+ class TagsMachines(BaseModel):
150
+
151
+ tag = ForeignKeyField(Tags, backref="machines")
152
+ machine = ForeignKeyField(Machines, backref="tags")
153
+ default_tag_name = CharField(max_length=64, null=True)
154
+
155
+ @classmethod
156
+ def create(
157
+ cls,
158
+ tag_name:str,
159
+ machine_name:str,
160
+ default_tag_name:str=None
161
+ )-> dict:
162
+
163
+ tag = Tags.get_or_none(name=tag_name)
164
+ machine = Machines.get_or_none(name=machine_name)
165
+
166
+ if not cls.get_or_none(tag=tag, machine=machine):
167
+
168
+ query = cls(
169
+ tag=tag,
170
+ machine=machine,
171
+ default_tag_name=default_tag_name
172
+ )
173
+ query.save()
174
+
175
+ def serialize(self):
176
+
177
+ return {
178
+ "machine": self.machine.serialize(),
179
+ "tag": self.tag.serialize(),
180
+ "default_tag_name": self.default_tag_name
181
+ }
@@ -0,0 +1,81 @@
1
+ from peewee import CharField, IntegerField
2
+ from ..dbmodels.core import BaseModel
3
+
4
+ class OPCUA(BaseModel):
5
+
6
+ client_name = CharField(unique=True)
7
+ host = CharField()
8
+ port = IntegerField()
9
+
10
+ @classmethod
11
+ def create(cls, client_name:str, host:str, port:int):
12
+ r"""
13
+ You can use Model.create() to create a new model instance. This method accepts keyword arguments, where the keys correspond
14
+ to the names of the model's fields. A new instance is returned and a row is added to the table.
15
+
16
+ ```python
17
+ >>> AlarmsType.create(name='High-High')
18
+ {
19
+ 'message': (str)
20
+ 'data': (dict) {
21
+ 'name': 'HIGH-HIGH'
22
+ }
23
+ }
24
+ ```
25
+
26
+ This will INSERT a new row into the database. The primary key will automatically be retrieved and stored on the model instance.
27
+
28
+ **Parameters**
29
+
30
+ * **name:** (str), Industrial protocol name
31
+
32
+ **Returns**
33
+
34
+ * **result:** (dict) --> {'message': (str), 'data': (dict) row serialized}
35
+
36
+ """
37
+
38
+ if not cls.client_name_exist(client_name):
39
+
40
+ query = cls(client_name=client_name, host=host, port=port)
41
+ query.save()
42
+
43
+ return query
44
+
45
+ @classmethod
46
+ def get_by_client_name(cls, client_name:str):
47
+ r"""
48
+ Documentation here
49
+ """
50
+ return cls.get_or_none(client_name=client_name)
51
+
52
+ @classmethod
53
+ def client_name_exist(cls, client_name:str):
54
+ r"""
55
+ Verify is a name exist into database
56
+
57
+ **Parameters**
58
+
59
+ * **name:** (str) Variable name
60
+
61
+ **Returns**
62
+
63
+ * **bool:** If True, name exist into database
64
+ """
65
+ query = cls.get_or_none(client_name=client_name)
66
+
67
+ if query is not None:
68
+
69
+ return True
70
+
71
+ return False
72
+
73
+ def serialize(self):
74
+ r"""
75
+ Documentation here
76
+ """
77
+ return {
78
+ "client_name": self.client_name,
79
+ "host": self.host,
80
+ "port": self.port
81
+ }