python-terminusgps 1.5.6__py3-none-any.whl → 1.5.8__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-1.5.6.dist-info → python_terminusgps-1.5.8.dist-info}/METADATA +2 -2
- {python_terminusgps-1.5.6.dist-info → python_terminusgps-1.5.8.dist-info}/RECORD +15 -8
- terminusgps/openstreetmap/__init__.py +0 -0
- terminusgps/openstreetmap/polyline.py +7 -0
- terminusgps/openstreetmap/renderer.py +3 -0
- terminusgps/openstreetmap/session.py +54 -0
- terminusgps/wialon/errors.py +26 -8
- terminusgps/wialon/items/retranslator.py +95 -0
- terminusgps/wialon/maps/__init__.py +0 -0
- terminusgps/wialon/maps/layers.py +49 -0
- terminusgps/wialon/maps/renderer.py +110 -0
- terminusgps/wialon/session.py +46 -26
- terminusgps/wialon/utils.py +16 -4
- {python_terminusgps-1.5.6.dist-info → python_terminusgps-1.5.8.dist-info}/WHEEL +0 -0
- {python_terminusgps-1.5.6.dist-info → python_terminusgps-1.5.8.dist-info}/licenses/COPYING +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.8
|
|
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
|
|
@@ -4,21 +4,28 @@ terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
4
4
|
terminusgps/authorizenet/auth.py,sha256=zITSQMH8F-3vw-lDQRbuR2s9AVlGqbOyyFo0zqU00qU,870
|
|
5
5
|
terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
terminusgps/aws/secrets.py,sha256=kgRA77rs0mD4berWRLkPtJLOe4Grf--o5f8NzwQqXCk,360
|
|
7
|
+
terminusgps/openstreetmap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
terminusgps/openstreetmap/polyline.py,sha256=GHle6UWiHt-HQJ9CXxKG9Z1lr7yXCq_09dHc8IAYP6Y,104
|
|
9
|
+
terminusgps/openstreetmap/renderer.py,sha256=vYvWfdBJAo4vUJlzHzjAaKwISz492-ADKgcZ4Gbabbs,76
|
|
10
|
+
terminusgps/openstreetmap/session.py,sha256=GqDzrA_DkNN0UYcZgRFE4EQ78S6PEbdTkBSB0hyJt3A,1697
|
|
7
11
|
terminusgps/wialon/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
12
|
terminusgps/wialon/constants.py,sha256=dsQaNt3TIjIZbr_m94KmBGFdrqe6HER2r6lol3X8QpU,2802
|
|
9
|
-
terminusgps/wialon/errors.py,sha256=
|
|
13
|
+
terminusgps/wialon/errors.py,sha256=SV9pVwU6FZ_zGlGP6zJN6aLE2auF4TfHFISQLiPMKrI,1758
|
|
10
14
|
terminusgps/wialon/flags.py,sha256=-OoH-eZM54yjRqxsAXL8VImdQu_7C0OAxCrFqaCEuko,13510
|
|
11
|
-
terminusgps/wialon/session.py,sha256=
|
|
12
|
-
terminusgps/wialon/utils.py,sha256=
|
|
15
|
+
terminusgps/wialon/session.py,sha256=x5aXxqLcBe4e0Zj3enUvWd1_Ufmd_MxXInC_d_GMn3E,9446
|
|
16
|
+
terminusgps/wialon/utils.py,sha256=PMtEaRB9RjdDgWWzHPRnw3Gnrv-DgjywutTCIw1S7_c,2127
|
|
13
17
|
terminusgps/wialon/items/__init__.py,sha256=3BVthghekMvhMQSzQgBMlD_phxmKSmp3Zvmo-z0O8Bs,211
|
|
14
18
|
terminusgps/wialon/items/base.py,sha256=MN4FG6U1nWkYAjNfXQJRVrWJoiW4Y64tyqxUO0mhv_w,6593
|
|
15
19
|
terminusgps/wialon/items/resource.py,sha256=ADjGsQaCqD6Y3_AaD8vLgYzGaMK69MpxCZojnylS4GE,815
|
|
16
|
-
terminusgps/wialon/items/retranslator.py,sha256=
|
|
20
|
+
terminusgps/wialon/items/retranslator.py,sha256=zsQXqOhH1zFe5_e8DROPu60z3v6xPWOEPyMCi2IqJAo,3861
|
|
17
21
|
terminusgps/wialon/items/route.py,sha256=qOHPN_rejwiGqvwWzlwmUIAIyc3lKavCalf8ki66rx0,760
|
|
18
22
|
terminusgps/wialon/items/unit.py,sha256=tLAWPfHUUS6_Feh1aYBMFPgyuGlSiAnfumJJmGt3bKw,4662
|
|
19
23
|
terminusgps/wialon/items/unit_group.py,sha256=1yc7ldPIgGbtiTj0djRDWmt6Q9K_VT9sxOaioasbbLY,5212
|
|
20
24
|
terminusgps/wialon/items/user.py,sha256=bkcMw_YiocaMuhP_pBfB7apjAZwnsOzGScnGkn8Ybbw,6107
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
python_terminusgps-1.5.
|
|
25
|
+
terminusgps/wialon/maps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
terminusgps/wialon/maps/layers.py,sha256=K_uxQjRG5Y7WRCpSL5RbYKJFyE87zgYuP9MdoBqgHEU,1763
|
|
27
|
+
terminusgps/wialon/maps/renderer.py,sha256=AusrPT7KXG2yn6E3Ls4DOAJEPANdL7548ZnjHFSmP9Y,5334
|
|
28
|
+
python_terminusgps-1.5.8.dist-info/METADATA,sha256=UDfapsi2DCVaBF5ToB-IXuuE4IG6VEvf74Y11Qkln-k,882
|
|
29
|
+
python_terminusgps-1.5.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
30
|
+
python_terminusgps-1.5.8.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
31
|
+
python_terminusgps-1.5.8.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import requests
|
|
3
|
+
from urllib.parse import urlencode
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OpenStreetMapSession:
|
|
7
|
+
def __init__(self, client_id: str, redirect_uri: str, scopes: list[str]) -> None:
|
|
8
|
+
self.client_id = client_id
|
|
9
|
+
self.redirect_uri = redirect_uri
|
|
10
|
+
self.scopes = scopes
|
|
11
|
+
self.base_token_url = "https://master.apis.dev.openstreetmap.org/oauth2/token?"
|
|
12
|
+
self.base_auth_url = (
|
|
13
|
+
"https://master.apis.dev.openstreetmap.org/oauth2/authorize?"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
def generate_auth_url(self) -> str:
|
|
17
|
+
params = urlencode(
|
|
18
|
+
{
|
|
19
|
+
"response_type": "code",
|
|
20
|
+
"client_id": self.client_id,
|
|
21
|
+
"redirect_uri": self.redirect_uri,
|
|
22
|
+
"scope": "%20".join(self.scopes),
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
return self.base_auth_url + params
|
|
26
|
+
|
|
27
|
+
def get_token(self, auth_code: str, client_secret: str) -> str | None:
|
|
28
|
+
params = urlencode(
|
|
29
|
+
{
|
|
30
|
+
"grant_type": "authorization_code",
|
|
31
|
+
"code": auth_code,
|
|
32
|
+
"redirect_uri": self.redirect_uri,
|
|
33
|
+
"client_id": self.client_id,
|
|
34
|
+
"client_secret": client_secret,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
response = requests.post(self.base_token_url + params).json()
|
|
38
|
+
self.scopes = [response.get("scope").split(" ")]
|
|
39
|
+
return response.get("access_token")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def main() -> None:
|
|
43
|
+
scopes = os.getenv("OSM_SCOPES").split(" ")
|
|
44
|
+
session = OpenStreetMapSession(
|
|
45
|
+
client_id=os.getenv("OSM_CLIENT_ID"),
|
|
46
|
+
redirect_uri=os.getenv("OSM_REDIRECT_URI"),
|
|
47
|
+
scopes=scopes,
|
|
48
|
+
)
|
|
49
|
+
print(f"{session.generate_auth_url() = }")
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
main()
|
terminusgps/wialon/errors.py
CHANGED
|
@@ -2,34 +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
|
|
13
15
|
) -> None:
|
|
14
16
|
message = f"Failed to login to the Wialon API using token: '{token}'\n"
|
|
15
17
|
if wialon_err:
|
|
16
18
|
message += str(wialon_err)
|
|
17
|
-
super().__init__(message, wialon_err)
|
|
19
|
+
return super().__init__(message, wialon_err)
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class WialonSessionDuplicationError(WialonBaseError):
|
|
21
23
|
def __init__(
|
|
22
|
-
self,
|
|
24
|
+
self,
|
|
25
|
+
session_id: str | None,
|
|
26
|
+
wialon_err: WialonError | AssertionError | None = None,
|
|
23
27
|
) -> None:
|
|
24
28
|
message = f"Failed to duplicate the Wialon session: '#{session_id}'\n"
|
|
25
29
|
if wialon_err:
|
|
26
30
|
message += str(wialon_err)
|
|
27
|
-
super().__init__(message, wialon_err)
|
|
31
|
+
return super().__init__(message, wialon_err)
|
|
28
32
|
|
|
29
33
|
|
|
30
34
|
class WialonLogoutError(WialonBaseError):
|
|
31
|
-
def __init__(
|
|
35
|
+
def __init__(
|
|
36
|
+
self, session_id: str, wialon_err: WialonError | AssertionError | None = None
|
|
37
|
+
) -> None:
|
|
32
38
|
message = f"Failed to logout of the Wialon API session: '{session_id}'\n"
|
|
33
39
|
if wialon_err:
|
|
34
40
|
message += str(wialon_err)
|
|
35
|
-
super().__init__(message, 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"
|
|
51
|
+
if wialon_err:
|
|
52
|
+
message += str(wialon_err)
|
|
53
|
+
return super().__init__(message, wialon_err)
|
|
@@ -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
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from terminusgps.wialon.maps.renderer import WialonMapRenderer
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class WialonMapLayerBase:
|
|
5
|
+
def __init__(self, renderer: WialonMapRenderer, name: str) -> None:
|
|
6
|
+
self.renderer = renderer
|
|
7
|
+
self.name = name
|
|
8
|
+
self.bounds = dict()
|
|
9
|
+
|
|
10
|
+
def __str__(self) -> str:
|
|
11
|
+
return self.name
|
|
12
|
+
|
|
13
|
+
def delete_layer(self) -> None:
|
|
14
|
+
self.renderer.session.wialon_api.render_remove_layer(**{"layerName": self.name})
|
|
15
|
+
|
|
16
|
+
def create_layer(self, data: list[dict], flags: int = 0x1) -> None:
|
|
17
|
+
raise NotImplementedError("Subclasses must implement this method")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WialonMapLayerGeofence(WialonMapLayerBase):
|
|
21
|
+
def create_layer(self, data: list[dict], flags: int = 0x1) -> None:
|
|
22
|
+
response = self.renderer.session.wialon_api.render_create_zones_layer(
|
|
23
|
+
**{"layerName": self.name, "flags": flags, "zones": data}
|
|
24
|
+
)
|
|
25
|
+
self.bounds = {
|
|
26
|
+
"min_lat": response.get("bounds")[0],
|
|
27
|
+
"min_lon": response.get("bounds")[1],
|
|
28
|
+
"max_lat": response.get("bounds")[2],
|
|
29
|
+
"max_lon": response.get("bounds")[3],
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class WialonMapLayerPoi(WialonMapLayerBase):
|
|
34
|
+
def create_layer(self, data: list[dict], flags: int = 0x1) -> None:
|
|
35
|
+
response = self.renderer.session.wialon_api.render_create_poi_layer(
|
|
36
|
+
**{"layerName": self.name, "flags": flags, "pois": data}
|
|
37
|
+
)
|
|
38
|
+
self.bounds = {
|
|
39
|
+
"min_lat": response.get("bounds")[0],
|
|
40
|
+
"min_lon": response.get("bounds")[1],
|
|
41
|
+
"max_lat": response.get("bounds")[2],
|
|
42
|
+
"max_lon": response.get("bounds")[3],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class WialonMapLayerTrack(WialonMapLayerBase):
|
|
47
|
+
def __init__(self, **kwargs) -> None:
|
|
48
|
+
self.units = []
|
|
49
|
+
return super().__init__(**kwargs)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from django.conf import ImproperlyConfigured, settings
|
|
2
|
+
|
|
3
|
+
from terminusgps.wialon.session import WialonSession
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class WialonMapRenderer:
|
|
7
|
+
def __init__(
|
|
8
|
+
self, sid: str | None = None, gis_host: str = "hst-api.wialon.com"
|
|
9
|
+
) -> None:
|
|
10
|
+
if not hasattr(settings, "WIALON_TOKEN"):
|
|
11
|
+
raise ImproperlyConfigured("'WIALON_TOKEN' setting is required.")
|
|
12
|
+
|
|
13
|
+
self.host = gis_host
|
|
14
|
+
self.layers = []
|
|
15
|
+
self.session = WialonSession(sid=sid)
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def total_layers(self) -> int:
|
|
19
|
+
return len(self.layers)
|
|
20
|
+
|
|
21
|
+
def get_events(self):
|
|
22
|
+
return self.session.wialon_api.avl_evts()
|
|
23
|
+
|
|
24
|
+
def toggle_layer(self, name: str, enabled: bool = True) -> None:
|
|
25
|
+
self.session.wialon_api.render_enable_layer(
|
|
26
|
+
**{"layerName": name, "enable": enabled}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def delete_all_layers(self) -> None:
|
|
30
|
+
self.session.wialon_api.render_remove_all_layers({})
|
|
31
|
+
self.layers = []
|
|
32
|
+
|
|
33
|
+
def get_tiles_url(self, x: int, y: int, z: int) -> str:
|
|
34
|
+
MIN_ZOOM, MAX_ZOOM = 2, 17
|
|
35
|
+
z = min(max(z, MIN_ZOOM), MAX_ZOOM)
|
|
36
|
+
return f"http://{self.host}/avl_render/{x}_{y}_{z}/{self.session.id}.png"
|
|
37
|
+
|
|
38
|
+
def update_locale(
|
|
39
|
+
self,
|
|
40
|
+
tz: int,
|
|
41
|
+
lang: str = "en",
|
|
42
|
+
flags: int = 1,
|
|
43
|
+
date_fmt: str = "%m-%E-%Y %H:%M:%S",
|
|
44
|
+
density: int = 256 * 256,
|
|
45
|
+
) -> None:
|
|
46
|
+
"""
|
|
47
|
+
Updates the renderer locale.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Date Format:
|
|
51
|
+
|
|
52
|
+
+-----------+------------------------------------------------------------------------+
|
|
53
|
+
| Parameter | Description |
|
|
54
|
+
+===========+========================================================================+
|
|
55
|
+
| ``%H`` | The hour of the day with leading zero if required ("00" to "23") |
|
|
56
|
+
+-----------+------------------------------------------------------------------------+
|
|
57
|
+
| ``%B`` | The full month name ("January" to "December") |
|
|
58
|
+
+-----------+------------------------------------------------------------------------+
|
|
59
|
+
| ``%b`` | Abbreviated month name ("Jan" to "Dec") |
|
|
60
|
+
+-----------+------------------------------------------------------------------------+
|
|
61
|
+
| ``%m`` | The month of the year with leading zero if required ("01" to "12") |
|
|
62
|
+
+-----------+------------------------------------------------------------------------+
|
|
63
|
+
| ``%l`` | The month of the year between 1-12 ("1" to "12") |
|
|
64
|
+
+-----------+------------------------------------------------------------------------+
|
|
65
|
+
| ``%P`` | Format Persian calendar ("01 Farvardin 1392 00:00:00") |
|
|
66
|
+
+-----------+------------------------------------------------------------------------+
|
|
67
|
+
| ``%A`` | The full day name ("Monday" to "Sunday") |
|
|
68
|
+
+-----------+------------------------------------------------------------------------+
|
|
69
|
+
| ``%a`` | Abbreviated day name ("Mon" to "Sun") |
|
|
70
|
+
+-----------+------------------------------------------------------------------------+
|
|
71
|
+
| ``%E`` | The day of the month with a leading zero if required ("01" to "31") |
|
|
72
|
+
+-----------+------------------------------------------------------------------------+
|
|
73
|
+
| ``%e`` | The day of the month between 1 and 31 ("1" to "31") |
|
|
74
|
+
+-----------+------------------------------------------------------------------------+
|
|
75
|
+
| ``%I`` | The hour of the day with leading zero if required ("01" to "12") |
|
|
76
|
+
+-----------+------------------------------------------------------------------------+
|
|
77
|
+
| ``%M`` | The minute of the hour with leading zero if required ("00" to "59") |
|
|
78
|
+
+-----------+------------------------------------------------------------------------+
|
|
79
|
+
| ``%S`` | The seconds of the minute with leading zero if required ("00" to "59") |
|
|
80
|
+
+-----------+------------------------------------------------------------------------+
|
|
81
|
+
| ``%p`` | Displays the A.M./P.M. designator ("AM" or "PM") |
|
|
82
|
+
+-----------+------------------------------------------------------------------------+
|
|
83
|
+
| ``%Y`` | The full four digit year ("1999" or "2000") |
|
|
84
|
+
+-----------+------------------------------------------------------------------------+
|
|
85
|
+
| ``%y`` | The year as a two digit number ("99" or "00") |
|
|
86
|
+
+-----------+------------------------------------------------------------------------+
|
|
87
|
+
|
|
88
|
+
"""
|
|
89
|
+
self.session.wialon_api.render_set_locale(
|
|
90
|
+
**{
|
|
91
|
+
"tzOffset": tz,
|
|
92
|
+
"language": lang,
|
|
93
|
+
"flags": flags,
|
|
94
|
+
"formatDate": date_fmt,
|
|
95
|
+
"density": density,
|
|
96
|
+
}
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def main() -> None:
|
|
101
|
+
from terminusgps.wialon.maps.layers import WialonMapLayerPoi
|
|
102
|
+
|
|
103
|
+
with WialonSession() as session:
|
|
104
|
+
renderer = WialonMapRenderer(session.id)
|
|
105
|
+
layer = WialonMapLayerPoi(renderer, "terminusgps_office")
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
if __name__ == "__main__":
|
|
110
|
+
main()
|
terminusgps/wialon/session.py
CHANGED
|
@@ -2,7 +2,12 @@ from wialon.api import Wialon, WialonError
|
|
|
2
2
|
from django.conf import settings
|
|
3
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:
|
|
@@ -32,7 +37,6 @@ class WialonSession:
|
|
|
32
37
|
raise ImproperlyConfigured("'WIALON_ADMIN_ID' setting is required.")
|
|
33
38
|
|
|
34
39
|
self.wialon_api = Wialon(scheme=scheme, host=host, port=port, sid=sid)
|
|
35
|
-
self.active = bool(sid)
|
|
36
40
|
self.token = token
|
|
37
41
|
self._username = None
|
|
38
42
|
self._gis_sid = None
|
|
@@ -48,6 +52,24 @@ class WialonSession:
|
|
|
48
52
|
def __exit__(self, *args, **kwargs) -> None:
|
|
49
53
|
self.logout()
|
|
50
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
|
+
|
|
51
73
|
@property
|
|
52
74
|
def gis_geocode(self) -> str | None:
|
|
53
75
|
"""
|
|
@@ -198,32 +220,31 @@ class WialonSession:
|
|
|
198
220
|
def token(self, value: str | None = None) -> None:
|
|
199
221
|
self._token = value if value else settings.WIALON_TOKEN
|
|
200
222
|
|
|
201
|
-
def duplicate(
|
|
202
|
-
self, user_id: str | None = None, continue_session: bool = False
|
|
203
|
-
) -> None:
|
|
223
|
+
def duplicate(self, username: str | None = None, continued: bool = False) -> str:
|
|
204
224
|
"""
|
|
205
225
|
Duplicates the active Wialon API session.
|
|
206
226
|
|
|
207
|
-
:param
|
|
208
|
-
:type
|
|
227
|
+
:param username: A Wialon user to operate as in the session.
|
|
228
|
+
:type username: :py:obj:`str` | :py:obj:`None`
|
|
209
229
|
:param continue_session: Whether or not the original session id should be valid after duplication.
|
|
210
230
|
:type continue_session: :py:obj:`bool`
|
|
211
231
|
:raises WialonSessionDuplicationError: If the Wialon session was not duplicated.
|
|
212
|
-
:
|
|
213
|
-
:
|
|
232
|
+
:raises AssertionError: If the session was already active.
|
|
233
|
+
:returns: The new session id.
|
|
234
|
+
:rtype: :py:obj:`str`
|
|
214
235
|
|
|
215
236
|
"""
|
|
216
237
|
try:
|
|
217
|
-
|
|
218
|
-
|
|
238
|
+
assert self.active, "Cannot duplicate an inactive session."
|
|
239
|
+
response = self.wialon_api.core_duplicate(
|
|
240
|
+
**{"operateAs": username, "continueCurrentSession": continued}
|
|
219
241
|
)
|
|
220
|
-
|
|
242
|
+
self._set_login_response(response)
|
|
243
|
+
return response.get("eid")
|
|
244
|
+
except (WialonError, AssertionError) as e:
|
|
221
245
|
raise WialonSessionDuplicationError(self.id, e)
|
|
222
|
-
else:
|
|
223
|
-
self._set_login_response(login_response)
|
|
224
|
-
self.active = True
|
|
225
246
|
|
|
226
|
-
def login(self, token: str, flags: int = sum([0x1, 0x2, 0x20])) ->
|
|
247
|
+
def login(self, token: str, flags: int = sum([0x1, 0x2, 0x20])) -> str:
|
|
227
248
|
"""
|
|
228
249
|
Logs into the Wialon API and starts a new session.
|
|
229
250
|
|
|
@@ -235,18 +256,17 @@ class WialonSession:
|
|
|
235
256
|
:type flags: :py:obj:`int`
|
|
236
257
|
:raises WialonLoginError: If the login fails.
|
|
237
258
|
:raises AssertionError: If the session was already active.
|
|
238
|
-
:returns:
|
|
239
|
-
:rtype: :py:obj:`
|
|
259
|
+
:returns: The new session id.
|
|
260
|
+
:rtype: :py:obj:`str`
|
|
240
261
|
|
|
241
262
|
"""
|
|
242
|
-
assert not self.active, "Cannot login to an active session."
|
|
243
263
|
try:
|
|
264
|
+
assert not self.active, "Cannot login to an active session."
|
|
244
265
|
response = self.wialon_api.token_login(**{"token": token, "fl": flags})
|
|
245
|
-
except WialonError as e:
|
|
246
|
-
raise WialonLoginError(token, e)
|
|
247
|
-
else:
|
|
248
266
|
self._set_login_response(response)
|
|
249
|
-
|
|
267
|
+
return response.get("eid")
|
|
268
|
+
except (WialonError, AssertionError) as e:
|
|
269
|
+
raise WialonLoginError(token, e)
|
|
250
270
|
|
|
251
271
|
def logout(self) -> None:
|
|
252
272
|
"""
|
|
@@ -265,7 +285,7 @@ class WialonSession:
|
|
|
265
285
|
"""
|
|
266
286
|
Sets the Wialon API session's attributes based on a login response.
|
|
267
287
|
|
|
268
|
-
:param login_response: A
|
|
288
|
+
:param login_response: A response returned from :py:meth:`login` or :py:meth:`duplicate`.
|
|
269
289
|
:type login_response: :py:obj:`dict`
|
|
270
290
|
:returns: Nothing.
|
|
271
291
|
:rtype: :py:obj:`None`
|
|
@@ -289,8 +309,8 @@ class WialonSession:
|
|
|
289
309
|
|
|
290
310
|
def main() -> None:
|
|
291
311
|
session = WialonSession()
|
|
292
|
-
session.login(settings.WIALON_TOKEN)
|
|
293
|
-
session.duplicate(
|
|
312
|
+
session.login(token=settings.WIALON_TOKEN)
|
|
313
|
+
session.duplicate(username="chrissyron@gmail.com", continued=False)
|
|
294
314
|
session.logout()
|
|
295
315
|
return
|
|
296
316
|
|
terminusgps/wialon/utils.py
CHANGED
|
@@ -38,10 +38,10 @@ def get_id_from_iccid(iccid: str, session: WialonSession) -> str | None:
|
|
|
38
38
|
**{
|
|
39
39
|
"spec": {
|
|
40
40
|
"itemsType": "avl_unit",
|
|
41
|
-
"propName": "
|
|
42
|
-
"propValueMask":
|
|
43
|
-
"sortType": "
|
|
44
|
-
"propType": "
|
|
41
|
+
"propName": "rel_admin_field_value",
|
|
42
|
+
"propValueMask": str(iccid),
|
|
43
|
+
"sortType": "admin_fields",
|
|
44
|
+
"propType": "adminfield",
|
|
45
45
|
"or_logic": 0,
|
|
46
46
|
},
|
|
47
47
|
"force": 0,
|
|
@@ -50,6 +50,18 @@ def get_id_from_iccid(iccid: str, session: WialonSession) -> str | None:
|
|
|
50
50
|
"to": 0,
|
|
51
51
|
}
|
|
52
52
|
)
|
|
53
|
+
print(f"{response = }")
|
|
53
54
|
if response.get("totalItemsCount", 0) != 1:
|
|
54
55
|
return None
|
|
55
56
|
return response["items"][0].get("id")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main() -> None:
|
|
60
|
+
with WialonSession() as session:
|
|
61
|
+
wialon_id = get_id_from_iccid("89015809000307608963", session)
|
|
62
|
+
print(f"{wialon_id = }")
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
main()
|
|
File without changes
|
|
File without changes
|