python-terminusgps 19.3.0__py3-none-any.whl → 20.1.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.
- {python_terminusgps-19.3.0.dist-info → python_terminusgps-20.1.0.dist-info}/METADATA +1 -1
- {python_terminusgps-19.3.0.dist-info → python_terminusgps-20.1.0.dist-info}/RECORD +7 -7
- terminusgps/wialon/items/unit_group.py +38 -4
- terminusgps/wialon/logger.py +29 -0
- terminusgps/wialon/session.py +40 -61
- terminusgps/wialon/errors.py +0 -29
- {python_terminusgps-19.3.0.dist-info → python_terminusgps-20.1.0.dist-info}/WHEEL +0 -0
- {python_terminusgps-19.3.0.dist-info → python_terminusgps-20.1.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: 20.1.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
|
|
@@ -15,9 +15,9 @@ terminusgps/twilio/__init__.py,sha256=dYo41F2jft_eHDWSUtSpKGSRG1bewq_qClqilUJZkY
|
|
|
15
15
|
terminusgps/twilio/caller.py,sha256=nHCIwUulo-C_v2orsp6OY0nuJA6YetSkxpMTwrRQ-uA,1831
|
|
16
16
|
terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
terminusgps/wialon/constants.py,sha256=u7y9MsA5LYvjPjxJnCMQdprTF3QhPPR9j4MvzoSNBaw,1628
|
|
18
|
-
terminusgps/wialon/errors.py,sha256=Fl8A0peF5HpDdR3y0r3g86-iQ4kQgye3FYQZKGe3T7Y,984
|
|
19
18
|
terminusgps/wialon/flags.py,sha256=-OoH-eZM54yjRqxsAXL8VImdQu_7C0OAxCrFqaCEuko,13510
|
|
20
|
-
terminusgps/wialon/
|
|
19
|
+
terminusgps/wialon/logger.py,sha256=nUBsaLMaffSaAHGHAM6mFXDzix9hbNecVtA3INVtii8,968
|
|
20
|
+
terminusgps/wialon/session.py,sha256=47Cq3cM4sF-lySPtafzizKHeHbfuDuK1CnR0Jrmwk-Q,10634
|
|
21
21
|
terminusgps/wialon/utils.py,sha256=KeZmV-MEdGOHXrsyn6IIoyX0EgVYiWYjvacXyZVr1u8,6501
|
|
22
22
|
terminusgps/wialon/items/__init__.py,sha256=cfUC5sfVsTwmpgsR-w9wA4ay6_EZYAPgEeuw2k06RJM,256
|
|
23
23
|
terminusgps/wialon/items/base.py,sha256=EAtzlnCvB7WTu3iX1bV1-S9TvwXc-Eez7e0X4TMiK9U,6943
|
|
@@ -27,9 +27,9 @@ terminusgps/wialon/items/resource.py,sha256=79SwbCyE1zlaoeBfU0erEqvqBAYUC4KAKs8A
|
|
|
27
27
|
terminusgps/wialon/items/retranslator.py,sha256=8q9EDc92w92MElnHIeEzH3Ra4kiPXrx4t9V5nPDZuRU,3728
|
|
28
28
|
terminusgps/wialon/items/route.py,sha256=PTJx1gmT_PGz7nlSSUS2VzjYD-aAuvkEOIdIFneUSSQ,1148
|
|
29
29
|
terminusgps/wialon/items/unit.py,sha256=PwF7xlpDWI5MpM_u6TmYZjNHWk6TSKM4rJ4OB9CIn4A,7533
|
|
30
|
-
terminusgps/wialon/items/unit_group.py,sha256=
|
|
30
|
+
terminusgps/wialon/items/unit_group.py,sha256=LdDCAz3lrr7ROAVKqx2joNitIi22Pw3mS7khAbtcGlc,5036
|
|
31
31
|
terminusgps/wialon/items/user.py,sha256=INwAibQVmjNNelepQXMfDevgJqMvIjHHgEjAMLRvhB0,7082
|
|
32
|
-
python_terminusgps-
|
|
33
|
-
python_terminusgps-
|
|
34
|
-
python_terminusgps-
|
|
35
|
-
python_terminusgps-
|
|
32
|
+
python_terminusgps-20.1.0.dist-info/METADATA,sha256=eOfT7nITGn2pLypPyBtiIImAN0npLFSP3_R-s60986Q,912
|
|
33
|
+
python_terminusgps-20.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
34
|
+
python_terminusgps-20.1.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
35
|
+
python_terminusgps-20.1.0.dist-info/RECORD,,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
from typing import Type
|
|
2
1
|
from terminusgps.wialon import flags
|
|
3
2
|
from terminusgps.wialon.items.base import WialonBase
|
|
4
3
|
|
|
@@ -47,7 +46,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
47
46
|
**{"itemId": self.id, "units": new_items}
|
|
48
47
|
)
|
|
49
48
|
|
|
50
|
-
def is_member(self, item:
|
|
49
|
+
def is_member(self, item: WialonBase) -> bool:
|
|
51
50
|
"""
|
|
52
51
|
Determines whether or not ``item`` is a member of the group.
|
|
53
52
|
|
|
@@ -60,7 +59,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
60
59
|
"""
|
|
61
60
|
return True if str(item.id) in self.items else False
|
|
62
61
|
|
|
63
|
-
def add_item(self, item:
|
|
62
|
+
def add_item(self, item: WialonBase) -> None:
|
|
64
63
|
"""
|
|
65
64
|
Adds a Wialon item to the group.
|
|
66
65
|
|
|
@@ -74,7 +73,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
74
73
|
new_items: list[str] = self.items.copy() + [str(item.id)]
|
|
75
74
|
self.set_items(new_items)
|
|
76
75
|
|
|
77
|
-
def rm_item(self, item:
|
|
76
|
+
def rm_item(self, item: WialonBase) -> None:
|
|
78
77
|
"""
|
|
79
78
|
Removes a Wialon unit from the group, if it's a member of the group.
|
|
80
79
|
|
|
@@ -116,3 +115,38 @@ class WialonUnitGroup(WialonBase):
|
|
|
116
115
|
}
|
|
117
116
|
)
|
|
118
117
|
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.utils import timezone
|
|
124
|
+
from django.conf import settings
|
|
125
|
+
from terminusgps.wialon.session import WialonSession
|
|
126
|
+
from terminusgps.wialon.items import WialonUnit
|
|
127
|
+
from terminusgps.wialon.utils import get_hw_type_id
|
|
128
|
+
|
|
129
|
+
timestamp = f"{timezone.now():%Y_%m_%d_%H:%M:%S}"
|
|
130
|
+
with WialonSession(log_level=logging.DEBUG) as session:
|
|
131
|
+
unit = WialonUnit(
|
|
132
|
+
id=None,
|
|
133
|
+
session=session,
|
|
134
|
+
creator_id=settings.WIALON_ADMIN_ID,
|
|
135
|
+
name=f"test_unit_{timestamp}",
|
|
136
|
+
hw_type_id=get_hw_type_id("Test HW", session=session),
|
|
137
|
+
)
|
|
138
|
+
group = WialonUnitGroup(
|
|
139
|
+
id=None,
|
|
140
|
+
session=session,
|
|
141
|
+
creator_id=settings.WIALON_ADMIN_ID,
|
|
142
|
+
name=f"test_group_{timestamp}",
|
|
143
|
+
)
|
|
144
|
+
group.add_item(unit)
|
|
145
|
+
print(f"{group.items = }")
|
|
146
|
+
unit.delete()
|
|
147
|
+
group.delete()
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if __name__ == "__main__":
|
|
152
|
+
main()
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class WialonLogger:
|
|
5
|
+
def __init__(
|
|
6
|
+
self,
|
|
7
|
+
logger: logging.Logger,
|
|
8
|
+
level: int = logging.DEBUG,
|
|
9
|
+
format: str = "%(name)s - %(levelname)s - %(asctime)s - %(message)s",
|
|
10
|
+
use_stream_handler: bool = True,
|
|
11
|
+
use_file_handler: bool = False,
|
|
12
|
+
filename: str = "wialon_debug.log",
|
|
13
|
+
) -> None:
|
|
14
|
+
self.logger = logger
|
|
15
|
+
self.logger.setLevel(level)
|
|
16
|
+
formatter = logging.Formatter(format)
|
|
17
|
+
|
|
18
|
+
if use_stream_handler and not self.logger.handlers:
|
|
19
|
+
stream_handler = logging.StreamHandler()
|
|
20
|
+
stream_handler.setFormatter(formatter)
|
|
21
|
+
self.logger.addHandler(stream_handler)
|
|
22
|
+
|
|
23
|
+
if use_file_handler and not self.logger.handlers:
|
|
24
|
+
file_handler = logging.FileHandler(filename)
|
|
25
|
+
file_handler.setFormatter(formatter)
|
|
26
|
+
self.logger.addHandler(file_handler)
|
|
27
|
+
|
|
28
|
+
def get_logger(self) -> logging.Logger:
|
|
29
|
+
return self.logger
|
terminusgps/wialon/session.py
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import threading
|
|
2
|
-
import logging
|
|
3
|
-
import typing
|
|
4
1
|
import dataclasses
|
|
5
2
|
import datetime
|
|
3
|
+
import logging
|
|
4
|
+
import threading
|
|
5
|
+
import typing
|
|
6
6
|
|
|
7
|
-
from wialon.api import WialonError
|
|
8
|
-
from wialon.api import Wialon as WialonAPI
|
|
9
7
|
from django.conf import settings
|
|
10
8
|
from django.utils import timezone
|
|
9
|
+
from wialon.api import Wialon as WialonBase
|
|
10
|
+
from wialon.api import WialonError
|
|
11
11
|
|
|
12
|
-
from terminusgps.wialon.
|
|
12
|
+
from terminusgps.wialon.logger import WialonLogger
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@dataclasses.dataclass
|
|
@@ -22,27 +22,21 @@ class WialonAPICall:
|
|
|
22
22
|
error: Exception | None = None
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class Wialon(
|
|
25
|
+
class Wialon(WialonBase):
|
|
26
26
|
def __init__(self, log_level: int = logging.INFO, *args, **kwargs) -> None:
|
|
27
27
|
super().__init__(*args, **kwargs)
|
|
28
28
|
self.call_history: list[WialonAPICall] = []
|
|
29
|
-
self.logger =
|
|
29
|
+
self.logger = WialonLogger(
|
|
30
|
+
logging.getLogger(self.__class__.__name__), level=log_level
|
|
31
|
+
).get_logger()
|
|
30
32
|
|
|
31
33
|
@property
|
|
32
34
|
def total_calls(self) -> int:
|
|
33
35
|
return len(self.call_history)
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
return
|
|
38
|
-
|
|
39
|
-
@property
|
|
40
|
-
def failed_calls(self) -> list[WialonAPICall | None]:
|
|
41
|
-
return [call for call in self.call_history if call.error]
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def failure_rate(self) -> float:
|
|
45
|
-
return len(self.failed_calls) / self.total_calls
|
|
37
|
+
def token_login(self, *args, **kwargs) -> typing.Any:
|
|
38
|
+
kwargs["appName"] = "python-terminusgps"
|
|
39
|
+
return self.call("token_login", *args, **kwargs)
|
|
46
40
|
|
|
47
41
|
def call(self, action_name: str, *argc, **kwargs) -> typing.Any:
|
|
48
42
|
self.logger.debug(f"Executing '{action_name}'...")
|
|
@@ -56,31 +50,18 @@ class Wialon(WialonAPI):
|
|
|
56
50
|
self.logger.debug(f"Executed '{action_name}' successfully.")
|
|
57
51
|
return result
|
|
58
52
|
except WialonError as e:
|
|
59
|
-
self.logger.warning(f"Failed to execute '{action_name}': '{e}'")
|
|
60
53
|
call_record.error = e
|
|
61
|
-
|
|
54
|
+
self.logger.warning(f"Failed to execute '{action_name}': '{e}'")
|
|
55
|
+
return
|
|
62
56
|
finally:
|
|
63
57
|
self.call_history.append(call_record)
|
|
64
58
|
|
|
65
|
-
def create_logger(self, log_level: int) -> logging.Logger:
|
|
66
|
-
logger = logging.getLogger(self.__class__.__name__)
|
|
67
|
-
handler = logging.StreamHandler()
|
|
68
|
-
formatter = logging.Formatter(
|
|
69
|
-
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
logger.setLevel(log_level)
|
|
73
|
-
handler.setFormatter(formatter)
|
|
74
|
-
logger.addHandler(handler)
|
|
75
|
-
return logger
|
|
76
|
-
|
|
77
59
|
|
|
78
60
|
class WialonSession:
|
|
79
61
|
def __init__(
|
|
80
62
|
self,
|
|
81
63
|
token: str | None = None,
|
|
82
64
|
sid: str | None = None,
|
|
83
|
-
uid: str | None = None,
|
|
84
65
|
scheme: str = "https",
|
|
85
66
|
host: str = "hst-api.wialon.com",
|
|
86
67
|
port: int = 443,
|
|
@@ -93,35 +74,31 @@ class WialonSession:
|
|
|
93
74
|
:type token: :py:obj:`str` | :py:obj:`None`
|
|
94
75
|
:param sid: An optional Wialon API session id. If provided, the session is continued.
|
|
95
76
|
:type sid: :py:obj:`str` | :py:obj:`None`
|
|
96
|
-
:
|
|
77
|
+
:param scheme: HTTP request scheme to use. Default is ``"https"``.
|
|
78
|
+
:type scheme: :py:obj:`str`
|
|
79
|
+
:param host: Wialon API host url. Default is ``"hst-api.wialon.com"``.
|
|
80
|
+
:type host: :py:obj:`str`
|
|
81
|
+
:param port: Wialon API host port. Default is ``443``.
|
|
82
|
+
:type port: :py:obj:`int`
|
|
83
|
+
:param log_level: Severity level at which log messages should be handled. Default is ``20`` (logging.INFO).
|
|
84
|
+
:type log_level: :py:obj:`int`
|
|
97
85
|
:returns: Nothing.
|
|
98
86
|
:rtype: :py:obj:`None`
|
|
99
87
|
|
|
100
88
|
"""
|
|
101
89
|
|
|
102
|
-
self.wialon_api = Wialon(
|
|
103
|
-
scheme=scheme, host=host, port=port, sid=sid, log_level=log_level
|
|
104
|
-
)
|
|
105
90
|
self._token = token or settings.WIALON_TOKEN
|
|
106
|
-
self.login_id = uid
|
|
107
91
|
self._username = None
|
|
108
92
|
self._gis_sid = None
|
|
109
93
|
self._hw_gp_ip = None
|
|
110
94
|
self._wsdk_version = None
|
|
111
95
|
self._uid = None
|
|
112
|
-
self.
|
|
113
|
-
|
|
114
|
-
def create_logger(self, log_level: int) -> logging.Logger:
|
|
115
|
-
logger = logging.getLogger(self.__class__.__name__)
|
|
116
|
-
handler = logging.StreamHandler()
|
|
117
|
-
formatter = logging.Formatter(
|
|
118
|
-
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
96
|
+
self.wialon_api = Wialon(
|
|
97
|
+
scheme=scheme, host=host, port=port, sid=sid, log_level=log_level
|
|
119
98
|
)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
logger.addHandler(handler)
|
|
124
|
-
return logger
|
|
99
|
+
self.logger = WialonLogger(
|
|
100
|
+
logging.getLogger(self.__class__.__name__), level=log_level
|
|
101
|
+
).get_logger()
|
|
125
102
|
|
|
126
103
|
def __enter__(self) -> "WialonSession":
|
|
127
104
|
assert self.token, "Wialon API token was not set"
|
|
@@ -285,39 +262,41 @@ class WialonSession:
|
|
|
285
262
|
:type token: :py:obj:`str`
|
|
286
263
|
:param flags: A login response flag integer.
|
|
287
264
|
:type flags: :py:obj:`int`
|
|
288
|
-
:raises
|
|
265
|
+
:raises WialonError: If the login fails.
|
|
266
|
+
:raises AssertionError: If the login token was not set.
|
|
289
267
|
:returns: The new session id.
|
|
290
268
|
:rtype: :py:obj:`str`
|
|
291
269
|
|
|
292
270
|
"""
|
|
293
271
|
try:
|
|
272
|
+
self.logger.info("Logging into Wialon API session...")
|
|
294
273
|
response = self.wialon_api.token_login(**{"token": token, "fl": flags})
|
|
295
274
|
self._set_login_response(response)
|
|
296
|
-
self.logger.
|
|
275
|
+
self.logger.debug(f"Logged into Wialon API session '{response.get('eid')}'")
|
|
297
276
|
return response.get("eid")
|
|
298
277
|
except (WialonError, AssertionError) as e:
|
|
299
278
|
self.logger.critical(f"Failed to login to Wialon API: '{e}'")
|
|
300
|
-
raise
|
|
279
|
+
raise
|
|
301
280
|
|
|
302
281
|
def logout(self) -> None:
|
|
303
282
|
"""
|
|
304
283
|
Logs out of the Wialon API session.
|
|
305
284
|
|
|
306
|
-
:raises WialonLogoutError: If the logout fails.
|
|
307
285
|
:returns: Nothing.
|
|
308
286
|
:rtype: :py:obj:`None`
|
|
309
287
|
|
|
310
288
|
"""
|
|
289
|
+
self.logger.info("Logging out of Wialon API session...")
|
|
311
290
|
response: dict = self.wialon_api.core_logout({})
|
|
312
|
-
|
|
313
|
-
f"Logged out of session '{self.id}' after {self.wialon_api.total_calls} Wialon API calls."
|
|
314
|
-
)
|
|
315
|
-
self.logger.debug(f"Failure rate: {self.wialon_api.failure_rate}%")
|
|
291
|
+
|
|
316
292
|
if response.get("error") != 0:
|
|
317
293
|
self.logger.warning(
|
|
318
294
|
f"Failed to logout of session: '{response.get('message')}'"
|
|
319
295
|
)
|
|
320
|
-
|
|
296
|
+
else:
|
|
297
|
+
self.logger.debug(
|
|
298
|
+
f"Logged out after {self.wialon_api.total_calls} Wialon API calls."
|
|
299
|
+
)
|
|
321
300
|
|
|
322
301
|
def _set_login_response(self, login_response: dict) -> None:
|
|
323
302
|
"""
|
|
@@ -367,7 +346,7 @@ class WialonSessionManager:
|
|
|
367
346
|
|
|
368
347
|
def main() -> None:
|
|
369
348
|
# Usage example
|
|
370
|
-
session = WialonSession() # Instantiate session
|
|
349
|
+
session = WialonSession(log_level=logging.DEBUG) # Instantiate session
|
|
371
350
|
session.login(settings.WIALON_TOKEN) # Login to session
|
|
372
351
|
session.wialon_api.avl_evts() # Call Wialon API
|
|
373
352
|
session.logout() # Logout of session
|
terminusgps/wialon/errors.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from wialon.api import WialonError
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class WialonBaseError(Exception):
|
|
5
|
-
def __init__(
|
|
6
|
-
self, message: str, wialon_err: WialonError | AssertionError | None = None
|
|
7
|
-
) -> None:
|
|
8
|
-
self.wialon_err = wialon_err
|
|
9
|
-
return super().__init__(message)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class WialonLoginError(WialonBaseError):
|
|
13
|
-
def __init__(
|
|
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 WialonLogoutError(WialonBaseError):
|
|
23
|
-
def __init__(
|
|
24
|
-
self, session_id: str, wialon_err: WialonError | AssertionError | None = None
|
|
25
|
-
) -> None:
|
|
26
|
-
message = f"Failed to logout of the Wialon API session: '{session_id}'\n"
|
|
27
|
-
if wialon_err:
|
|
28
|
-
message += str(wialon_err)
|
|
29
|
-
return super().__init__(message, wialon_err)
|
|
File without changes
|
{python_terminusgps-19.3.0.dist-info → python_terminusgps-20.1.0.dist-info}/licenses/COPYING
RENAMED
|
File without changes
|