python-terminusgps 1.15.1__tar.gz → 1.16.0__tar.gz
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.15.1 → python_terminusgps-1.16.0}/PKG-INFO +1 -1
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/pyproject.toml +1 -1
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/base.py +23 -18
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/resource.py +31 -4
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/unit_group.py +10 -43
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/session.py +8 -9
- python_terminusgps-1.16.0/terminusgps/wialon/utils.py +185 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/uv.lock +1 -1
- python_terminusgps-1.15.1/terminusgps/wialon/utils.py +0 -113
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/.gitignore +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/COPYING +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/README.md +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/auth.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/addresses.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/base.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/customers.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/payments.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/subscriptions.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/aws/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/aws/secrets.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/aws/ses.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/settings.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/twilio/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/twilio/caller.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/constants.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/errors.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/flags.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/__init__.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/notification.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/retranslator.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/route.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/unit.py +0 -0
- {python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/user.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-terminusgps
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.16.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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-terminusgps"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.16.0"
|
|
4
4
|
description = "Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [ {name = "Blake Nall", email = "blake@terminusgps.com" } ]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from abc import abstractmethod
|
|
2
|
+
from typing import Type
|
|
2
3
|
|
|
3
4
|
from terminusgps.wialon import flags
|
|
4
5
|
from terminusgps.wialon.session import WialonSession
|
|
@@ -24,6 +25,7 @@ class WialonBase:
|
|
|
24
25
|
return str(self.id)
|
|
25
26
|
|
|
26
27
|
def populate(self) -> None:
|
|
28
|
+
"""Retrieves and saves the latest data for the item from Wialon."""
|
|
27
29
|
response = self.session.wialon_api.core_search_item(
|
|
28
30
|
**{"id": str(self.id), "flags": 0x1}
|
|
29
31
|
).get("item", {})
|
|
@@ -53,7 +55,7 @@ class WialonBase:
|
|
|
53
55
|
|
|
54
56
|
return int(self._id) if self._id else None
|
|
55
57
|
|
|
56
|
-
def has_access(self, other: "WialonBase") -> bool:
|
|
58
|
+
def has_access(self, other: Type["WialonBase"]) -> bool:
|
|
57
59
|
"""
|
|
58
60
|
Checks if this Wialon object has access to ``other``.
|
|
59
61
|
|
|
@@ -74,7 +76,7 @@ class WialonBase:
|
|
|
74
76
|
"""
|
|
75
77
|
Renames the Wialon object to the new name.
|
|
76
78
|
|
|
77
|
-
:param new_name: A new name
|
|
79
|
+
:param new_name: A new name.
|
|
78
80
|
:type new_name: :py:obj:`str`
|
|
79
81
|
:returns: Nothing.
|
|
80
82
|
:rtype: :py:obj:`None`
|
|
@@ -215,24 +217,27 @@ class WialonBase:
|
|
|
215
217
|
|
|
216
218
|
self.session.wialon_api.item_delete_item(**{"itemId": self.id})
|
|
217
219
|
|
|
218
|
-
def _get_cfields(self) -> dict:
|
|
219
|
-
response = self.session.wialon_api.core_search_item(
|
|
220
|
-
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_CUSTOM_FIELDS}
|
|
221
|
-
)
|
|
222
|
-
return response["item"]["flds"]
|
|
223
|
-
|
|
224
|
-
def _get_afields(self) -> dict:
|
|
225
|
-
response = self.session.wialon_api.core_search_item(
|
|
226
|
-
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_ADMIN_FIELDS}
|
|
227
|
-
)
|
|
228
|
-
return response["item"]["aflds"]
|
|
229
|
-
|
|
230
220
|
@property
|
|
231
221
|
def cfields(self) -> dict:
|
|
232
|
-
fields
|
|
233
|
-
|
|
222
|
+
"""Custom fields associated with the Wialon object."""
|
|
223
|
+
fields = (
|
|
224
|
+
self.session.wialon_api.core_search_item(
|
|
225
|
+
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_CUSTOM_FIELDS}
|
|
226
|
+
)
|
|
227
|
+
.get("item", {})
|
|
228
|
+
.get("cfields")
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
return {field["n"]: field["v"] for _, field in fields.items()} if fields else {}
|
|
234
232
|
|
|
235
233
|
@property
|
|
236
234
|
def afields(self) -> dict:
|
|
237
|
-
fields
|
|
238
|
-
|
|
235
|
+
"""Admin fields associated with the Wialon object."""
|
|
236
|
+
fields = (
|
|
237
|
+
self.session.wialon_api.core_search_item(
|
|
238
|
+
**{"id": self.id, "flags": flags.DATAFLAG_UNIT_ADMIN_FIELDS}
|
|
239
|
+
)
|
|
240
|
+
.get("item", {})
|
|
241
|
+
.get("afields")
|
|
242
|
+
)
|
|
243
|
+
return {field["n"]: field["v"] for _, field in fields.items()} if fields else {}
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/resource.py
RENAMED
|
@@ -21,10 +21,34 @@ class WialonResource(WialonBase):
|
|
|
21
21
|
return response.get("item", {}).get("id")
|
|
22
22
|
|
|
23
23
|
def delete(self) -> None:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
"""
|
|
25
|
+
Deletes all micro-objects assigned to the resource.
|
|
26
|
+
|
|
27
|
+
If the resource is an account, instead deletes all macro-objects and micro-objects assigned to the account.
|
|
28
|
+
|
|
29
|
+
:returns: Nothing.
|
|
30
|
+
:rtype: :py:obj:`None`
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
self.delete_account() if self.is_account else super().delete()
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def is_dealer(self) -> bool:
|
|
37
|
+
"""
|
|
38
|
+
Whether or not the resource/account has dealer rights.
|
|
39
|
+
|
|
40
|
+
If the resource is **not** an account, this always returns :py:obj:`False`.
|
|
41
|
+
|
|
42
|
+
:type: :py:obj:`bool`
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
if not self.is_account:
|
|
46
|
+
return False # Resources cannot have dealer rights
|
|
47
|
+
return bool(
|
|
48
|
+
self.session.wialon_api.get_account_data(
|
|
49
|
+
**{"itemId": self.id, "type": 1}
|
|
50
|
+
).get("dealerRights")
|
|
51
|
+
)
|
|
28
52
|
|
|
29
53
|
@property
|
|
30
54
|
def is_account(self) -> bool:
|
|
@@ -60,6 +84,8 @@ class WialonResource(WialonBase):
|
|
|
60
84
|
"""
|
|
61
85
|
Sets dealer rights on the account.
|
|
62
86
|
|
|
87
|
+
You **probably don't** need to use this method.
|
|
88
|
+
|
|
63
89
|
:param enabled: :py:obj:`True` to enable dealer rights, :py:obj:`False` to disable dealer rights. Default is :py:obj:`False`.
|
|
64
90
|
:type enabled: :py:obj:`bool`
|
|
65
91
|
:raises AssertionError: If the resource is not an account.
|
|
@@ -123,6 +149,7 @@ class WialonResource(WialonBase):
|
|
|
123
149
|
self.session.wialon_api.account_create_account(
|
|
124
150
|
**{"itemId": self.id, "plan": billing_plan}
|
|
125
151
|
)
|
|
152
|
+
self.set_settings_flags()
|
|
126
153
|
|
|
127
154
|
def delete_account(self) -> None:
|
|
128
155
|
"""
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/unit_group.py
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from typing import Type
|
|
2
|
+
from terminusgps.wialon import flags
|
|
2
3
|
from terminusgps.wialon.items.base import WialonBase
|
|
3
4
|
|
|
4
5
|
|
|
@@ -31,7 +32,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
31
32
|
)
|
|
32
33
|
return response.get("item", {}).get("id")
|
|
33
34
|
|
|
34
|
-
def
|
|
35
|
+
def set_items(self, new_items: list[str]) -> None:
|
|
35
36
|
"""
|
|
36
37
|
Sets this group's members to a list of Wialon unit ids.
|
|
37
38
|
|
|
@@ -47,7 +48,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
47
48
|
**{"itemId": self.id, "units": new_items}
|
|
48
49
|
)
|
|
49
50
|
|
|
50
|
-
def is_member(self, item: WialonBase) -> bool:
|
|
51
|
+
def is_member(self, item: Type[WialonBase]) -> bool:
|
|
51
52
|
"""
|
|
52
53
|
Determines whether or not ``item`` is a member of the group.
|
|
53
54
|
|
|
@@ -60,43 +61,9 @@ class WialonUnitGroup(WialonBase):
|
|
|
60
61
|
"""
|
|
61
62
|
return True if str(item.id) in self.items else False
|
|
62
63
|
|
|
63
|
-
def
|
|
64
|
-
self, item: WialonBase, access_mask: int = constants.ACCESSMASK_UNIT_BASIC
|
|
65
|
-
) -> None:
|
|
64
|
+
def add_item(self, item: Type[WialonBase]) -> None:
|
|
66
65
|
"""
|
|
67
|
-
|
|
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
|
-
"""
|
|
78
|
-
self.session.wialon_api.user_update_item_access(
|
|
79
|
-
**{"userId": item.id, "itemId": self.id, "accessMask": access_mask}
|
|
80
|
-
)
|
|
81
|
-
|
|
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
|
-
"""
|
|
93
|
-
self.session.wialon_api.user_update_item_access(
|
|
94
|
-
**{"userId": item.id, "itemId": self.id, "accessMask": 0}
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
def add_item(self, item: WialonBase) -> None:
|
|
98
|
-
"""
|
|
99
|
-
Adds a Wialon unit to the group.
|
|
66
|
+
Adds a Wialon item to the group.
|
|
100
67
|
|
|
101
68
|
:param item: A Wialon object.
|
|
102
69
|
:type item: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
@@ -106,9 +73,9 @@ class WialonUnitGroup(WialonBase):
|
|
|
106
73
|
|
|
107
74
|
"""
|
|
108
75
|
new_items: list[str] = self.items.copy() + [str(item.id)]
|
|
109
|
-
self.
|
|
76
|
+
self.set_items(new_items)
|
|
110
77
|
|
|
111
|
-
def rm_item(self, item: WialonBase) -> None:
|
|
78
|
+
def rm_item(self, item: Type[WialonBase]) -> None:
|
|
112
79
|
"""
|
|
113
80
|
Removes a Wialon unit from the group, if it's a member of the group.
|
|
114
81
|
|
|
@@ -123,7 +90,7 @@ class WialonUnitGroup(WialonBase):
|
|
|
123
90
|
assert self.is_member(item), f"Cannot remove {item}, it's not in the group"
|
|
124
91
|
new_items: list[str] = self.items.copy()
|
|
125
92
|
new_items.remove(str(item.id))
|
|
126
|
-
self.
|
|
93
|
+
self.set_items(new_items)
|
|
127
94
|
|
|
128
95
|
@property
|
|
129
96
|
def items(self) -> list[str]:
|
|
@@ -149,4 +116,4 @@ class WialonUnitGroup(WialonBase):
|
|
|
149
116
|
"to": 0,
|
|
150
117
|
}
|
|
151
118
|
)
|
|
152
|
-
return [
|
|
119
|
+
return [unit_id for unit_id in response.get("items")[0].get("u", [])]
|
|
@@ -1,25 +1,24 @@
|
|
|
1
1
|
import threading
|
|
2
2
|
import logging
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
from datetime import datetime
|
|
3
|
+
import typing
|
|
4
|
+
import dataclasses
|
|
5
|
+
import datetime
|
|
7
6
|
|
|
8
7
|
from wialon.api import WialonError
|
|
9
8
|
from wialon.api import Wialon as WialonAPI
|
|
10
9
|
from django.conf import settings
|
|
11
10
|
from django.utils import timezone
|
|
12
11
|
|
|
13
|
-
from .errors import WialonLogoutError, WialonLoginError
|
|
12
|
+
from terminusgps.wialon.errors import WialonLogoutError, WialonLoginError
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
@dataclass
|
|
15
|
+
@dataclasses.dataclass
|
|
17
16
|
class WialonAPICall:
|
|
18
17
|
action: str
|
|
19
|
-
timestamp: datetime
|
|
18
|
+
timestamp: datetime.datetime
|
|
20
19
|
args: tuple
|
|
21
20
|
kwargs: dict
|
|
22
|
-
result: Any = None
|
|
21
|
+
result: typing.Any = None
|
|
23
22
|
error: Exception | None = None
|
|
24
23
|
|
|
25
24
|
|
|
@@ -45,7 +44,7 @@ class Wialon(WialonAPI):
|
|
|
45
44
|
def failure_rate(self) -> float:
|
|
46
45
|
return len(self.failed_calls) / self.total_calls
|
|
47
46
|
|
|
48
|
-
def call(self, action_name: str, *argc, **kwargs) -> Any:
|
|
47
|
+
def call(self, action_name: str, *argc, **kwargs) -> typing.Any:
|
|
49
48
|
self.logger.info(f"Executing '{action_name}'...")
|
|
50
49
|
self.logger.debug(f"Executing '{action_name}' using: '{kwargs}'")
|
|
51
50
|
call_record = WialonAPICall(
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
import string
|
|
3
|
+
import warnings
|
|
4
|
+
import typing
|
|
5
|
+
|
|
6
|
+
from terminusgps.wialon import items, flags
|
|
7
|
+
from terminusgps.wialon.items.base import WialonBase
|
|
8
|
+
from terminusgps.wialon.session import WialonSession
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_hw_type_id(name: str, session: WialonSession) -> int | None:
|
|
12
|
+
"""
|
|
13
|
+
Takes a Wialon hardware type name and returns its id, if it exists.
|
|
14
|
+
|
|
15
|
+
:param name: The name of a Wialon hardware type.
|
|
16
|
+
:type name: :py:obj:`str`
|
|
17
|
+
:param session: A valid Wialon API session.
|
|
18
|
+
:type session: :py:obj:`~terminusgps.wialon.session.WialonSession`
|
|
19
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
20
|
+
:returns: A Wialon hardware type id, if it was found.
|
|
21
|
+
:rtype: :py:obj:`int` | :py:obj:`None`
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
response = session.wialon_api.core_get_hw_types(
|
|
25
|
+
**{
|
|
26
|
+
"filterType": "id",
|
|
27
|
+
"filterValue": "name,id",
|
|
28
|
+
"includeType": "true",
|
|
29
|
+
"ignoreRename": "true",
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
hw_types = {item.get("name"): item.get("id") for item in response}
|
|
33
|
+
return int(hw_types.get(name)) if name in hw_types.keys() else None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_id_from_iccid(iccid: str, session: WialonSession) -> str | None:
|
|
37
|
+
"""
|
|
38
|
+
Takes a Wialon unit's IMEI # and returns its unit id, if it exists.
|
|
39
|
+
|
|
40
|
+
:param iccid: A unique id.
|
|
41
|
+
:type iccid: :py:obj:`str`
|
|
42
|
+
:param session: A valid Wialon API session.
|
|
43
|
+
:type session: :py:obj:`~terminusgps.wialon.session.WialonSession`
|
|
44
|
+
:raises WialonError: If something goes wrong with Wialon.
|
|
45
|
+
:returns: A Wialon object id, if it was found.
|
|
46
|
+
:rtype: :py:obj:`str` | :py:obj:`None`
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
response = session.wialon_api.core_search_items(
|
|
50
|
+
**{
|
|
51
|
+
"spec": {
|
|
52
|
+
"itemsType": "avl_unit",
|
|
53
|
+
"propName": "rel_admin_field_value",
|
|
54
|
+
"propValueMask": str(iccid),
|
|
55
|
+
"sortType": "admin_fields",
|
|
56
|
+
"propType": "adminfield",
|
|
57
|
+
"or_logic": 0,
|
|
58
|
+
},
|
|
59
|
+
"force": 0,
|
|
60
|
+
"flags": flags.DATAFLAG_UNIT_BASE,
|
|
61
|
+
"from": 0,
|
|
62
|
+
"to": 0,
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if response.get("totalItemsCount", 0) == 1:
|
|
67
|
+
return response["items"][0].get("id")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def get_wialon_cls(items_type: str) -> typing.Type[WialonBase]:
|
|
71
|
+
"""
|
|
72
|
+
Returns a Wialon object class based on items_type.
|
|
73
|
+
|
|
74
|
+
:param items_type: A Wialon object type.
|
|
75
|
+
:type items_type: :py:obj:`str`
|
|
76
|
+
:returns: A subclass of :py:obj:`~terminusgps.wialon.items.base.WialonBase`.
|
|
77
|
+
:rtype: :py:obj:`~terminusgps.wialon.items.base.WialonBase`
|
|
78
|
+
|
|
79
|
+
"""
|
|
80
|
+
match items_type:
|
|
81
|
+
case "user":
|
|
82
|
+
wialon_cls = items.WialonUser
|
|
83
|
+
case "avl_unit":
|
|
84
|
+
wialon_cls = items.WialonUnit
|
|
85
|
+
case "avl_unit_group":
|
|
86
|
+
wialon_cls = items.WialonUnitGroup
|
|
87
|
+
case "avl_resource":
|
|
88
|
+
wialon_cls = items.WialonResource
|
|
89
|
+
case _:
|
|
90
|
+
raise ValueError(f"Invalid items_type '{items_type}'")
|
|
91
|
+
return wialon_cls
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def is_unique(value: str, session: WialonSession, items_type: str = "avl_unit") -> bool:
|
|
95
|
+
"""
|
|
96
|
+
Determines if the value is unique among Wialon objects of type 'items_type'.
|
|
97
|
+
|
|
98
|
+
:param value: A value whose uniqueness is unknown.
|
|
99
|
+
:type value: :py:obj:`str`
|
|
100
|
+
:param session: A valid Wialon API session.
|
|
101
|
+
:type session: :py:obj:`~terminusgps.wialon.session.WialonSession`
|
|
102
|
+
:param items_type: The type of Wialon objects to validate the value against. Default is ``"avl_unit"``.
|
|
103
|
+
:type items_type: :py:obj:`str`
|
|
104
|
+
:returns: Whether or not the value is unique among 'items_type'.
|
|
105
|
+
:rtype: :py:obj:`bool`
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
"""
|
|
109
|
+
result = session.wialon_api.core_check_unique(
|
|
110
|
+
**{"type": items_type, "value": value.strip()}
|
|
111
|
+
).get("result")
|
|
112
|
+
return not bool(result)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def generate_wialon_password(length: int = 32) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Generates a Wialon compliant password of random characters.
|
|
118
|
+
|
|
119
|
+
Password length can be between ``8`` and ``64`` characters.
|
|
120
|
+
|
|
121
|
+
:param length: Length of the generated password. Default is ``32``.
|
|
122
|
+
:type length: :py:obj:`int`
|
|
123
|
+
:raises ValueError: If the provided length is invalid.
|
|
124
|
+
:returns: A Wialon compliant password.
|
|
125
|
+
:rtype: :py:obj:`str`
|
|
126
|
+
|
|
127
|
+
"""
|
|
128
|
+
min_length, max_length = 8, 64
|
|
129
|
+
if length > max_length:
|
|
130
|
+
raise ValueError(
|
|
131
|
+
f"Password cannot be greater than {max_length} characters in length. Got {length}."
|
|
132
|
+
)
|
|
133
|
+
elif length < min_length:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
f"Password cannot be less than {min_length} characters in length. Got {length}."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
s0 = list(string.ascii_uppercase)
|
|
139
|
+
s1 = list(string.ascii_lowercase)
|
|
140
|
+
s2 = list(string.digits)
|
|
141
|
+
s3 = list("!@#$%^*()[]-_+")
|
|
142
|
+
|
|
143
|
+
while True:
|
|
144
|
+
password = "".join([secrets.choice(s0 + s1 + s2 + s3) for _ in range(length)])
|
|
145
|
+
if (
|
|
146
|
+
any(c.islower() for c in password)
|
|
147
|
+
and any(c.isupper() for c in password)
|
|
148
|
+
and sum(c.isdigit() for c in password) >= 3
|
|
149
|
+
and any(c in s3 for c in password)
|
|
150
|
+
):
|
|
151
|
+
break
|
|
152
|
+
return password
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def gen_wialon_password(length: int = 32) -> str:
|
|
156
|
+
"""
|
|
157
|
+
DEPRECATED: Use :py:func:`~terminusgps.wialon.utils.generate_wialon_password` instead.
|
|
158
|
+
|
|
159
|
+
Generates a Wialon compliant password of random characters.
|
|
160
|
+
|
|
161
|
+
Password length can be between ``8`` and ``64`` characters.
|
|
162
|
+
|
|
163
|
+
:param length: Length of the generated password. Default is ``32``.
|
|
164
|
+
:type length: :py:obj:`int`
|
|
165
|
+
:raises ValueError: If the provided length is invalid.
|
|
166
|
+
:returns: A Wialon compliant password.
|
|
167
|
+
:rtype: :py:obj:`str`
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
warnings.warn(
|
|
171
|
+
"gen_wialon_password is deprecated and will be removed in a future version. Use generate_wialon_password instead.",
|
|
172
|
+
DeprecationWarning,
|
|
173
|
+
stacklevel=2,
|
|
174
|
+
)
|
|
175
|
+
return generate_wialon_password(length)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
__all__ = [
|
|
179
|
+
"get_hw_type_id",
|
|
180
|
+
"get_id_from_iccid",
|
|
181
|
+
"get_wialon_cls",
|
|
182
|
+
"is_unique",
|
|
183
|
+
"generate_wialon_password",
|
|
184
|
+
"gen_wialon_password",
|
|
185
|
+
]
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import secrets
|
|
2
|
-
import string
|
|
3
|
-
|
|
4
|
-
from typing import Any
|
|
5
|
-
from .session import WialonSession
|
|
6
|
-
from .flags import DATAFLAG_UNIT_BASE
|
|
7
|
-
|
|
8
|
-
from terminusgps.wialon.items import (
|
|
9
|
-
WialonUser,
|
|
10
|
-
WialonUnit,
|
|
11
|
-
WialonUnitGroup,
|
|
12
|
-
WialonResource,
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def get_hw_type_id(name: str, session: WialonSession) -> int | None:
|
|
17
|
-
response = session.wialon_api.core_get_hw_types(
|
|
18
|
-
**{
|
|
19
|
-
"filterType": "id",
|
|
20
|
-
"filterValue": "name,id",
|
|
21
|
-
"includeType": "true",
|
|
22
|
-
"ignoreRename": "true",
|
|
23
|
-
}
|
|
24
|
-
)
|
|
25
|
-
hw_types = {item.get("name"): item.get("id") for item in response}
|
|
26
|
-
return int(hw_types.get(name)) if name in hw_types.keys() else None
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def get_wialon_cls(items_type: str) -> Any:
|
|
30
|
-
"""Returns a Wialon object class based on items_type."""
|
|
31
|
-
match items_type:
|
|
32
|
-
case "user":
|
|
33
|
-
wialon_cls = WialonUser
|
|
34
|
-
case "avl_unit":
|
|
35
|
-
wialon_cls = WialonUnit
|
|
36
|
-
case "avl_unit_group":
|
|
37
|
-
wialon_cls = WialonUnitGroup
|
|
38
|
-
case "avl_resource":
|
|
39
|
-
wialon_cls = WialonResource
|
|
40
|
-
case _:
|
|
41
|
-
raise ValueError(f"Invalid items_type '{items_type}'")
|
|
42
|
-
return wialon_cls
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def is_unique(value: str, session: WialonSession, items_type: str = "avl_unit") -> bool:
|
|
46
|
-
"""Determines if the value is unique among Wialon objects of type 'items_type'."""
|
|
47
|
-
result = session.wialon_api.core_check_unique(
|
|
48
|
-
**{"type": items_type, "value": value.strip()}
|
|
49
|
-
).get("result")
|
|
50
|
-
return not bool(result)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def gen_wialon_password(length: int = 32) -> str:
|
|
54
|
-
"""Generates a Wialon compliant password."""
|
|
55
|
-
min_length, max_length = 4, 64
|
|
56
|
-
if length > max_length:
|
|
57
|
-
raise ValueError(
|
|
58
|
-
f"Password cannot be greater than {max_length} characters in length. Got {length}."
|
|
59
|
-
)
|
|
60
|
-
elif length < min_length:
|
|
61
|
-
raise ValueError(
|
|
62
|
-
f"Password cannot be less than {min_length} characters in length. Got {length}."
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
s0 = list(string.ascii_uppercase)
|
|
66
|
-
s1 = list(string.ascii_lowercase)
|
|
67
|
-
s2 = list(string.digits)
|
|
68
|
-
s3 = list("!@#$%^*()[]-_+")
|
|
69
|
-
|
|
70
|
-
while True:
|
|
71
|
-
password = "".join([secrets.choice(s0 + s1 + s2 + s3) for _ in range(length)])
|
|
72
|
-
if (
|
|
73
|
-
any(c.islower() for c in password)
|
|
74
|
-
and any(c.isupper() for c in password)
|
|
75
|
-
and sum(c.isdigit() for c in password) >= 3
|
|
76
|
-
and any(c in s3 for c in password)
|
|
77
|
-
):
|
|
78
|
-
break
|
|
79
|
-
return password
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def get_id_from_iccid(iccid: str, session: WialonSession) -> str | None:
|
|
83
|
-
"""Takes a Wialon unit's IMEI # and returns its unit id, if it exists."""
|
|
84
|
-
response = session.wialon_api.core_search_items(
|
|
85
|
-
**{
|
|
86
|
-
"spec": {
|
|
87
|
-
"itemsType": "avl_unit",
|
|
88
|
-
"propName": "rel_admin_field_value",
|
|
89
|
-
"propValueMask": str(iccid),
|
|
90
|
-
"sortType": "admin_fields",
|
|
91
|
-
"propType": "adminfield",
|
|
92
|
-
"or_logic": 0,
|
|
93
|
-
},
|
|
94
|
-
"force": 0,
|
|
95
|
-
"flags": DATAFLAG_UNIT_BASE,
|
|
96
|
-
"from": 0,
|
|
97
|
-
"to": 0,
|
|
98
|
-
}
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
if response.get("totalItemsCount", 0) == 1:
|
|
102
|
-
return response["items"][0].get("id")
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def main() -> None:
|
|
106
|
-
with WialonSession() as session:
|
|
107
|
-
wialon_id = get_id_from_iccid("89015809000307608963", session)
|
|
108
|
-
print(f"{wialon_id = }")
|
|
109
|
-
return
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if __name__ == "__main__":
|
|
113
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/profiles/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/authorizenet/subscriptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/__init__.py
RENAMED
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/notification.py
RENAMED
|
File without changes
|
{python_terminusgps-1.15.1 → python_terminusgps-1.16.0}/terminusgps/wialon/items/retranslator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|