python-terminusgps 25.1.0__py3-none-any.whl → 27.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.
Potentially problematic release.
This version of python-terminusgps might be problematic. Click here for more details.
- {python_terminusgps-25.1.0.dist-info → python_terminusgps-27.0.0.dist-info}/METADATA +1 -1
- {python_terminusgps-25.1.0.dist-info → python_terminusgps-27.0.0.dist-info}/RECORD +14 -15
- terminusgps/twilio/validators.py +6 -0
- terminusgps/wialon/items/base.py +52 -65
- terminusgps/wialon/items/resource.py +5 -1
- terminusgps/wialon/items/retranslator.py +5 -1
- terminusgps/wialon/items/route.py +5 -1
- terminusgps/wialon/items/unit.py +13 -10
- terminusgps/wialon/items/unit_group.py +5 -39
- terminusgps/wialon/items/user.py +5 -1
- terminusgps/wialon/session.py +4 -5
- terminusgps/wialon/utils.py +30 -27
- terminusgps/aws/ses.py +0 -72
- {python_terminusgps-25.1.0.dist-info → python_terminusgps-27.0.0.dist-info}/WHEEL +0 -0
- {python_terminusgps-25.1.0.dist-info → python_terminusgps-27.0.0.dist-info}/licenses/COPYING +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version:
|
|
3
|
+
Version: 27.0.0
|
|
4
4
|
Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
|
|
5
5
|
Project-URL: Documentation, https://app.terminusgps.com/docs/apps/python-terminusgps/index.html
|
|
6
6
|
Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
|
|
@@ -13,25 +13,24 @@ terminusgps/authorizenet/subscriptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JC
|
|
|
13
13
|
terminusgps/authorizenet/subscriptions/subscriptions.py,sha256=yg0rZw0Zzm3v7daLPR0PsdfCWBU6RyoE_gNPDBMkCjM,1621
|
|
14
14
|
terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
terminusgps/aws/secrets.py,sha256=MxQEmmBLpMUQ2tYAsHdCYf-7RZ84LiogdKcTsACX5dw,361
|
|
16
|
-
terminusgps/aws/ses.py,sha256=sDca2GjMaZvUt3kUPtGCpcqHiOkij9lMV1ogZofgYUU,2372
|
|
17
16
|
terminusgps/twilio/__init__.py,sha256=dYo41F2jft_eHDWSUtSpKGSRG1bewq_qClqilUJZkYM,33
|
|
18
17
|
terminusgps/twilio/caller.py,sha256=TiQ4f0TDDC35he1M1iSsBM2vutdGriwtV4pc17T--6I,3552
|
|
19
|
-
terminusgps/twilio/validators.py,sha256=
|
|
18
|
+
terminusgps/twilio/validators.py,sha256=nn7CCBTktNjcln6M4MR0ACxEsClgioSu89LRLgIiBZk,1112
|
|
20
19
|
terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
20
|
terminusgps/wialon/constants.py,sha256=n1ux68oWYWnzeZdN811Iw_Lk78KBM0YMJMoonn67uZY,1723
|
|
22
21
|
terminusgps/wialon/flags.py,sha256=_NIL3mrEGhvI5YISVjimjYtUatdgOqhZPJX368MtKSU,13959
|
|
23
22
|
terminusgps/wialon/logger.py,sha256=nUBsaLMaffSaAHGHAM6mFXDzix9hbNecVtA3INVtii8,968
|
|
24
|
-
terminusgps/wialon/session.py,sha256=
|
|
25
|
-
terminusgps/wialon/utils.py,sha256=
|
|
23
|
+
terminusgps/wialon/session.py,sha256=THl88yfVBfRH8daKh1lmLSR8ro8TbyOokHx1Cev-En8,9638
|
|
24
|
+
terminusgps/wialon/utils.py,sha256=QXBksDJlC0_khuJ6n9HEYlUQB9ArM-Pvh-K0xHORvDs,6917
|
|
26
25
|
terminusgps/wialon/items/__init__.py,sha256=3BVthghekMvhMQSzQgBMlD_phxmKSmp3Zvmo-z0O8Bs,211
|
|
27
|
-
terminusgps/wialon/items/base.py,sha256=
|
|
28
|
-
terminusgps/wialon/items/resource.py,sha256=
|
|
29
|
-
terminusgps/wialon/items/retranslator.py,sha256=
|
|
30
|
-
terminusgps/wialon/items/route.py,sha256=
|
|
31
|
-
terminusgps/wialon/items/unit.py,sha256=
|
|
32
|
-
terminusgps/wialon/items/unit_group.py,sha256=
|
|
33
|
-
terminusgps/wialon/items/user.py,sha256=
|
|
34
|
-
python_terminusgps-
|
|
35
|
-
python_terminusgps-
|
|
36
|
-
python_terminusgps-
|
|
37
|
-
python_terminusgps-
|
|
26
|
+
terminusgps/wialon/items/base.py,sha256=GCSzhDc3bk-jltWYNL60BEYCeSNRsPWos5aeFvgye8Y,7208
|
|
27
|
+
terminusgps/wialon/items/resource.py,sha256=vNR6hJmf23RxsqXpDhM0dODbQB8KKTKcy6ncjpEZty8,14610
|
|
28
|
+
terminusgps/wialon/items/retranslator.py,sha256=vauuaLoEdKQF0FnOvJfksmLKsIlxvGZxt80dLTh3SVs,3789
|
|
29
|
+
terminusgps/wialon/items/route.py,sha256=8SzlqNmpYVdt-ZAY--B_KHoDIHgN0Zb7KBsBWAzoz3s,1209
|
|
30
|
+
terminusgps/wialon/items/unit.py,sha256=i7sQiRu3N0XxyTHVN2RnmjYy9X48KdnZLSB18ic37w8,9363
|
|
31
|
+
terminusgps/wialon/items/unit_group.py,sha256=YsYh34l2DjSKcv5SIZkEVi5FSjveGB1gxU2fwdLyvl4,4101
|
|
32
|
+
terminusgps/wialon/items/user.py,sha256=PFYBie04F16YE2B5364PLxkmlTmQr4sZXpItvRBxsDc,7143
|
|
33
|
+
python_terminusgps-27.0.0.dist-info/METADATA,sha256=z36oD2rqxZYskS3SuUT3pqdXzt8ZWmIjVL3MUOBhmZs,946
|
|
34
|
+
python_terminusgps-27.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
35
|
+
python_terminusgps-27.0.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
36
|
+
python_terminusgps-27.0.0.dist-info/RECORD,,
|
terminusgps/twilio/validators.py
CHANGED
|
@@ -11,6 +11,12 @@ def validate_phone_number(value: str) -> None:
|
|
|
11
11
|
code="invalid",
|
|
12
12
|
params={"value": value},
|
|
13
13
|
)
|
|
14
|
+
if not value[1:].isdigit():
|
|
15
|
+
raise ValidationError(
|
|
16
|
+
_("Phone number must be '+' followed by a digit, got '%(value)s'"),
|
|
17
|
+
code="invalid",
|
|
18
|
+
params={"value": value},
|
|
19
|
+
)
|
|
14
20
|
if len(value) < min_length:
|
|
15
21
|
raise ValidationError(
|
|
16
22
|
_("Phone number cannot be less than %(min)s characters, got %(len)s."),
|
terminusgps/wialon/items/base.py
CHANGED
|
@@ -75,131 +75,119 @@ class WialonBase:
|
|
|
75
75
|
|
|
76
76
|
:param new_name: A new name.
|
|
77
77
|
:type new_name: :py:obj:`str`
|
|
78
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
78
79
|
:returns: Nothing.
|
|
79
80
|
:rtype: :py:obj:`None`
|
|
80
81
|
|
|
81
82
|
"""
|
|
82
|
-
|
|
83
83
|
self.session.wialon_api.item_update_name(
|
|
84
84
|
**{"itemId": self.id, "name": new_name}
|
|
85
85
|
)
|
|
86
86
|
|
|
87
|
-
def add_afield(self,
|
|
87
|
+
def add_afield(self, key: str, value: str) -> None:
|
|
88
88
|
"""
|
|
89
89
|
Adds an admin field to the Wialon object.
|
|
90
90
|
|
|
91
|
-
:param
|
|
92
|
-
:type
|
|
91
|
+
:param key: A key (name) for the admin field.
|
|
92
|
+
:type key: :py:obj:`str`
|
|
93
|
+
:param value: A value for the admin field.
|
|
94
|
+
:type value: :py:obj:`str`
|
|
95
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
93
96
|
:returns: Nothing.
|
|
94
97
|
:rtype: :py:obj:`None`
|
|
95
98
|
|
|
96
99
|
"""
|
|
97
|
-
|
|
98
100
|
self.session.wialon_api.item_update_admin_field(
|
|
99
|
-
**{
|
|
100
|
-
"itemId": self.id,
|
|
101
|
-
"id": 0,
|
|
102
|
-
"callMode": "create",
|
|
103
|
-
"n": field[0],
|
|
104
|
-
"v": field[1],
|
|
105
|
-
}
|
|
101
|
+
**{"itemId": self.id, "id": 0, "callMode": "create", "n": key, "v": value}
|
|
106
102
|
)
|
|
107
103
|
|
|
108
|
-
def update_afield(self,
|
|
104
|
+
def update_afield(self, id: int, key: str, value: str) -> None:
|
|
109
105
|
"""
|
|
110
|
-
Updates an admin field by id
|
|
106
|
+
Updates an admin field by id.
|
|
111
107
|
|
|
112
|
-
:param
|
|
113
|
-
:type
|
|
114
|
-
:param
|
|
115
|
-
:type
|
|
108
|
+
:param id: The admin field id.
|
|
109
|
+
:type id: :py:obj:`int`
|
|
110
|
+
:param key: A key (name) for the admin field.
|
|
111
|
+
:type key: :py:obj:`str`
|
|
112
|
+
:param value: A value for the admin field.
|
|
113
|
+
:type value: :py:obj:`str`
|
|
114
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
116
115
|
:returns: Nothing.
|
|
117
116
|
:rtype: :py:obj:`None`
|
|
118
117
|
|
|
119
118
|
"""
|
|
120
|
-
|
|
121
119
|
self.session.wialon_api.item_update_admin_field(
|
|
122
|
-
**{
|
|
123
|
-
"itemId": self.id,
|
|
124
|
-
"id": field_id,
|
|
125
|
-
"callMode": "update",
|
|
126
|
-
"n": field[0],
|
|
127
|
-
"v": field[1],
|
|
128
|
-
}
|
|
120
|
+
**{"itemId": self.id, "id": id, "callMode": "update", "n": key, "v": value}
|
|
129
121
|
)
|
|
130
122
|
|
|
131
|
-
def add_cfield(self,
|
|
123
|
+
def add_cfield(self, key: str, value: str) -> None:
|
|
132
124
|
"""
|
|
133
125
|
Adds a custom field to the Wialon object.
|
|
134
126
|
|
|
135
|
-
:param
|
|
136
|
-
:type
|
|
127
|
+
:param key: A key (name) for the custom field.
|
|
128
|
+
:type key: :py:obj:`str`
|
|
129
|
+
:param value: A value for the custom field.
|
|
130
|
+
:type value: :py:obj:`str`
|
|
131
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
137
132
|
:returns: Nothing.
|
|
138
133
|
:rtype: :py:obj:`None`
|
|
139
134
|
|
|
140
135
|
"""
|
|
141
|
-
|
|
142
136
|
self.session.wialon_api.item_update_custom_field(
|
|
143
|
-
**{
|
|
144
|
-
"itemId": self.id,
|
|
145
|
-
"id": 0,
|
|
146
|
-
"callMode": "create",
|
|
147
|
-
"n": field[0],
|
|
148
|
-
"v": field[1],
|
|
149
|
-
}
|
|
137
|
+
**{"itemId": self.id, "id": 0, "callMode": "create", "n": key, "v": value}
|
|
150
138
|
)
|
|
151
139
|
|
|
152
|
-
def update_cfield(self,
|
|
140
|
+
def update_cfield(self, id: int, key: str, value: str) -> None:
|
|
153
141
|
"""
|
|
154
142
|
Updates a custom field by id.
|
|
155
143
|
|
|
156
|
-
:param
|
|
157
|
-
:type
|
|
158
|
-
:param field: A
|
|
159
|
-
:type field: :py:obj:`
|
|
144
|
+
:param id: The admin field id.
|
|
145
|
+
:type id: :py:obj:`int`
|
|
146
|
+
:param field: A key (name) for the custom field.
|
|
147
|
+
:type field: :py:obj:`str`
|
|
148
|
+
:param field: A value for the custom field.
|
|
149
|
+
:type field: :py:obj:`str`
|
|
150
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
160
151
|
:returns: Nothing.
|
|
161
152
|
:rtype: :py:obj:`None`
|
|
162
153
|
|
|
163
154
|
"""
|
|
164
|
-
|
|
165
155
|
self.session.wialon_api.item_update_custom_field(
|
|
166
|
-
**{
|
|
167
|
-
"itemId": self.id,
|
|
168
|
-
"id": field_id,
|
|
169
|
-
"callMode": "update",
|
|
170
|
-
"n": field[0],
|
|
171
|
-
"v": field[1],
|
|
172
|
-
}
|
|
156
|
+
**{"itemId": self.id, "id": id, "callMode": "update", "n": key, "v": value}
|
|
173
157
|
)
|
|
174
158
|
|
|
175
|
-
def add_cproperty(self,
|
|
159
|
+
def add_cproperty(self, key: str, value: str) -> None:
|
|
176
160
|
"""
|
|
177
161
|
Adds a custom property to the Wialon object.
|
|
178
162
|
|
|
179
|
-
:param
|
|
180
|
-
:type
|
|
163
|
+
:param key: A key (name) for the custom property.
|
|
164
|
+
:type key: :py:obj:`str`
|
|
165
|
+
:param value: A value for the custom property.
|
|
166
|
+
:type value: :py:obj:`str`
|
|
167
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
181
168
|
:returns: Nothing.
|
|
182
169
|
:rtype: :py:obj:`None`
|
|
183
170
|
|
|
184
171
|
"""
|
|
185
|
-
|
|
186
172
|
self.session.wialon_api.item_update_custom_property(
|
|
187
|
-
**{"itemId": self.id, "name":
|
|
173
|
+
**{"itemId": self.id, "name": key, "value": value}
|
|
188
174
|
)
|
|
189
175
|
|
|
190
|
-
def add_profile_field(self,
|
|
176
|
+
def add_profile_field(self, key: str, value: str) -> None:
|
|
191
177
|
"""
|
|
192
178
|
Adds a profile field to the Wialon object.
|
|
193
179
|
|
|
194
|
-
:param
|
|
195
|
-
:type
|
|
180
|
+
:param key: A key (name) for the profile field.
|
|
181
|
+
:type key: :py:obj:`str`
|
|
182
|
+
:param value: A value for the profile field.
|
|
183
|
+
:type value: :py:obj:`str`
|
|
184
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
196
185
|
:returns: Nothing.
|
|
197
186
|
:rtype: :py:obj:`None`
|
|
198
187
|
|
|
199
188
|
"""
|
|
200
|
-
|
|
201
189
|
self.session.wialon_api.item_update_profile_field(
|
|
202
|
-
**{"itemId": self.id, "n":
|
|
190
|
+
**{"itemId": self.id, "n": key, "v": value}
|
|
203
191
|
)
|
|
204
192
|
|
|
205
193
|
def delete(self) -> None:
|
|
@@ -211,12 +199,11 @@ class WialonBase:
|
|
|
211
199
|
:rtype: :py:obj:`None`
|
|
212
200
|
|
|
213
201
|
"""
|
|
214
|
-
|
|
215
202
|
self.session.wialon_api.item_delete_item(**{"itemId": self.id})
|
|
216
203
|
|
|
217
204
|
@property
|
|
218
|
-
def cfields(self) -> dict:
|
|
219
|
-
"""Custom fields
|
|
205
|
+
def cfields(self) -> dict[str, str]:
|
|
206
|
+
"""Custom fields for the Wialon object."""
|
|
220
207
|
response = self.session.wialon_api.core_search_item(
|
|
221
208
|
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_CUSTOM_FIELDS}
|
|
222
209
|
)
|
|
@@ -224,8 +211,8 @@ class WialonBase:
|
|
|
224
211
|
return {field["n"]: field["v"] for field in fields.values()} if fields else {}
|
|
225
212
|
|
|
226
213
|
@property
|
|
227
|
-
def afields(self) -> dict:
|
|
228
|
-
"""Admin fields
|
|
214
|
+
def afields(self) -> dict[str, str]:
|
|
215
|
+
"""Admin fields for the Wialon object."""
|
|
229
216
|
response = self.session.wialon_api.core_search_item(
|
|
230
217
|
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_ADMIN_FIELDS}
|
|
231
218
|
)
|
|
@@ -34,7 +34,11 @@ class WialonResource(WialonBase):
|
|
|
34
34
|
"skipCreatorCheck": int(skip_creator_check),
|
|
35
35
|
}
|
|
36
36
|
)
|
|
37
|
-
return
|
|
37
|
+
return (
|
|
38
|
+
int(response.get("item", {}).get("id"))
|
|
39
|
+
if response and response.get("item")
|
|
40
|
+
else None
|
|
41
|
+
)
|
|
38
42
|
|
|
39
43
|
def delete(self) -> None:
|
|
40
44
|
"""
|
|
@@ -30,7 +30,11 @@ class WialonRetranslator(WialonBase):
|
|
|
30
30
|
"dataFlags": flags.DATAFLAG_UNIT_BASE,
|
|
31
31
|
}
|
|
32
32
|
)
|
|
33
|
-
return
|
|
33
|
+
return (
|
|
34
|
+
int(response.get("item", {}).get("id"))
|
|
35
|
+
if response and response.get("item")
|
|
36
|
+
else None
|
|
37
|
+
)
|
|
34
38
|
|
|
35
39
|
def update_config(self, new_config: dict) -> None:
|
|
36
40
|
"""
|
|
@@ -27,4 +27,8 @@ class WialonRoute(WialonBase):
|
|
|
27
27
|
"dataFlags": flags.DATAFLAG_UNIT_BASE,
|
|
28
28
|
}
|
|
29
29
|
)
|
|
30
|
-
return
|
|
30
|
+
return (
|
|
31
|
+
int(response.get("item", {}).get("id"))
|
|
32
|
+
if response and response.get("item")
|
|
33
|
+
else None
|
|
34
|
+
)
|
terminusgps/wialon/items/unit.py
CHANGED
|
@@ -36,7 +36,11 @@ class WialonUnit(WialonBase):
|
|
|
36
36
|
"dataFlags": flags.DATAFLAG_UNIT_BASE,
|
|
37
37
|
}
|
|
38
38
|
)
|
|
39
|
-
return
|
|
39
|
+
return (
|
|
40
|
+
int(response.get("item", {}).get("id"))
|
|
41
|
+
if response and response.get("item")
|
|
42
|
+
else None
|
|
43
|
+
)
|
|
40
44
|
|
|
41
45
|
def populate(self) -> None:
|
|
42
46
|
super().populate()
|
|
@@ -48,17 +52,22 @@ class WialonUnit(WialonBase):
|
|
|
48
52
|
),
|
|
49
53
|
}
|
|
50
54
|
)
|
|
51
|
-
if response
|
|
55
|
+
if response:
|
|
52
56
|
item = response.get("item", {})
|
|
53
57
|
self._imei_number = item.get("uid")
|
|
54
58
|
self._active = item.get("act", False)
|
|
55
59
|
self._image_uri = item.get("uri")
|
|
56
60
|
|
|
57
|
-
def get_position(self) -> dict:
|
|
61
|
+
def get_position(self) -> dict | None:
|
|
58
62
|
return self.session.wialon_api.core_search_item(
|
|
59
63
|
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_POSITION}
|
|
60
64
|
)
|
|
61
65
|
|
|
66
|
+
@property
|
|
67
|
+
def position(self) -> dict | None:
|
|
68
|
+
"""Current GPS position of the unit."""
|
|
69
|
+
return self.get_position()
|
|
70
|
+
|
|
62
71
|
@property
|
|
63
72
|
def exists(self) -> bool:
|
|
64
73
|
"""Whether or not the unit exists in Wialon."""
|
|
@@ -118,7 +127,6 @@ class WialonUnit(WialonBase):
|
|
|
118
127
|
:rtype: :py:obj:`None`
|
|
119
128
|
|
|
120
129
|
"""
|
|
121
|
-
|
|
122
130
|
self.session.wialon_api.unit_exec_cmd(
|
|
123
131
|
**{
|
|
124
132
|
"itemId": self.id,
|
|
@@ -141,7 +149,6 @@ class WialonUnit(WialonBase):
|
|
|
141
149
|
:rtype: :py:obj:`None`
|
|
142
150
|
|
|
143
151
|
"""
|
|
144
|
-
|
|
145
152
|
self.session.wialon_api.unit_update_access_password(
|
|
146
153
|
**{"itemId": self.id, "accessPassword": password}
|
|
147
154
|
)
|
|
@@ -155,7 +162,6 @@ class WialonUnit(WialonBase):
|
|
|
155
162
|
:rtype: :py:obj:`None`
|
|
156
163
|
|
|
157
164
|
"""
|
|
158
|
-
|
|
159
165
|
self.session.wialon_api.unit_set_active(
|
|
160
166
|
**{"itemId": self.id, "active": int(True)}
|
|
161
167
|
)
|
|
@@ -169,7 +175,6 @@ class WialonUnit(WialonBase):
|
|
|
169
175
|
:rtype: :py:obj:`None`
|
|
170
176
|
|
|
171
177
|
"""
|
|
172
|
-
|
|
173
178
|
self.session.wialon_api.unit_set_active(
|
|
174
179
|
**{"itemId": self.id, "active": int(False)}
|
|
175
180
|
)
|
|
@@ -185,7 +190,6 @@ class WialonUnit(WialonBase):
|
|
|
185
190
|
:rtype: :py:obj:`None`
|
|
186
191
|
|
|
187
192
|
"""
|
|
188
|
-
|
|
189
193
|
self.session.wialon_api.unit_update_phone(
|
|
190
194
|
**{"itemId": self.id, "phoneNumber": quote_plus(phone)}
|
|
191
195
|
)
|
|
@@ -194,14 +198,13 @@ class WialonUnit(WialonBase):
|
|
|
194
198
|
"""
|
|
195
199
|
Retrieves all phone numbers assigned to the unit.
|
|
196
200
|
|
|
197
|
-
This includes any attached drivers, custom/admin fields
|
|
201
|
+
This includes any attached drivers, custom/admin fields or otherwise assigned phone numbers.
|
|
198
202
|
|
|
199
203
|
:raises WialonError: If something goes wrong with Wialon.
|
|
200
204
|
:returns: A list of phone numbers.
|
|
201
205
|
:rtype: :py:obj:`list`
|
|
202
206
|
|
|
203
207
|
"""
|
|
204
|
-
|
|
205
208
|
phone_numbers: list[str] = []
|
|
206
209
|
phones_0: list[str] | None = self._get_driver_phone_numbers()
|
|
207
210
|
phones_1: list[str] | None = self._get_cfield_phone_numbers()
|
|
@@ -17,7 +17,6 @@ class WialonUnitGroup(WialonBase):
|
|
|
17
17
|
:rtype: :py:obj:`int` | :py:obj:`None`
|
|
18
18
|
|
|
19
19
|
"""
|
|
20
|
-
|
|
21
20
|
if isinstance(creator_id, str) and not creator_id.isdigit():
|
|
22
21
|
raise ValueError(f"'creator_id' must be a digit, got '{creator_id}'.")
|
|
23
22
|
|
|
@@ -28,7 +27,11 @@ class WialonUnitGroup(WialonBase):
|
|
|
28
27
|
"dataFlags": flags.DATAFLAG_UNIT_BASE,
|
|
29
28
|
}
|
|
30
29
|
)
|
|
31
|
-
return
|
|
30
|
+
return (
|
|
31
|
+
int(response.get("item", {}).get("id"))
|
|
32
|
+
if response and response.get("item")
|
|
33
|
+
else None
|
|
34
|
+
)
|
|
32
35
|
|
|
33
36
|
def set_items(self, new_items: list[str]) -> None:
|
|
34
37
|
"""
|
|
@@ -41,7 +44,6 @@ class WialonUnitGroup(WialonBase):
|
|
|
41
44
|
:rtype: :py:obj:`None`
|
|
42
45
|
|
|
43
46
|
"""
|
|
44
|
-
|
|
45
47
|
self.session.wialon_api.unit_group_update_units(
|
|
46
48
|
**{"itemId": self.id, "units": new_items}
|
|
47
49
|
)
|
|
@@ -115,39 +117,3 @@ class WialonUnitGroup(WialonBase):
|
|
|
115
117
|
}
|
|
116
118
|
)
|
|
117
119
|
return [unit_id for unit_id in response.get("items")[0].get("u", [])]
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
def main() -> None:
|
|
121
|
-
import logging
|
|
122
|
-
|
|
123
|
-
from django.conf import settings
|
|
124
|
-
from django.utils import timezone
|
|
125
|
-
|
|
126
|
-
from terminusgps.wialon.items import WialonUnit
|
|
127
|
-
from terminusgps.wialon.session import WialonSession
|
|
128
|
-
from terminusgps.wialon.utils import get_hw_type_id
|
|
129
|
-
|
|
130
|
-
timestamp = f"{timezone.now():%Y_%m_%d_%H:%M:%S}"
|
|
131
|
-
with WialonSession(log_level=logging.DEBUG) as session:
|
|
132
|
-
unit = WialonUnit(
|
|
133
|
-
id=None,
|
|
134
|
-
session=session,
|
|
135
|
-
creator_id=settings.WIALON_ADMIN_ID,
|
|
136
|
-
name=f"test_unit_{timestamp}",
|
|
137
|
-
hw_type_id=get_hw_type_id("Test HW", session=session),
|
|
138
|
-
)
|
|
139
|
-
group = WialonUnitGroup(
|
|
140
|
-
id=None,
|
|
141
|
-
session=session,
|
|
142
|
-
creator_id=settings.WIALON_ADMIN_ID,
|
|
143
|
-
name=f"test_group_{timestamp}",
|
|
144
|
-
)
|
|
145
|
-
group.add_item(unit)
|
|
146
|
-
print(f"{group.items = }")
|
|
147
|
-
unit.delete()
|
|
148
|
-
group.delete()
|
|
149
|
-
return
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if __name__ == "__main__":
|
|
153
|
-
main()
|
terminusgps/wialon/items/user.py
CHANGED
|
@@ -32,7 +32,11 @@ class WialonUser(WialonBase):
|
|
|
32
32
|
"dataFlags": flags.DATAFLAG_UNIT_BASE,
|
|
33
33
|
}
|
|
34
34
|
)
|
|
35
|
-
return
|
|
35
|
+
return (
|
|
36
|
+
int(response.get("item", {}).get("id"))
|
|
37
|
+
if response and response.get("item")
|
|
38
|
+
else None
|
|
39
|
+
)
|
|
36
40
|
|
|
37
41
|
def _get_access_response(self, hw_type: str) -> dict:
|
|
38
42
|
"""
|
terminusgps/wialon/session.py
CHANGED
|
@@ -3,10 +3,9 @@ import datetime
|
|
|
3
3
|
import logging
|
|
4
4
|
import typing
|
|
5
5
|
|
|
6
|
+
import wialon.api
|
|
6
7
|
from django.conf import settings
|
|
7
8
|
from django.utils import timezone
|
|
8
|
-
from wialon.api import Wialon as WialonBase
|
|
9
|
-
from wialon.api import WialonError
|
|
10
9
|
|
|
11
10
|
from terminusgps.wialon.logger import WialonLogger
|
|
12
11
|
|
|
@@ -21,7 +20,7 @@ class WialonAPICall:
|
|
|
21
20
|
error: Exception | None = None
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
class Wialon(
|
|
23
|
+
class Wialon(wialon.api.Wialon):
|
|
25
24
|
def __init__(self, log_level: int = logging.INFO, *args, **kwargs) -> None:
|
|
26
25
|
super().__init__(*args, **kwargs)
|
|
27
26
|
self.call_history: list[WialonAPICall] = []
|
|
@@ -48,7 +47,7 @@ class Wialon(WialonBase):
|
|
|
48
47
|
call_record.result = result
|
|
49
48
|
self.logger.debug(f"Executed '{action_name}' successfully.")
|
|
50
49
|
return result
|
|
51
|
-
except WialonError as e:
|
|
50
|
+
except wialon.api.WialonError as e:
|
|
52
51
|
call_record.error = e
|
|
53
52
|
self.logger.warning(f"Failed to execute '{action_name}': '{e}'")
|
|
54
53
|
return
|
|
@@ -275,7 +274,7 @@ class WialonSession:
|
|
|
275
274
|
self._set_login_response(response)
|
|
276
275
|
self.logger.debug(f"Logged into Wialon API session '{response.get('eid')}'")
|
|
277
276
|
return response.get("eid")
|
|
278
|
-
except (WialonError, AssertionError) as e:
|
|
277
|
+
except (wialon.api.WialonError, AssertionError) as e:
|
|
279
278
|
self.logger.critical(f"Failed to login to Wialon API: '{e}'")
|
|
280
279
|
raise
|
|
281
280
|
|
terminusgps/wialon/utils.py
CHANGED
|
@@ -49,7 +49,7 @@ def get_id_from_imei(imei: str, session: WialonSession) -> str | None:
|
|
|
49
49
|
if not imei.isdigit():
|
|
50
50
|
raise ValueError(f"'imei' must be a digit, got '{imei}'.")
|
|
51
51
|
|
|
52
|
-
results = session.wialon_api.core_search_items(
|
|
52
|
+
results: dict[str, typing.Any] | None = session.wialon_api.core_search_items(
|
|
53
53
|
**{
|
|
54
54
|
"spec": {
|
|
55
55
|
"itemsType": "avl_unit",
|
|
@@ -66,7 +66,7 @@ def get_id_from_imei(imei: str, session: WialonSession) -> str | None:
|
|
|
66
66
|
}
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
-
if results.get("totalItemsCount", 0) == 1:
|
|
69
|
+
if results and results.get("totalItemsCount", 0) == 1:
|
|
70
70
|
return results["items"][0].get("id")
|
|
71
71
|
|
|
72
72
|
|
|
@@ -88,27 +88,25 @@ def get_id_from_iccid(iccid: str, session: WialonSession) -> str | None:
|
|
|
88
88
|
return get_id_from_imei(imei=iccid, session=session)
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
def get_wialon_cls(items_type: str) -> typing.Type[WialonBase]:
|
|
91
|
+
def get_wialon_cls(items_type: str) -> typing.Type[WialonBase] | None:
|
|
92
92
|
"""
|
|
93
|
-
Returns a Wialon object class based on items_type
|
|
93
|
+
Returns a Wialon object class based on ``items_type``.
|
|
94
|
+
|
|
95
|
+
Valid ``items_type`` are ``"user"``, ``"avl_unit"``, ``"avl_unit_group"`` and ``"avl_resource"``.
|
|
94
96
|
|
|
95
97
|
:param items_type: A Wialon object type.
|
|
96
98
|
:type items_type: :py:obj:`str`
|
|
97
99
|
:returns: A subclass of :py:obj:`~terminusgps.wialon.items.base.WialonBase`.
|
|
98
|
-
:rtype: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
100
|
+
:rtype: :py:obj:`~terminusgps.wialon.items.base.WialonBase` | :py:obj:`None`
|
|
99
101
|
|
|
100
102
|
"""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
case "avl_resource":
|
|
109
|
-
return items.WialonResource
|
|
110
|
-
case _:
|
|
111
|
-
raise ValueError(f"Invalid items_type, got '{items_type}'.")
|
|
103
|
+
items_map: dict[str, typing.Type[WialonBase]] = {
|
|
104
|
+
"user": items.WialonUser,
|
|
105
|
+
"avl_unit": items.WialonUnit,
|
|
106
|
+
"avl_unit_group": items.WialonUnitGroup,
|
|
107
|
+
"avl_resource": items.WialonResource,
|
|
108
|
+
}
|
|
109
|
+
return items_map.get(items_type)
|
|
112
110
|
|
|
113
111
|
|
|
114
112
|
def get_vin_info(vin_number: str, session: WialonSession) -> dict:
|
|
@@ -123,15 +121,18 @@ def get_vin_info(vin_number: str, session: WialonSession) -> dict:
|
|
|
123
121
|
:rtype: :py:obj:`dict`
|
|
124
122
|
|
|
125
123
|
"""
|
|
126
|
-
response = session.wialon_api.unit_get_vin_info(
|
|
127
|
-
"
|
|
128
|
-
)
|
|
129
|
-
return (
|
|
130
|
-
{field.get("n"): field.get("v") for field in response.get("pflds")}
|
|
131
|
-
if "error" not in response.keys()
|
|
132
|
-
else {}
|
|
124
|
+
response: dict[str, typing.Any] | None = session.wialon_api.unit_get_vin_info(
|
|
125
|
+
**{"vin": vin_number}
|
|
133
126
|
)
|
|
134
127
|
|
|
128
|
+
if response is None or "error" in response.get("vin_lookup_result", {}).keys():
|
|
129
|
+
return {}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
field.get("n"): field.get("v")
|
|
133
|
+
for field in response.get("vin_lookup_result", {}).get("pflds")
|
|
134
|
+
}
|
|
135
|
+
|
|
135
136
|
|
|
136
137
|
def is_unique(value: str, session: WialonSession, items_type: str = "avl_unit") -> bool:
|
|
137
138
|
"""
|
|
@@ -148,12 +149,14 @@ def is_unique(value: str, session: WialonSession, items_type: str = "avl_unit")
|
|
|
148
149
|
:rtype: :py:obj:`bool`
|
|
149
150
|
|
|
150
151
|
"""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
**{"type": items_type, "value": value.strip()}
|
|
154
|
-
).get("result")
|
|
152
|
+
response = session.wialon_api.core_check_unique(
|
|
153
|
+
**{"type": items_type, "value": value.strip()}
|
|
155
154
|
)
|
|
156
155
|
|
|
156
|
+
if not response:
|
|
157
|
+
return False
|
|
158
|
+
return bool(response.get("result"))
|
|
159
|
+
|
|
157
160
|
|
|
158
161
|
def generate_wialon_password(length: int = 32) -> str:
|
|
159
162
|
"""
|
terminusgps/aws/ses.py
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import boto3
|
|
2
|
-
import json
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class SESEmailTemplate:
|
|
6
|
-
def __init__(self, template_name: str, region_name: str = "us-east-1") -> None:
|
|
7
|
-
self.name = template_name
|
|
8
|
-
self.region = region_name
|
|
9
|
-
self.client = boto3.Session().client(service_name="ses")
|
|
10
|
-
|
|
11
|
-
def send(
|
|
12
|
-
self,
|
|
13
|
-
from_addr: str,
|
|
14
|
-
recipients: list[str],
|
|
15
|
-
replyto_list: list[str],
|
|
16
|
-
data: dict[str, str],
|
|
17
|
-
cc_list: list[str] | None = None,
|
|
18
|
-
bcc_list: list[str] | None = None,
|
|
19
|
-
) -> None:
|
|
20
|
-
destination = self._get_destination(recipients, cc_list, bcc_list)
|
|
21
|
-
self.client.send_templated_email(
|
|
22
|
-
**{
|
|
23
|
-
"Source": from_addr,
|
|
24
|
-
"Destination": destination,
|
|
25
|
-
"ReplyToAddresses": replyto_list,
|
|
26
|
-
"Template": self.name,
|
|
27
|
-
"TemplateData": json.dumps(data),
|
|
28
|
-
}
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
def create(self, subject: str, text_content: str, html_content: str) -> None:
|
|
32
|
-
self.client.create_template(
|
|
33
|
-
**{
|
|
34
|
-
"Template": {
|
|
35
|
-
"TemplateName": self.name,
|
|
36
|
-
"SubjectPart": subject,
|
|
37
|
-
"TextPart": text_content,
|
|
38
|
-
"HtmlPart": html_content,
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
def update(self, subject: str, text_content: str, html_content: str) -> None:
|
|
44
|
-
self.client.update_template(
|
|
45
|
-
**{
|
|
46
|
-
"Template": {
|
|
47
|
-
"TemplateName": self.name,
|
|
48
|
-
"SubjectPart": subject,
|
|
49
|
-
"TextPart": text_content,
|
|
50
|
-
"HtmlPart": html_content,
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
def test_render(self, data: dict[str, str]) -> str:
|
|
56
|
-
response = self.client.test_render_template(
|
|
57
|
-
**{"TemplateName": self.name, "TemplateData": json.dumps(data)}
|
|
58
|
-
)
|
|
59
|
-
return response.get("RenderedTemplate")
|
|
60
|
-
|
|
61
|
-
def _get_destination(
|
|
62
|
-
self,
|
|
63
|
-
recipients: list[str],
|
|
64
|
-
cc_list: list[str] | None,
|
|
65
|
-
bcc_list: list[str] | None,
|
|
66
|
-
) -> dict[str, list[str]]:
|
|
67
|
-
destination: dict[str, list[str]] = {"ToAddresses": recipients}
|
|
68
|
-
if cc_list is not None:
|
|
69
|
-
destination.update({"CcAddresses": cc_list})
|
|
70
|
-
if bcc_list is not None:
|
|
71
|
-
destination.update({"BccAddresses": bcc_list})
|
|
72
|
-
return destination
|
|
File without changes
|
{python_terminusgps-25.1.0.dist-info → python_terminusgps-27.0.0.dist-info}/licenses/COPYING
RENAMED
|
File without changes
|