python-terminusgps 1.4.6__py3-none-any.whl → 1.5.7__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.
- {python_terminusgps-1.4.6.dist-info → python_terminusgps-1.5.7.dist-info}/METADATA +2 -2
- python_terminusgps-1.5.7.dist-info/RECORD +24 -0
- terminusgps/authorizenet/auth.py +7 -1
- terminusgps/settings.py +6 -0
- terminusgps/wialon/__init__.py +0 -5
- terminusgps/wialon/errors.py +36 -8
- terminusgps/wialon/items/base.py +114 -15
- terminusgps/wialon/items/resource.py +1 -1
- terminusgps/wialon/items/retranslator.py +95 -0
- terminusgps/wialon/items/unit.py +81 -19
- terminusgps/wialon/items/unit_group.py +84 -1
- terminusgps/wialon/items/user.py +106 -2
- terminusgps/wialon/session.py +296 -42
- terminusgps/wialon/utils.py +0 -9
- python_terminusgps-1.4.6.dist-info/RECORD +0 -24
- terminusgps/wialon/items/account.py +0 -15
- {python_terminusgps-1.4.6.dist-info → python_terminusgps-1.5.7.dist-info}/WHEEL +0 -0
- {python_terminusgps-1.4.6.dist-info → python_terminusgps-1.5.7.dist-info}/licenses/COPYING +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.7
|
|
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
|
|
@@ -15,5 +15,5 @@ Requires-Python: >=3.12
|
|
|
15
15
|
Requires-Dist: argparse>=1.4.0
|
|
16
16
|
Requires-Dist: authorizenet>=1.1.5
|
|
17
17
|
Requires-Dist: boto3>=1.34.144
|
|
18
|
-
Requires-Dist: django>=5.1.
|
|
18
|
+
Requires-Dist: django>=5.1.5
|
|
19
19
|
Requires-Dist: python-wialon>=1.2.4
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
terminusgps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
terminusgps/settings.py,sha256=CIWif9AJYXk5nE-9Mqmqkeoum6-ON5MTuh0WJilgv3E,185
|
|
3
|
+
terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
terminusgps/authorizenet/auth.py,sha256=zITSQMH8F-3vw-lDQRbuR2s9AVlGqbOyyFo0zqU00qU,870
|
|
5
|
+
terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
terminusgps/aws/secrets.py,sha256=kgRA77rs0mD4berWRLkPtJLOe4Grf--o5f8NzwQqXCk,360
|
|
7
|
+
terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
terminusgps/wialon/constants.py,sha256=dsQaNt3TIjIZbr_m94KmBGFdrqe6HER2r6lol3X8QpU,2802
|
|
9
|
+
terminusgps/wialon/errors.py,sha256=SV9pVwU6FZ_zGlGP6zJN6aLE2auF4TfHFISQLiPMKrI,1758
|
|
10
|
+
terminusgps/wialon/flags.py,sha256=-OoH-eZM54yjRqxsAXL8VImdQu_7C0OAxCrFqaCEuko,13510
|
|
11
|
+
terminusgps/wialon/session.py,sha256=x5aXxqLcBe4e0Zj3enUvWd1_Ufmd_MxXInC_d_GMn3E,9446
|
|
12
|
+
terminusgps/wialon/utils.py,sha256=J8V2F-QDMsLD5x2OhCYI2lnZZdgqKboMve5XJD7Qt30,1877
|
|
13
|
+
terminusgps/wialon/items/__init__.py,sha256=3BVthghekMvhMQSzQgBMlD_phxmKSmp3Zvmo-z0O8Bs,211
|
|
14
|
+
terminusgps/wialon/items/base.py,sha256=MN4FG6U1nWkYAjNfXQJRVrWJoiW4Y64tyqxUO0mhv_w,6593
|
|
15
|
+
terminusgps/wialon/items/resource.py,sha256=ADjGsQaCqD6Y3_AaD8vLgYzGaMK69MpxCZojnylS4GE,815
|
|
16
|
+
terminusgps/wialon/items/retranslator.py,sha256=zsQXqOhH1zFe5_e8DROPu60z3v6xPWOEPyMCi2IqJAo,3861
|
|
17
|
+
terminusgps/wialon/items/route.py,sha256=qOHPN_rejwiGqvwWzlwmUIAIyc3lKavCalf8ki66rx0,760
|
|
18
|
+
terminusgps/wialon/items/unit.py,sha256=tLAWPfHUUS6_Feh1aYBMFPgyuGlSiAnfumJJmGt3bKw,4662
|
|
19
|
+
terminusgps/wialon/items/unit_group.py,sha256=1yc7ldPIgGbtiTj0djRDWmt6Q9K_VT9sxOaioasbbLY,5212
|
|
20
|
+
terminusgps/wialon/items/user.py,sha256=bkcMw_YiocaMuhP_pBfB7apjAZwnsOzGScnGkn8Ybbw,6107
|
|
21
|
+
python_terminusgps-1.5.7.dist-info/METADATA,sha256=nY0ZeyVuZ4mUV82NrlzNEXNbLQ-kpDUJW8Y1vvFAAOM,882
|
|
22
|
+
python_terminusgps-1.5.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
+
python_terminusgps-1.5.7.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
24
|
+
python_terminusgps-1.5.7.dist-info/RECORD,,
|
terminusgps/authorizenet/auth.py
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
from authorizenet.apicontractsv1 import merchantAuthenticationType
|
|
2
2
|
from authorizenet.constants import constants
|
|
3
3
|
|
|
4
|
-
from django.conf import settings
|
|
4
|
+
from django.conf import ImproperlyConfigured, settings
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def get_merchant_auth() -> merchantAuthenticationType:
|
|
8
|
+
if not hasattr(settings, "MERCHANT_AUTH_LOGIN_ID"):
|
|
9
|
+
raise ImproperlyConfigured("'MERCHANT_AUTH_LOGIN_ID' is required.")
|
|
10
|
+
if not hasattr(settings, "MERCHANT_AUTH_TRANSACTION_KEY"):
|
|
11
|
+
raise ImproperlyConfigured("'MERCHANT_AUTH_TRANSACTION_KEY' is required.")
|
|
8
12
|
return merchantAuthenticationType(
|
|
9
13
|
name=str(settings.MERCHANT_AUTH_LOGIN_ID),
|
|
10
14
|
transactionKey=str(settings.MERCHANT_AUTH_TRANSACTION_KEY),
|
|
@@ -12,4 +16,6 @@ def get_merchant_auth() -> merchantAuthenticationType:
|
|
|
12
16
|
|
|
13
17
|
|
|
14
18
|
def get_environment() -> str:
|
|
19
|
+
if not hasattr(settings, "DEBUG"):
|
|
20
|
+
raise ImproperlyConfigured("'DEBUG' is required.")
|
|
15
21
|
return constants.SANDBOX if settings.DEBUG else constants.PRODUCTION
|
terminusgps/settings.py
ADDED
terminusgps/wialon/__init__.py
CHANGED
terminusgps/wialon/errors.py
CHANGED
|
@@ -2,24 +2,52 @@ from wialon.api import WialonError
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
class WialonBaseError(Exception):
|
|
5
|
-
def __init__(
|
|
5
|
+
def __init__(
|
|
6
|
+
self, message: str, wialon_err: WialonError | AssertionError | None = None
|
|
7
|
+
) -> None:
|
|
6
8
|
self.wialon_err = wialon_err
|
|
7
|
-
super().__init__(message)
|
|
9
|
+
return super().__init__(message)
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class WialonLoginError(WialonBaseError):
|
|
11
13
|
def __init__(
|
|
12
|
-
self, token: str | None, wialon_err: WialonError | None = None
|
|
14
|
+
self, token: str | None, wialon_err: WialonError | AssertionError | None = None
|
|
15
|
+
) -> None:
|
|
16
|
+
message = f"Failed to login to the Wialon API using token: '{token}'\n"
|
|
17
|
+
if wialon_err:
|
|
18
|
+
message += str(wialon_err)
|
|
19
|
+
return super().__init__(message, wialon_err)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class WialonSessionDuplicationError(WialonBaseError):
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
session_id: str | None,
|
|
26
|
+
wialon_err: WialonError | AssertionError | None = None,
|
|
13
27
|
) -> None:
|
|
14
|
-
message = f"Failed to
|
|
28
|
+
message = f"Failed to duplicate the Wialon session: '#{session_id}'\n"
|
|
15
29
|
if wialon_err:
|
|
16
30
|
message += str(wialon_err)
|
|
17
|
-
super().__init__(message, wialon_err)
|
|
31
|
+
return super().__init__(message, wialon_err)
|
|
18
32
|
|
|
19
33
|
|
|
20
34
|
class WialonLogoutError(WialonBaseError):
|
|
21
|
-
def __init__(
|
|
22
|
-
|
|
35
|
+
def __init__(
|
|
36
|
+
self, session_id: str, wialon_err: WialonError | AssertionError | None = None
|
|
37
|
+
) -> None:
|
|
38
|
+
message = f"Failed to logout of the Wialon API session: '{session_id}'\n"
|
|
39
|
+
if wialon_err:
|
|
40
|
+
message += str(wialon_err)
|
|
41
|
+
return super().__init__(message, wialon_err)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class WialonSessionInvalidError(WialonBaseError):
|
|
45
|
+
def __init__(
|
|
46
|
+
self,
|
|
47
|
+
session_id: str | None,
|
|
48
|
+
wialon_err: WialonError | AssertionError | None = None,
|
|
49
|
+
) -> None:
|
|
50
|
+
message = f"The session was invalid/expired: '{session_id}'\n"
|
|
23
51
|
if wialon_err:
|
|
24
52
|
message += str(wialon_err)
|
|
25
|
-
super().__init__(message, wialon_err)
|
|
53
|
+
return super().__init__(message, wialon_err)
|
terminusgps/wialon/items/base.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import terminusgps.wialon.flags as flags
|
|
2
2
|
from terminusgps.wialon.session import WialonSession
|
|
3
|
-
from terminusgps.wialon.utils import repopulate
|
|
4
3
|
|
|
5
4
|
|
|
6
5
|
class WialonBase:
|
|
7
|
-
@repopulate
|
|
8
6
|
def __init__(
|
|
9
7
|
self, *, id: str | None = None, session: WialonSession, **kwargs
|
|
10
8
|
) -> None:
|
|
@@ -16,17 +14,45 @@ class WialonBase:
|
|
|
16
14
|
self._id = id
|
|
17
15
|
|
|
18
16
|
def __str__(self) -> str:
|
|
19
|
-
return
|
|
17
|
+
return str(self.id)
|
|
18
|
+
|
|
19
|
+
def populate(self) -> None:
|
|
20
|
+
response = self.session.wialon_api.core_search_item(
|
|
21
|
+
**{"id": str(self.id), "flags": 0x1}
|
|
22
|
+
)["item"]
|
|
23
|
+
self.name = response.get("nm")
|
|
24
|
+
self.hw_type = response.get("cls")
|
|
25
|
+
self.access_lvl = response.get("uacl")
|
|
20
26
|
|
|
21
27
|
@property
|
|
22
28
|
def session(self) -> WialonSession:
|
|
29
|
+
"""
|
|
30
|
+
A valid Wialon API session.
|
|
31
|
+
|
|
32
|
+
:type: :py:obj:`~terminusgps.wialon.session.WialonSession`
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
23
36
|
return self._session
|
|
24
37
|
|
|
25
38
|
@property
|
|
26
39
|
def id(self) -> int | None:
|
|
40
|
+
"""
|
|
41
|
+
A unique Wialon ID.
|
|
42
|
+
|
|
43
|
+
:type: :py:obj:`int` | :py:obj:`None`
|
|
44
|
+
|
|
45
|
+
"""
|
|
46
|
+
|
|
27
47
|
return int(self._id) if self._id else None
|
|
28
48
|
|
|
29
49
|
def has_access(self, other: "WialonBase") -> bool:
|
|
50
|
+
"""
|
|
51
|
+
Checks if this Wialon object has access to ``other``.
|
|
52
|
+
|
|
53
|
+
:type: :py:obj:`bool`
|
|
54
|
+
|
|
55
|
+
"""
|
|
30
56
|
response = self.session.wialon_api.core_check_accessors(
|
|
31
57
|
**{"items": [other.id], "flags": False}
|
|
32
58
|
)
|
|
@@ -36,22 +62,32 @@ class WialonBase:
|
|
|
36
62
|
"""Creates a Wialon object and returns the newly created Wialon object's id."""
|
|
37
63
|
raise NotImplementedError("Subclasses must implement this method.")
|
|
38
64
|
|
|
39
|
-
def populate(self) -> None:
|
|
40
|
-
"""Retrieves and sets hw_type and name for this Wialon object."""
|
|
41
|
-
item = self.session.wialon_api.core_search_item(
|
|
42
|
-
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_BASE}
|
|
43
|
-
).get("item", {})
|
|
44
|
-
self.hw_type = item.get("cls", None)
|
|
45
|
-
self.name = item.get("nm", None)
|
|
46
|
-
self.uid = item.get("uid", None)
|
|
47
|
-
|
|
48
|
-
@repopulate
|
|
49
65
|
def rename(self, new_name: str) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Renames the Wialon object to the new name.
|
|
68
|
+
|
|
69
|
+
:param new_name: A new name for this object.
|
|
70
|
+
:type new_name: :py:obj:`str`
|
|
71
|
+
:returns: Nothing.
|
|
72
|
+
:rtype: :py:obj:`None`
|
|
73
|
+
|
|
74
|
+
"""
|
|
75
|
+
|
|
50
76
|
self.session.wialon_api.item_update_name(
|
|
51
77
|
**{"itemId": self.id, "name": new_name}
|
|
52
78
|
)
|
|
53
79
|
|
|
54
80
|
def add_afield(self, field: tuple[str, str]) -> None:
|
|
81
|
+
"""
|
|
82
|
+
Adds an admin field to the Wialon object.
|
|
83
|
+
|
|
84
|
+
:param field: A tuple containing the name of the field and the value of the field.
|
|
85
|
+
:type field: :py:obj:`tuple`
|
|
86
|
+
:returns: Nothing.
|
|
87
|
+
:rtype: :py:obj:`None`
|
|
88
|
+
|
|
89
|
+
"""
|
|
90
|
+
|
|
55
91
|
self.session.wialon_api.item_update_admin_field(
|
|
56
92
|
**{
|
|
57
93
|
"itemId": self.id,
|
|
@@ -63,6 +99,18 @@ class WialonBase:
|
|
|
63
99
|
)
|
|
64
100
|
|
|
65
101
|
def update_afield(self, field_id: int, field: tuple[str, str]) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Updates an admin field by id to the Wialon object.
|
|
104
|
+
|
|
105
|
+
:param field_id: The admin field id.
|
|
106
|
+
:type field_id: :py:obj:`int`
|
|
107
|
+
:param field: A tuple containing the name of the field and the value of the field.
|
|
108
|
+
:type field: :py:obj:`tuple`
|
|
109
|
+
:returns: Nothing.
|
|
110
|
+
:rtype: :py:obj:`None`
|
|
111
|
+
|
|
112
|
+
"""
|
|
113
|
+
|
|
66
114
|
self.session.wialon_api.item_update_admin_field(
|
|
67
115
|
**{
|
|
68
116
|
"itemId": self.id,
|
|
@@ -74,6 +122,16 @@ class WialonBase:
|
|
|
74
122
|
)
|
|
75
123
|
|
|
76
124
|
def add_cfield(self, field: tuple[str, str]) -> None:
|
|
125
|
+
"""
|
|
126
|
+
Adds a custom field to the Wialon object.
|
|
127
|
+
|
|
128
|
+
:param field: A tuple containing the name of the field and the value of the field.
|
|
129
|
+
:type field: :py:obj:`tuple`
|
|
130
|
+
:returns: Nothing.
|
|
131
|
+
:rtype: :py:obj:`None`
|
|
132
|
+
|
|
133
|
+
"""
|
|
134
|
+
|
|
77
135
|
self.session.wialon_api.item_update_custom_field(
|
|
78
136
|
**{
|
|
79
137
|
"itemId": self.id,
|
|
@@ -85,6 +143,18 @@ class WialonBase:
|
|
|
85
143
|
)
|
|
86
144
|
|
|
87
145
|
def update_cfield(self, field_id: int, field: tuple[str, str]) -> None:
|
|
146
|
+
"""
|
|
147
|
+
Updates a custom field by id.
|
|
148
|
+
|
|
149
|
+
:param field_id: The admin field id.
|
|
150
|
+
:type field_id: :py:obj:`int`
|
|
151
|
+
:param field: A tuple containing the name of the field and the value of the field.
|
|
152
|
+
:type field: :py:obj:`tuple`
|
|
153
|
+
:returns: Nothing.
|
|
154
|
+
:rtype: :py:obj:`None`
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
|
|
88
158
|
self.session.wialon_api.item_update_custom_field(
|
|
89
159
|
**{
|
|
90
160
|
"itemId": self.id,
|
|
@@ -95,17 +165,46 @@ class WialonBase:
|
|
|
95
165
|
}
|
|
96
166
|
)
|
|
97
167
|
|
|
98
|
-
def add_cproperty(self,
|
|
168
|
+
def add_cproperty(self, property: tuple[str, str]) -> None:
|
|
169
|
+
"""
|
|
170
|
+
Adds a custom property to the Wialon object.
|
|
171
|
+
|
|
172
|
+
:param property: A tuple containing the name of the property and the value of the property.
|
|
173
|
+
:type property: :py:obj:`tuple`
|
|
174
|
+
:returns: Nothing.
|
|
175
|
+
:rtype: :py:obj:`None`
|
|
176
|
+
|
|
177
|
+
"""
|
|
178
|
+
|
|
99
179
|
self.session.wialon_api.item_update_custom_property(
|
|
100
|
-
**{"itemId": self.id, "name":
|
|
180
|
+
**{"itemId": self.id, "name": property[0], "value": property[1]}
|
|
101
181
|
)
|
|
102
182
|
|
|
103
183
|
def add_profile_field(self, field: tuple[str, str]) -> None:
|
|
184
|
+
"""
|
|
185
|
+
Adds a profile field to the Wialon object.
|
|
186
|
+
|
|
187
|
+
:param field: A tuple containing the name of the field and the value of the field.
|
|
188
|
+
:type field: :py:obj:`tuple`
|
|
189
|
+
:returns: Nothing.
|
|
190
|
+
:rtype: :py:obj:`None`
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
|
|
104
194
|
self.session.wialon_api.item_update_profile_field(
|
|
105
195
|
**{"itemId": self.id, "n": field[0], "v": field[1]}
|
|
106
196
|
)
|
|
107
197
|
|
|
108
198
|
def delete(self) -> None:
|
|
199
|
+
"""
|
|
200
|
+
Deletes the Wialon object.
|
|
201
|
+
|
|
202
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
203
|
+
:returns: Nothing.
|
|
204
|
+
:rtype: :py:obj:`None`
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
|
|
109
208
|
self.session.wialon_api.item_delete_item(**{"itemId": self.id})
|
|
110
209
|
|
|
111
210
|
def _get_cfields(self) -> dict:
|
|
@@ -4,6 +4,21 @@ from terminusgps.wialon.items.base import WialonBase
|
|
|
4
4
|
|
|
5
5
|
class WialonRetranslator(WialonBase):
|
|
6
6
|
def create(self, **kwargs) -> int | None:
|
|
7
|
+
"""
|
|
8
|
+
Creates a Wialon retranslator.
|
|
9
|
+
|
|
10
|
+
:param creator_id: A Wialon user that will create the retranslator.
|
|
11
|
+
:type creator_id: :py:obj:`str`
|
|
12
|
+
:param name: A name for the new retranslator.
|
|
13
|
+
:type name: :py:obj:`str`
|
|
14
|
+
:param config: A Wialon retranslator configuration object.
|
|
15
|
+
:type config: :py:obj:`dict`
|
|
16
|
+
:raises ValueError: If a required parameter was not provided.
|
|
17
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
18
|
+
:returns: Nothing.
|
|
19
|
+
:rtype: :py:obj:`None`
|
|
20
|
+
|
|
21
|
+
"""
|
|
7
22
|
if not kwargs.get("creator_id"):
|
|
8
23
|
raise ValueError("'creator_id' is required on creation.")
|
|
9
24
|
if not kwargs.get("name"):
|
|
@@ -20,3 +35,83 @@ class WialonRetranslator(WialonBase):
|
|
|
20
35
|
}
|
|
21
36
|
)
|
|
22
37
|
return response.get("item", {}).get("id")
|
|
38
|
+
|
|
39
|
+
def update_config(self, new_config: dict) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Updates the retranslator config to the new config.
|
|
42
|
+
|
|
43
|
+
:param new_config: A Wialon retranslator configuration.
|
|
44
|
+
:type units: :py:obj:`dict`
|
|
45
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
46
|
+
:returns: Nothing.
|
|
47
|
+
:rtype: :py:obj:`None`
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
self.session.wialon_api.retranslator_update_config(
|
|
51
|
+
**{"itemId": self.id, "config": new_config}
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def add_units(self, units: list[WialonBase]) -> None:
|
|
55
|
+
"""
|
|
56
|
+
Adds a list of units to the Wialon retranslator.
|
|
57
|
+
|
|
58
|
+
:param units: A list of Wialon unit objects.
|
|
59
|
+
:type units: :py:obj:`list`
|
|
60
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
61
|
+
:returns: Nothing.
|
|
62
|
+
:rtype: :py:obj:`None`
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
self.session.wialon_api.retranslator_update_units(
|
|
66
|
+
**{
|
|
67
|
+
"itemId": self.id,
|
|
68
|
+
"units": [{"a": unit.id, "i": unit.hw_type} for unit in units],
|
|
69
|
+
"callMode": "add",
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
def rm_units(self, units: list[WialonBase]) -> None:
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
Naively removes a list of units from the Wialon retranslator.
|
|
77
|
+
|
|
78
|
+
:param units: A list of Wialon unit objects.
|
|
79
|
+
:type units: :py:obj:`list`
|
|
80
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
81
|
+
:returns: Nothing.
|
|
82
|
+
:rtype: :py:obj:`None`
|
|
83
|
+
|
|
84
|
+
"""
|
|
85
|
+
self.session.wialon_api.retranslator_update_units(
|
|
86
|
+
**{
|
|
87
|
+
"itemId": self.id,
|
|
88
|
+
"units": [{"a": unit.id, "i": unit.hw_type} for unit in units],
|
|
89
|
+
"callMode": "remove",
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def start(self, stop: int | None = None) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Starts the Wialon retranslator.
|
|
96
|
+
|
|
97
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
98
|
+
:returns: Nothing.
|
|
99
|
+
:rtype: :py:obj:`None`
|
|
100
|
+
|
|
101
|
+
"""
|
|
102
|
+
self.session.wialon_api.retranslator_update_operating(
|
|
103
|
+
**{"itemId": self.id, "operate": int(True), "stopTime": stop}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def stop(self) -> None:
|
|
107
|
+
"""
|
|
108
|
+
Stops the Wialon retranslator.
|
|
109
|
+
|
|
110
|
+
:raises WialonError: If something went wrong with Wialon.
|
|
111
|
+
:returns: Nothing.
|
|
112
|
+
:rtype: :py:obj:`None`
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
self.session.wialon_api.retranslator_update_operating(
|
|
116
|
+
**{"itemId": self.id, "operate": int(False)}
|
|
117
|
+
)
|
terminusgps/wialon/items/unit.py
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
from urllib.parse import quote_plus
|
|
2
2
|
|
|
3
3
|
from terminusgps.wialon import flags
|
|
4
|
-
from terminusgps.wialon.items.base import WialonBase
|
|
4
|
+
from terminusgps.wialon.items.base import WialonBase
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class WialonUnit(WialonBase):
|
|
8
8
|
def create(self, **kwargs) -> int | None:
|
|
9
|
+
"""
|
|
10
|
+
Creates a new Wialon unit.
|
|
11
|
+
|
|
12
|
+
:param creator_id: A Wialon user id.
|
|
13
|
+
:type creator_id: :py:obj:`int`
|
|
14
|
+
:param name: A new name for the unit.
|
|
15
|
+
:type name: :py:obj:`str`
|
|
16
|
+
:param hw_type: A Wialon hardware type.
|
|
17
|
+
:type hw_type: :py:obj:`str`
|
|
18
|
+
:returns: The Wialon id for the new unit.
|
|
19
|
+
:rtype: :py:obj:`int` | :py:obj:`None`
|
|
20
|
+
|
|
21
|
+
"""
|
|
9
22
|
if not kwargs.get("creator_id"):
|
|
10
23
|
raise ValueError("'creator_id' is required on creation.")
|
|
11
24
|
if not kwargs.get("name"):
|
|
@@ -23,15 +36,6 @@ class WialonUnit(WialonBase):
|
|
|
23
36
|
)
|
|
24
37
|
return response.get("item", {}).get("id")
|
|
25
38
|
|
|
26
|
-
def populate(self) -> None:
|
|
27
|
-
super().populate()
|
|
28
|
-
unit_data = self.session.wialon_api.core_search_item(
|
|
29
|
-
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_ADVANCED_PROPERTIES}
|
|
30
|
-
)
|
|
31
|
-
self.uid = unit_data.get("uid", "")
|
|
32
|
-
self.phone = unit_data.get("ph", "")
|
|
33
|
-
self.is_active = bool(unit_data.get("act", 0))
|
|
34
|
-
|
|
35
39
|
def execute_command(
|
|
36
40
|
self,
|
|
37
41
|
name: str,
|
|
@@ -40,6 +44,24 @@ class WialonUnit(WialonBase):
|
|
|
40
44
|
flags: int = 0,
|
|
41
45
|
param: dict | None = None,
|
|
42
46
|
) -> None:
|
|
47
|
+
"""
|
|
48
|
+
Executes a command on this Wialon unit.
|
|
49
|
+
|
|
50
|
+
:param name: A Wialon command name.
|
|
51
|
+
:type name: :py:obj:`str`
|
|
52
|
+
:param link_type: A protocol to use for the Wialon command.
|
|
53
|
+
:type link_type: :py:obj:`str`
|
|
54
|
+
:param timeout: How long (in seconds) to wait before timing out command execution. Default is ``5``.
|
|
55
|
+
:type timeout: :py:obj:`int`
|
|
56
|
+
:param flags: Flags to pass to the Wialon command execution.
|
|
57
|
+
:type flags: :py:obj:`int`
|
|
58
|
+
:param param: Additional parameters to execute the command with.
|
|
59
|
+
:type param: :py:obj:`dict` | :py:obj:`None`
|
|
60
|
+
:returns: Nothing.
|
|
61
|
+
:rtype: :py:obj:`None`
|
|
62
|
+
|
|
63
|
+
"""
|
|
64
|
+
|
|
43
65
|
self.session.wialon_api.unit_exec_cmd(
|
|
44
66
|
**{
|
|
45
67
|
"itemId": self.id,
|
|
@@ -52,38 +74,78 @@ class WialonUnit(WialonBase):
|
|
|
52
74
|
)
|
|
53
75
|
|
|
54
76
|
def set_access_password(self, password: str) -> None:
|
|
77
|
+
"""
|
|
78
|
+
Sets a new access password for this Wialon unit.
|
|
79
|
+
|
|
80
|
+
:param password: A new access password.
|
|
81
|
+
:type name: :py:obj:`str`
|
|
82
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
83
|
+
:returns: Nothing.
|
|
84
|
+
:rtype: :py:obj:`None`
|
|
85
|
+
|
|
86
|
+
"""
|
|
87
|
+
|
|
55
88
|
self.session.wialon_api.unit_update_access_password(
|
|
56
89
|
**{"itemId": self.id, "accessPassword": password}
|
|
57
90
|
)
|
|
58
91
|
|
|
59
|
-
@repopulate
|
|
60
92
|
def activate(self) -> None:
|
|
61
|
-
|
|
62
|
-
|
|
93
|
+
"""
|
|
94
|
+
Activates this Wialon unit.
|
|
95
|
+
|
|
96
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
97
|
+
:returns: Nothing.
|
|
98
|
+
:rtype: :py:obj:`None`
|
|
99
|
+
|
|
100
|
+
"""
|
|
63
101
|
|
|
64
102
|
self.session.wialon_api.unit_set_active(
|
|
65
103
|
**{"itemId": self.id, "active": int(True)}
|
|
66
104
|
)
|
|
67
105
|
|
|
68
|
-
@repopulate
|
|
69
106
|
def deactivate(self) -> None:
|
|
70
|
-
|
|
71
|
-
|
|
107
|
+
"""
|
|
108
|
+
Deactivates this Wialon unit.
|
|
109
|
+
|
|
110
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
111
|
+
:returns: Nothing.
|
|
112
|
+
:rtype: :py:obj:`None`
|
|
113
|
+
|
|
114
|
+
"""
|
|
72
115
|
|
|
73
116
|
self.session.wialon_api.unit_set_active(
|
|
74
117
|
**{"itemId": self.id, "active": int(False)}
|
|
75
118
|
)
|
|
76
119
|
|
|
77
|
-
@repopulate
|
|
78
120
|
def assign_phone(self, phone: str) -> None:
|
|
121
|
+
"""
|
|
122
|
+
Assigns a phone number to this Wialon unit.
|
|
123
|
+
|
|
124
|
+
:param phone: A phone number beginning with a country code.
|
|
125
|
+
:type phone: :py:obj:`str`
|
|
126
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
127
|
+
:returns: Nothing.
|
|
128
|
+
:rtype: :py:obj:`None`
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
|
|
79
132
|
self.session.wialon_api.unit_update_phone(
|
|
80
133
|
**{"itemId": self.id, "phoneNumber": quote_plus(phone)}
|
|
81
134
|
)
|
|
82
135
|
|
|
83
136
|
def get_phone_numbers(self) -> list[str]:
|
|
137
|
+
"""
|
|
138
|
+
Retrieves all phone numbers assigned to this Wialon unit.
|
|
139
|
+
|
|
140
|
+
This includes the usually assigned phone number + custom/admin fields labeled ``to_number``.
|
|
141
|
+
|
|
142
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
143
|
+
:returns: A list of phone numbers.
|
|
144
|
+
:rtype: :py:obj:`list`
|
|
145
|
+
|
|
146
|
+
"""
|
|
147
|
+
|
|
84
148
|
phones = []
|
|
85
|
-
if self.phone:
|
|
86
|
-
phones.append(self.phone)
|
|
87
149
|
for field in self.cfields | self.afields:
|
|
88
150
|
if field["n"] == "to_number":
|
|
89
151
|
phones.append(field["v"])
|
|
@@ -4,6 +4,19 @@ from terminusgps.wialon.items.base import WialonBase
|
|
|
4
4
|
|
|
5
5
|
class WialonUnitGroup(WialonBase):
|
|
6
6
|
def create(self, **kwargs) -> int | None:
|
|
7
|
+
"""
|
|
8
|
+
Creates a new Wialon unit group.
|
|
9
|
+
|
|
10
|
+
:param creator_id: A Wialon user id.
|
|
11
|
+
:type creator_id: :py:obj:`int`
|
|
12
|
+
:param name: A name for the group.
|
|
13
|
+
:type name: :py:obj:`str`
|
|
14
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
15
|
+
:returns: The Wialon id for the new group.
|
|
16
|
+
:rtype: :py:obj:`int` | :py:obj:`None`
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
7
20
|
if not kwargs.get("creator_id"):
|
|
8
21
|
raise ValueError("'creator_id' is required on creation.")
|
|
9
22
|
if not kwargs.get("name"):
|
|
@@ -19,37 +32,107 @@ class WialonUnitGroup(WialonBase):
|
|
|
19
32
|
return response.get("item", {}).get("id")
|
|
20
33
|
|
|
21
34
|
def _update_items(self, new_items: list[str]) -> None:
|
|
35
|
+
"""
|
|
36
|
+
Sets this group's members to a list of Wialon unit ids.
|
|
37
|
+
|
|
38
|
+
:param new_items: A list of Wialon unit ids.
|
|
39
|
+
:type new_items: :py:obj:`list`
|
|
40
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
41
|
+
:returns: Nothing.
|
|
42
|
+
:rtype: :py:obj:`None`
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
|
|
22
46
|
self.session.wialon_api.unit_group_update_units(
|
|
23
47
|
**{"itemId": self.id, "units": new_items}
|
|
24
48
|
)
|
|
25
49
|
|
|
26
50
|
def is_member(self, item: WialonBase) -> bool:
|
|
51
|
+
"""
|
|
52
|
+
Determines whether or not ``item`` is a member of the group.
|
|
53
|
+
|
|
54
|
+
:param item: A Wialon object.
|
|
55
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
56
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
57
|
+
:returns: :py:obj:`True` if ``item`` is a member of the group, else :py:obj:`False`.
|
|
58
|
+
:rtype: :py:obj:`bool`
|
|
59
|
+
|
|
60
|
+
"""
|
|
27
61
|
return True if str(item.id) in self.items else False
|
|
28
62
|
|
|
29
63
|
def grant_access(
|
|
30
64
|
self, item: WialonBase, access_mask: int = constants.ACCESSMASK_UNIT_BASIC
|
|
31
65
|
) -> None:
|
|
66
|
+
"""
|
|
67
|
+
Grants ``item`` access to the group, if it didn't already have access.
|
|
68
|
+
|
|
69
|
+
:param item: A Wialon object.
|
|
70
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
71
|
+
:param access_mask: A Wialon access mask.
|
|
72
|
+
:type access_mask: :py:obj:`int`
|
|
73
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
74
|
+
:returns: Nothing.
|
|
75
|
+
:rtype: :py:obj:`None`
|
|
76
|
+
|
|
77
|
+
"""
|
|
32
78
|
self.session.wialon_api.user_update_item_access(
|
|
33
79
|
**{"userId": item.id, "itemId": self.id, "accessMask": access_mask}
|
|
34
80
|
)
|
|
35
81
|
|
|
36
82
|
def revoke_access(self, item: WialonBase) -> None:
|
|
83
|
+
"""
|
|
84
|
+
Revokes ``item``'s access from the group, if it had access.
|
|
85
|
+
|
|
86
|
+
:param item: A Wialon object.
|
|
87
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
88
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
89
|
+
:returns: Nothing.
|
|
90
|
+
:rtype: :py:obj:`None`
|
|
91
|
+
|
|
92
|
+
"""
|
|
37
93
|
self.session.wialon_api.user_update_item_access(
|
|
38
94
|
**{"userId": item.id, "itemId": self.id, "accessMask": 0}
|
|
39
95
|
)
|
|
40
96
|
|
|
41
97
|
def add_item(self, item: WialonBase) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Adds a Wialon unit to the group.
|
|
100
|
+
|
|
101
|
+
:param item: A Wialon object.
|
|
102
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
103
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
104
|
+
:returns: Nothing.
|
|
105
|
+
:rtype: :py:obj:`None`
|
|
106
|
+
|
|
107
|
+
"""
|
|
42
108
|
new_items: list[str] = self.items.copy() + [str(item.id)]
|
|
43
109
|
self._update_items(new_items)
|
|
44
110
|
|
|
45
111
|
def rm_item(self, item: WialonBase) -> None:
|
|
46
|
-
|
|
112
|
+
"""
|
|
113
|
+
Removes a Wialon unit from the group, if it's a member of the group.
|
|
114
|
+
|
|
115
|
+
:param item: A Wialon object.
|
|
116
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
117
|
+
:raises AssertionError: If the item wasn't in the group.
|
|
118
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
119
|
+
:returns: Nothing.
|
|
120
|
+
:rtype: :py:obj:`None`
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
assert self.is_member(item), f"Cannot remove {item}, it's not in the group"
|
|
47
124
|
new_items: list[str] = self.items.copy()
|
|
48
125
|
new_items.remove(str(item.id))
|
|
49
126
|
self._update_items(new_items)
|
|
50
127
|
|
|
51
128
|
@property
|
|
52
129
|
def items(self) -> list[str]:
|
|
130
|
+
"""
|
|
131
|
+
Returns a list of the group's Wialon unit ids.
|
|
132
|
+
|
|
133
|
+
:type: :py:obj:`list`
|
|
134
|
+
|
|
135
|
+
"""
|
|
53
136
|
response = self.session.wialon_api.core_search_items(
|
|
54
137
|
**{
|
|
55
138
|
"spec": {
|
terminusgps/wialon/items/user.py
CHANGED
|
@@ -7,6 +7,20 @@ from terminusgps.wialon import constants
|
|
|
7
7
|
|
|
8
8
|
class WialonUser(WialonBase):
|
|
9
9
|
def create(self, **kwargs) -> int | None:
|
|
10
|
+
"""
|
|
11
|
+
Creates a new Wialon user.
|
|
12
|
+
|
|
13
|
+
:param creator_id: A Wialon user id.
|
|
14
|
+
:type creator_id: :py:obj:`int`
|
|
15
|
+
:param name: A name for the user.
|
|
16
|
+
:type name: :py:obj:`str`
|
|
17
|
+
:param name: A password for the user.
|
|
18
|
+
:type name: :py:obj:`str`
|
|
19
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
20
|
+
:returns: The Wialon id for the new user.
|
|
21
|
+
:rtype: :py:obj:`int` | :py:obj:`None`
|
|
22
|
+
|
|
23
|
+
"""
|
|
10
24
|
if not kwargs.get("creator_id"):
|
|
11
25
|
raise ValueError("'creator_id' is required on creation.")
|
|
12
26
|
if not kwargs.get("name"):
|
|
@@ -25,6 +39,16 @@ class WialonUser(WialonBase):
|
|
|
25
39
|
return response.get("item", {}).get("id")
|
|
26
40
|
|
|
27
41
|
def _get_access_response(self, hw_type: str) -> dict:
|
|
42
|
+
"""
|
|
43
|
+
Returns a dict of the Wialon objects the user has access to.
|
|
44
|
+
|
|
45
|
+
:param hw_type: A hardware type of Wialon objects to generate a list for.
|
|
46
|
+
:type hw_type: :py:obj:`str`
|
|
47
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
48
|
+
:returns: The Wialon API response.
|
|
49
|
+
:rtype: :py:obj:`dict`
|
|
50
|
+
|
|
51
|
+
"""
|
|
28
52
|
return self.session.wialon_api.user_get_items_access(
|
|
29
53
|
**{
|
|
30
54
|
"userId": self.id,
|
|
@@ -36,40 +60,120 @@ class WialonUser(WialonBase):
|
|
|
36
60
|
|
|
37
61
|
@property
|
|
38
62
|
def units(self) -> list[str]:
|
|
63
|
+
"""
|
|
64
|
+
The user's units.
|
|
65
|
+
|
|
66
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
67
|
+
:returns: A list of unit ids the user has access to.
|
|
68
|
+
:rtype: :py:obj:`list`
|
|
69
|
+
|
|
70
|
+
"""
|
|
39
71
|
response = self._get_access_response(hw_type="avl_unit")
|
|
40
72
|
return [key for key in response.keys()]
|
|
41
73
|
|
|
42
74
|
@property
|
|
43
75
|
def groups(self) -> list[str]:
|
|
76
|
+
"""
|
|
77
|
+
The user's unit groups.
|
|
78
|
+
|
|
79
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
80
|
+
:returns: A list of group ids the user has access to.
|
|
81
|
+
:rtype: :py:obj:`list`
|
|
82
|
+
|
|
83
|
+
"""
|
|
44
84
|
response = self._get_access_response(hw_type="avl_unit_group")
|
|
45
85
|
return [key for key in response.keys()]
|
|
46
86
|
|
|
47
87
|
def has_access(self, other: WialonBase) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
Checks if the user has access to ``other``.
|
|
90
|
+
|
|
91
|
+
:param other: A Wialon object.
|
|
92
|
+
:type phone: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
93
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
94
|
+
:returns: :py:obj:`True` if the user can access ``other``, else :py:obj:`False`.
|
|
95
|
+
:rtype: :py:obj:`bool`
|
|
96
|
+
|
|
97
|
+
"""
|
|
48
98
|
response: dict = self._get_access_response(hw_type=other.hw_type)
|
|
49
99
|
items: list[str] = [key for key in response.keys()]
|
|
50
100
|
return True if str(other.id) in items else False
|
|
51
101
|
|
|
52
102
|
def assign_phone(self, phone: str) -> None:
|
|
103
|
+
"""
|
|
104
|
+
Assigns a phone number to the user.
|
|
105
|
+
|
|
106
|
+
:param phone: A phone number, including country code.
|
|
107
|
+
:type phone: :py:obj:`str`
|
|
108
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
109
|
+
:returns: Nothing.
|
|
110
|
+
:rtype: :py:obj:`None`
|
|
111
|
+
|
|
112
|
+
"""
|
|
53
113
|
self.add_cproperty(("phone", quote_plus(phone)))
|
|
54
114
|
|
|
55
115
|
def assign_email(self, email: str) -> None:
|
|
56
|
-
"""
|
|
116
|
+
"""
|
|
117
|
+
Assigns an email address to the user.
|
|
118
|
+
|
|
119
|
+
:param phone: An email address.
|
|
120
|
+
:type phone: :py:obj:`str`
|
|
121
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
122
|
+
:returns: Nothing.
|
|
123
|
+
:rtype: :py:obj:`None`
|
|
124
|
+
|
|
125
|
+
"""
|
|
57
126
|
self.add_cproperty(("email", email))
|
|
58
127
|
|
|
59
128
|
def grant_access(
|
|
60
129
|
self, item: WialonBase, access_mask: int = constants.ACCESSMASK_UNIT_BASIC
|
|
61
130
|
) -> None:
|
|
62
|
-
"""
|
|
131
|
+
"""
|
|
132
|
+
Grants the user access to ``item``.
|
|
133
|
+
|
|
134
|
+
:param item: A Wialon object.
|
|
135
|
+
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
136
|
+
:param access_mask: A Wialon access mask integer.
|
|
137
|
+
:type access_mask: :py:obj:`int`
|
|
138
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
139
|
+
:returns: Nothing.
|
|
140
|
+
:rtype: :py:obj:`None`
|
|
141
|
+
|
|
142
|
+
"""
|
|
63
143
|
self.session.wialon_api.user_update_item_access(
|
|
64
144
|
**{"userId": self.id, "itemId": item.id, "accessMask": access_mask}
|
|
65
145
|
)
|
|
66
146
|
|
|
67
147
|
def set_settings_flags(self, flags: int, flags_mask: int) -> None:
|
|
148
|
+
"""
|
|
149
|
+
Sets the user's settings flags.
|
|
150
|
+
|
|
151
|
+
:param flags: The new user settings flags.
|
|
152
|
+
:type flags: :py:obj:`int`
|
|
153
|
+
:param flags_mask: A user settings flag mask.
|
|
154
|
+
:type flags_mask: :py:obj:`int`
|
|
155
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
156
|
+
:returns: Nothing.
|
|
157
|
+
:rtype: :py:obj:`None`
|
|
158
|
+
|
|
159
|
+
"""
|
|
68
160
|
self.session.wialon_api.user_update_user_flags(
|
|
69
161
|
**{"userId": self.id, "flags": flags, "flagsMask": flags_mask}
|
|
70
162
|
)
|
|
71
163
|
|
|
72
164
|
def update_password(self, old_password: str, new_password: str) -> None:
|
|
165
|
+
"""
|
|
166
|
+
Updates the password of the user.
|
|
167
|
+
|
|
168
|
+
:param old_password: The user's original password.
|
|
169
|
+
:type old_password: :py:obj:`str`
|
|
170
|
+
:param new_password: A new password.
|
|
171
|
+
:type new_password: :py:obj:`str`
|
|
172
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
173
|
+
:returns: Nothing.
|
|
174
|
+
:rtype: :py:obj:`None`
|
|
175
|
+
|
|
176
|
+
"""
|
|
73
177
|
self.session.wialon_api.user_update_password(
|
|
74
178
|
**{
|
|
75
179
|
"userId": self.id,
|
terminusgps/wialon/session.py
CHANGED
|
@@ -1,65 +1,319 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
1
|
from wialon.api import Wialon, WialonError
|
|
2
|
+
from django.conf import settings
|
|
3
|
+
from django.core.exceptions import ImproperlyConfigured
|
|
4
4
|
|
|
5
|
-
from .errors import
|
|
5
|
+
from .errors import (
|
|
6
|
+
WialonLogoutError,
|
|
7
|
+
WialonLoginError,
|
|
8
|
+
WialonSessionDuplicationError,
|
|
9
|
+
WialonSessionInvalidError,
|
|
10
|
+
)
|
|
6
11
|
|
|
7
12
|
|
|
8
13
|
class WialonSession:
|
|
9
|
-
def __init__(
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
token: str | None = None,
|
|
17
|
+
sid: str | None = None,
|
|
18
|
+
scheme: str = "https",
|
|
19
|
+
host: str = "hst-api.wialon.com",
|
|
20
|
+
port: int = 443,
|
|
21
|
+
) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Starts or continues a Wialon API session.
|
|
24
|
+
|
|
25
|
+
:param token: An optional Wialon API token. Default is :confval:`WIALON_TOKEN`.
|
|
26
|
+
:type token: :py:obj:`str` | :py:obj:`None`
|
|
27
|
+
:param sid: An optional Wialon API session id. If provided, the session is continued.
|
|
28
|
+
:type sid: :py:obj:`str` | :py:obj:`None`
|
|
29
|
+
:raises ImproperlyConfigured: If either :confval:`WIALON_TOKEN` or :confval:`WIALON_ADMIN_ID` is not set.
|
|
30
|
+
:returns: Nothing.
|
|
31
|
+
:rtype: :py:obj:`None`
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
if not hasattr(settings, "WIALON_TOKEN"):
|
|
35
|
+
raise ImproperlyConfigured("'WIALON_TOKEN' setting is required.")
|
|
36
|
+
if not hasattr(settings, "WIALON_ADMIN_ID"):
|
|
37
|
+
raise ImproperlyConfigured("'WIALON_ADMIN_ID' setting is required.")
|
|
38
|
+
|
|
39
|
+
self.wialon_api = Wialon(scheme=scheme, host=host, port=port, sid=sid)
|
|
10
40
|
self.token = token
|
|
11
|
-
self.
|
|
12
|
-
|
|
13
|
-
|
|
41
|
+
self._username = None
|
|
42
|
+
self._gis_sid = None
|
|
43
|
+
self._hw_gp_ip = None
|
|
44
|
+
self._wsdk_version = None
|
|
45
|
+
self._uid = None
|
|
46
|
+
|
|
47
|
+
def __enter__(self) -> "WialonSession":
|
|
48
|
+
assert self.token, "Wialon API token was not set"
|
|
49
|
+
self.login(self.token)
|
|
50
|
+
return self
|
|
51
|
+
|
|
52
|
+
def __exit__(self, *args, **kwargs) -> None:
|
|
53
|
+
self.logout()
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def active(self) -> bool:
|
|
57
|
+
"""
|
|
58
|
+
Whether or not the Wialon session is currently active.
|
|
59
|
+
|
|
60
|
+
:type: :py:obj:`bool`
|
|
61
|
+
:value: :py:obj:`False`
|
|
62
|
+
"""
|
|
63
|
+
is_active = False
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
response = self.wialon_api.core_duplicate(**{"restore": 1})
|
|
67
|
+
is_active = bool(response)
|
|
68
|
+
except WialonError as e:
|
|
69
|
+
raise WialonSessionInvalidError(self.id, e)
|
|
70
|
+
finally:
|
|
71
|
+
return is_active
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def gis_geocode(self) -> str | None:
|
|
75
|
+
"""
|
|
76
|
+
Gis geocode URL.
|
|
77
|
+
|
|
78
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
79
|
+
:value: :py:obj:`None`
|
|
80
|
+
|
|
81
|
+
"""
|
|
82
|
+
return self._gis_geocode
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def gis_render(self) -> str | None:
|
|
86
|
+
"""
|
|
87
|
+
Gis rendering URL.
|
|
88
|
+
|
|
89
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
90
|
+
:value: :py:obj:`None`
|
|
91
|
+
|
|
92
|
+
"""
|
|
93
|
+
return self._gis_render
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def gis_routing(self) -> str | None:
|
|
97
|
+
"""
|
|
98
|
+
Gis routing URL.
|
|
99
|
+
|
|
100
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
101
|
+
:value: :py:obj:`None`
|
|
102
|
+
|
|
103
|
+
"""
|
|
104
|
+
return self._gis_routing
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def gis_search(self) -> str | None:
|
|
108
|
+
"""
|
|
109
|
+
Gis search URL.
|
|
110
|
+
|
|
111
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
112
|
+
:value: :py:obj:`None`
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
return self._gis_search
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def gis_sid(self) -> str | None:
|
|
119
|
+
"""
|
|
120
|
+
Gis session id.
|
|
121
|
+
|
|
122
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
123
|
+
:value: :py:obj:`None`
|
|
124
|
+
|
|
125
|
+
"""
|
|
126
|
+
return self._gis_sid
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def host(self) -> str | None:
|
|
130
|
+
"""
|
|
131
|
+
IP of the client hosting the Wialon session.
|
|
132
|
+
|
|
133
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
134
|
+
:value: :py:obj:`None`
|
|
135
|
+
|
|
136
|
+
"""
|
|
137
|
+
return self._host
|
|
138
|
+
|
|
139
|
+
@property
|
|
140
|
+
def hw_gw_ip(self) -> str | None:
|
|
141
|
+
"""
|
|
142
|
+
Hardware gateway IP.
|
|
143
|
+
|
|
144
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
145
|
+
:value: :py:obj:`None`
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
return self._hw_gw_ip
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def hw_gw_dns(self) -> str | None:
|
|
152
|
+
"""
|
|
153
|
+
Hardware gateway domain name, should evaluate to :py:attr:`hw_gw_ip` if present.
|
|
154
|
+
|
|
155
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
156
|
+
:value: :py:obj:`None`
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
return self._hw_gw_dns
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def wsdk_version(self) -> str | None:
|
|
163
|
+
"""
|
|
164
|
+
The Wialon Source Developer Kit (WSDK) version number of the session.
|
|
165
|
+
|
|
166
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
167
|
+
:value: :py:obj:`None`
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
return self._wsdk_version
|
|
171
|
+
|
|
172
|
+
@property
|
|
173
|
+
def uid(self) -> str | None:
|
|
174
|
+
"""
|
|
175
|
+
A Wialon user ID this session is operating as.
|
|
176
|
+
|
|
177
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
178
|
+
:value: :py:obj:`None`
|
|
179
|
+
"""
|
|
180
|
+
return self._uid
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def username(self) -> str | None:
|
|
184
|
+
"""
|
|
185
|
+
A Wialon username the session is operating as.
|
|
186
|
+
|
|
187
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
188
|
+
:value: :py:obj:`None`
|
|
189
|
+
|
|
190
|
+
"""
|
|
191
|
+
return self._username
|
|
14
192
|
|
|
15
193
|
@property
|
|
16
194
|
def id(self) -> str | None:
|
|
195
|
+
"""
|
|
196
|
+
Shortcut property for :py:attr:`WialonSession.wialon_api.sid`.
|
|
197
|
+
|
|
198
|
+
Returns :py:obj:`None` if the session wasn't logged in.
|
|
199
|
+
|
|
200
|
+
:type: :py:obj:`str` | :py:obj:`None`
|
|
201
|
+
:value: :py:obj:`None`
|
|
202
|
+
|
|
203
|
+
"""
|
|
17
204
|
return self.wialon_api.sid
|
|
18
205
|
|
|
19
206
|
@property
|
|
20
|
-
def token(self) -> str
|
|
207
|
+
def token(self) -> str:
|
|
208
|
+
"""
|
|
209
|
+
A Wialon API token set during :py:meth:`WialonSession.__init__`.
|
|
210
|
+
|
|
211
|
+
Default token value is :confval:`WIALON_TOKEN`.
|
|
212
|
+
|
|
213
|
+
:type: :py:obj:`str`
|
|
214
|
+
:value: :confval:`WIALON_TOKEN`
|
|
215
|
+
|
|
216
|
+
"""
|
|
21
217
|
return self._token
|
|
22
218
|
|
|
23
219
|
@token.setter
|
|
24
220
|
def token(self, value: str | None = None) -> None:
|
|
25
|
-
self._token = value if value else
|
|
221
|
+
self._token = value if value else settings.WIALON_TOKEN
|
|
26
222
|
|
|
27
|
-
def
|
|
28
|
-
|
|
29
|
-
|
|
223
|
+
def duplicate(self, username: str | None = None, continued: bool = False) -> str:
|
|
224
|
+
"""
|
|
225
|
+
Duplicates the active Wialon API session.
|
|
30
226
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
self.host = login_response.get("host", "")
|
|
42
|
-
self.hw_gp_ip = login_response.get("hw_gw_ip", "")
|
|
43
|
-
self.video_service_url = login_response.get("video_service_url", "")
|
|
44
|
-
self.wsdk_version = login_response.get("wsdk_version", "")
|
|
45
|
-
return
|
|
46
|
-
|
|
47
|
-
def login(self, token: str | None = None) -> None:
|
|
48
|
-
"""Logs into the Wialon API and starts a new session."""
|
|
49
|
-
if not token:
|
|
50
|
-
raise ValueError("Must provide a Wialon API token to login with.")
|
|
227
|
+
:param username: A Wialon user to operate as in the session.
|
|
228
|
+
:type username: :py:obj:`str` | :py:obj:`None`
|
|
229
|
+
:param continue_session: Whether or not the original session id should be valid after duplication.
|
|
230
|
+
:type continue_session: :py:obj:`bool`
|
|
231
|
+
:raises WialonSessionDuplicationError: If the Wialon session was not duplicated.
|
|
232
|
+
:raises AssertionError: If the session was already active.
|
|
233
|
+
:returns: The new session id.
|
|
234
|
+
:rtype: :py:obj:`str`
|
|
235
|
+
|
|
236
|
+
"""
|
|
51
237
|
try:
|
|
52
|
-
|
|
53
|
-
|
|
238
|
+
assert self.active, "Cannot duplicate an inactive session."
|
|
239
|
+
response = self.wialon_api.core_duplicate(
|
|
240
|
+
**{"operateAs": username, "continueCurrentSession": continued}
|
|
54
241
|
)
|
|
55
|
-
|
|
242
|
+
self._set_login_response(response)
|
|
243
|
+
return response.get("eid")
|
|
244
|
+
except (WialonError, AssertionError) as e:
|
|
245
|
+
raise WialonSessionDuplicationError(self.id, e)
|
|
246
|
+
|
|
247
|
+
def login(self, token: str, flags: int = sum([0x1, 0x2, 0x20])) -> str:
|
|
248
|
+
"""
|
|
249
|
+
Logs into the Wialon API and starts a new session.
|
|
250
|
+
|
|
251
|
+
:param token: An active Wialon API token.
|
|
252
|
+
:type token: :py:obj:`str`
|
|
253
|
+
:param user_id: A user to operate as in the Wialon API session.
|
|
254
|
+
:type user_id: :py:obj:`str` | :py:obj:`None`
|
|
255
|
+
:param flags: A login response flag integer.
|
|
256
|
+
:type flags: :py:obj:`int`
|
|
257
|
+
:raises WialonLoginError: If the login fails.
|
|
258
|
+
:raises AssertionError: If the session was already active.
|
|
259
|
+
:returns: The new session id.
|
|
260
|
+
:rtype: :py:obj:`str`
|
|
261
|
+
|
|
262
|
+
"""
|
|
263
|
+
try:
|
|
264
|
+
assert not self.active, "Cannot login to an active session."
|
|
265
|
+
response = self.wialon_api.token_login(**{"token": token, "fl": flags})
|
|
266
|
+
self._set_login_response(response)
|
|
267
|
+
return response.get("eid")
|
|
268
|
+
except (WialonError, AssertionError) as e:
|
|
56
269
|
raise WialonLoginError(token, e)
|
|
57
|
-
else:
|
|
58
|
-
self._deconstruct_login_response(login_response)
|
|
59
270
|
|
|
60
271
|
def logout(self) -> None:
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
272
|
+
"""
|
|
273
|
+
Logs out of the Wialon API session.
|
|
274
|
+
|
|
275
|
+
:raises WialonLogoutError: If the logout fails.
|
|
276
|
+
:returns: Nothing.
|
|
277
|
+
:rtype: :py:obj:`None`
|
|
278
|
+
|
|
279
|
+
"""
|
|
280
|
+
response: dict = self.wialon_api.core_logout({})
|
|
281
|
+
if response.get("error") != 0:
|
|
282
|
+
raise WialonLogoutError(str(self.id))
|
|
283
|
+
|
|
284
|
+
def _set_login_response(self, login_response: dict) -> None:
|
|
285
|
+
"""
|
|
286
|
+
Sets the Wialon API session's attributes based on a login response.
|
|
287
|
+
|
|
288
|
+
:param login_response: A response returned from :py:meth:`login` or :py:meth:`duplicate`.
|
|
289
|
+
:type login_response: :py:obj:`dict`
|
|
290
|
+
:returns: Nothing.
|
|
291
|
+
:rtype: :py:obj:`None`
|
|
292
|
+
|
|
293
|
+
"""
|
|
294
|
+
self.wialon_api.sid = login_response.get("eid")
|
|
295
|
+
self._gis_geocode = login_response.get("gis_geocode")
|
|
296
|
+
self._gis_render = login_response.get("gis_render")
|
|
297
|
+
self._gis_routing = login_response.get("gis_routing")
|
|
298
|
+
self._gis_search = login_response.get("gis_search")
|
|
299
|
+
self._gis_sid = login_response.get("gis_sid")
|
|
300
|
+
self._host = login_response.get("host")
|
|
301
|
+
self._hw_gw_dns = login_response.get("hw_gw_dns")
|
|
302
|
+
self._hw_gw_ip = login_response.get("hw_gw_ip")
|
|
303
|
+
self._uid = login_response.get("user", {}).get("id")
|
|
304
|
+
self._nm = login_response.get("user", {}).get("nm")
|
|
305
|
+
self._username = login_response.get("au")
|
|
306
|
+
self._video_service_url = login_response.get("video_service_url")
|
|
307
|
+
self._wsdk_version = login_response.get("wsdk_version")
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def main() -> None:
|
|
311
|
+
session = WialonSession()
|
|
312
|
+
session.login(token=settings.WIALON_TOKEN)
|
|
313
|
+
session.duplicate(username="chrissyron@gmail.com", continued=False)
|
|
314
|
+
session.logout()
|
|
315
|
+
return
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if __name__ == "__main__":
|
|
319
|
+
main()
|
terminusgps/wialon/utils.py
CHANGED
|
@@ -5,15 +5,6 @@ from .session import WialonSession
|
|
|
5
5
|
from .flags import DATAFLAG_UNIT_BASE
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def repopulate(func):
|
|
9
|
-
def wrapper(self, *args, **kwargs):
|
|
10
|
-
result = func(self, *args, **kwargs)
|
|
11
|
-
self.populate()
|
|
12
|
-
return result
|
|
13
|
-
|
|
14
|
-
return wrapper
|
|
15
|
-
|
|
16
|
-
|
|
17
8
|
def is_unique(value: str, session: WialonSession, items_type: str = "avl_unit") -> bool:
|
|
18
9
|
"""Determines if the value is unique among Wialon objects of type 'items_type'."""
|
|
19
10
|
result = session.wialon_api.core_check_unique(
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
terminusgps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
terminusgps/authorizenet/auth.py,sha256=TBq_PY_-kUlg7ZOK4iWxJbpOnMkM5170j3ZyWSsuq6E,472
|
|
4
|
-
terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
terminusgps/aws/secrets.py,sha256=kgRA77rs0mD4berWRLkPtJLOe4Grf--o5f8NzwQqXCk,360
|
|
6
|
-
terminusgps/wialon/__init__.py,sha256=vDlkEycUXBKRaZHJXpZIKis3v3Lmp1qjt9FNx3PtjZk,166
|
|
7
|
-
terminusgps/wialon/constants.py,sha256=dsQaNt3TIjIZbr_m94KmBGFdrqe6HER2r6lol3X8QpU,2802
|
|
8
|
-
terminusgps/wialon/errors.py,sha256=AFnu6RHPFlJ6x3zAC-iKn4x_8PyUgheY2IOSEv02Sp4,880
|
|
9
|
-
terminusgps/wialon/flags.py,sha256=-OoH-eZM54yjRqxsAXL8VImdQu_7C0OAxCrFqaCEuko,13510
|
|
10
|
-
terminusgps/wialon/session.py,sha256=A8vJbofARlOMXxc_ihSbgPSPM5B1tRtS8EjvNRB2wS8,2327
|
|
11
|
-
terminusgps/wialon/utils.py,sha256=Y3N_U1-KDROvGZrVDECvBuAy1iJUazvisfPSCpsn-gg,2052
|
|
12
|
-
terminusgps/wialon/items/__init__.py,sha256=3BVthghekMvhMQSzQgBMlD_phxmKSmp3Zvmo-z0O8Bs,211
|
|
13
|
-
terminusgps/wialon/items/account.py,sha256=j6CoNe-NCqGOtYtoG5SY-pHviqDKIVQOsWm7zxF0yP0,504
|
|
14
|
-
terminusgps/wialon/items/base.py,sha256=bmqcCmTPNXaZJA1NOXHuPvby2LNM6pwNN1jNrGg5XwU,4254
|
|
15
|
-
terminusgps/wialon/items/resource.py,sha256=uK93I9dPKzZbVyxpEhfR2OdJMabYzB4vC2_FgYLlRu4,810
|
|
16
|
-
terminusgps/wialon/items/retranslator.py,sha256=HkL_asa_4VTRDvl7e6I9rtUhF0PBV3HRmecgesneHUM,839
|
|
17
|
-
terminusgps/wialon/items/route.py,sha256=qOHPN_rejwiGqvwWzlwmUIAIyc3lKavCalf8ki66rx0,760
|
|
18
|
-
terminusgps/wialon/items/unit.py,sha256=i9rZfcX7MFkSedwaJbSzbI9CLC9Xd50R-cqwSG36S18,2828
|
|
19
|
-
terminusgps/wialon/items/unit_group.py,sha256=CHcBS5hjiCKYsFts_tvc93V3rwu8wm5Ip-ykMM4_aEo,2548
|
|
20
|
-
terminusgps/wialon/items/user.py,sha256=3eEPOr4ixnK-5b2J4_Rlh3p2lbo5HxecTO-0109vdKc,2919
|
|
21
|
-
python_terminusgps-1.4.6.dist-info/METADATA,sha256=AQQYHavcVlNHuT8Ys5aG35kgbUjByjjdzB5dC4Ygz_E,882
|
|
22
|
-
python_terminusgps-1.4.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
23
|
-
python_terminusgps-1.4.6.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
24
|
-
python_terminusgps-1.4.6.dist-info/RECORD,,
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from terminusgps.wialon.items.base import WialonBase
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class WialonAccount(WialonBase):
|
|
5
|
-
def create(self, **kwargs) -> int | None:
|
|
6
|
-
if not kwargs.get("resource_id"):
|
|
7
|
-
raise ValueError("'resource_id' is required for creation.")
|
|
8
|
-
|
|
9
|
-
self.session.wialon_api.account_create_account(
|
|
10
|
-
**{
|
|
11
|
-
"itemId": kwargs["resource_id"],
|
|
12
|
-
"plan": kwargs.get("plan", "terminusgps_ext_hist"),
|
|
13
|
-
}
|
|
14
|
-
)
|
|
15
|
-
return int(kwargs["resource_id"])
|
|
File without changes
|
|
File without changes
|