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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-terminusgps
3
- Version: 1.4.6
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.4
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,,
@@ -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
@@ -0,0 +1,6 @@
1
+ from os import getenv
2
+
3
+ DEBUG = False
4
+ SECRET_KEY = "xem*6no%8d9%^qzt2f3x3ar-uq4_+7h9myc$t0!+4%bj5us6f)"
5
+ WIALON_ADMIN_ID = getenv("WIALON_ADMIN_ID")
6
+ WIALON_TOKEN = getenv("WIALON_TOKEN")
@@ -1,5 +0,0 @@
1
- from os import environ
2
-
3
- environ.setdefault("WIALON_HOST", "hst-api.wialon.com")
4
- environ.setdefault("WIALON_SCHEME", "https")
5
- environ.setdefault("WIALON_PORT", "443")
@@ -2,24 +2,52 @@ from wialon.api import WialonError
2
2
 
3
3
 
4
4
  class WialonBaseError(Exception):
5
- def __init__(self, message: str, wialon_err: WialonError | None = None) -> None:
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 login to the Wialon API using token: '{token}'"
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__(self, session_id: str, wialon_err: WialonError | None = None) -> None:
22
- message = f"Failed to logout of the Wialon API session: '{session_id}'"
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)
@@ -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 f"{self.__class__}:{self.id}"
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, field: tuple[str, str]) -> None:
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": field[0], "value": field[1]}
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:
@@ -16,7 +16,7 @@ class WialonResource(WialonBase):
16
16
  "creatorId": kwargs["creator_id"],
17
17
  "name": kwargs["name"],
18
18
  "dataFlags": kwargs["flags"],
19
- "skipCreatorCheck": True,
19
+ "skipCreatorCheck": int(True),
20
20
  }
21
21
  )
22
22
  return response.get("item", {}).get("id")
@@ -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
+ )
@@ -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, repopulate
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
- if self.is_active:
62
- return
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
- if not self.is_active:
71
- return
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
- assert self.is_member(item), f"Cannot remove {item.name}, it's not in the group"
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": {
@@ -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
- """Assigns an email address to the Wialon user."""
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
- """Grants item access to the Wialon user according to the access mask integer."""
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,
@@ -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 WialonLogoutError, WialonLoginError
5
+ from .errors import (
6
+ WialonLogoutError,
7
+ WialonLoginError,
8
+ WialonSessionDuplicationError,
9
+ WialonSessionInvalidError,
10
+ )
6
11
 
7
12
 
8
13
  class WialonSession:
9
- def __init__(self, token: str | None = None, sid: str | None = None) -> None:
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.wialon_api = Wialon(
12
- scheme="https", host="hst-api.wialon.com", port=443, sid=sid
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 | None:
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 os.getenv("WIALON_TOKEN")
221
+ self._token = value if value else settings.WIALON_TOKEN
26
222
 
27
- def __enter__(self) -> "WialonSession":
28
- self.login(self.token)
29
- return self
223
+ def duplicate(self, username: str | None = None, continued: bool = False) -> str:
224
+ """
225
+ Duplicates the active Wialon API session.
30
226
 
31
- def __exit__(self, exc_type, exc_value, exc_tb) -> None:
32
- self.logout()
33
- return
34
-
35
- def _deconstruct_login_response(self, login_response: dict) -> None:
36
- self.wialon_api.sid = login_response.get("eid", "")
37
- self.username = login_response.get("user", {}).get("nm")
38
- self.uid = login_response.get("user", {}).get("id")
39
- self.base_url = login_response.get("base_url", "")
40
- self.gis_sid = login_response.get("gis_sid", "")
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
- login_response = self.wialon_api.token_login(
53
- **{"token": token, "fl": sum([0x1, 0x2, 0x20])}
238
+ assert self.active, "Cannot duplicate an inactive session."
239
+ response = self.wialon_api.core_duplicate(
240
+ **{"operateAs": username, "continueCurrentSession": continued}
54
241
  )
55
- except WialonError as e:
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
- """Logs out of the Wialon API and raises an error if the session was not destroyed."""
62
- sid: str = str(self.id)
63
- logout_response = self.wialon_api.core_logout({})
64
- if logout_response.get("error") != 0:
65
- raise WialonLogoutError(sid)
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()
@@ -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"])