pycloudedge 0.1.6.dev2__py3-none-any.whl → 0.1.6.dev4__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.
- cloudedge/_version.py +8 -18
- cloudedge/client.py +24 -22
- cloudedge/constants.py +3 -69
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/METADATA +1 -1
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/RECORD +9 -9
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/WHEEL +0 -0
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/entry_points.txt +0 -0
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/licenses/LICENSE +0 -0
- {pycloudedge-0.1.6.dev2.dist-info → pycloudedge-0.1.6.dev4.dist-info}/top_level.txt +0 -0
cloudedge/_version.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
# file generated by
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
2
|
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
3
4
|
|
|
4
5
|
__all__ = [
|
|
5
6
|
"__version__",
|
|
@@ -10,25 +11,14 @@ __all__ = [
|
|
|
10
11
|
"commit_id",
|
|
11
12
|
]
|
|
12
13
|
|
|
13
|
-
TYPE_CHECKING = False
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from typing import Tuple
|
|
16
|
-
from typing import Union
|
|
17
|
-
|
|
18
|
-
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
-
COMMIT_ID = Union[str, None]
|
|
20
|
-
else:
|
|
21
|
-
VERSION_TUPLE = object
|
|
22
|
-
COMMIT_ID = object
|
|
23
|
-
|
|
24
14
|
version: str
|
|
25
15
|
__version__: str
|
|
26
|
-
__version_tuple__:
|
|
27
|
-
version_tuple:
|
|
28
|
-
commit_id:
|
|
29
|
-
__commit_id__:
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
30
20
|
|
|
31
|
-
__version__ = version = '0.1.6.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 1, 6, '
|
|
21
|
+
__version__ = version = '0.1.6.dev4'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 6, 'dev4')
|
|
33
23
|
|
|
34
24
|
__commit_id__ = commit_id = None
|
cloudedge/client.py
CHANGED
|
@@ -37,9 +37,7 @@ from .iot_parameters import (
|
|
|
37
37
|
)
|
|
38
38
|
from .constants import (
|
|
39
39
|
CA_KEY, CA_SECRET, DEFAULT_HEADERS, DEFAULT_TIMEOUT,
|
|
40
|
-
REGION_ENDPOINTS, REGION_EU, REGION_US, REGION_AP,
|
|
41
40
|
REDIRECT_URL,
|
|
42
|
-
region_for_country,
|
|
43
41
|
)
|
|
44
42
|
from .validators import validate_email, validate_country_code, validate_phone_code
|
|
45
43
|
from .logging_config import get_logger
|
|
@@ -132,7 +130,6 @@ class CloudEdgeClient:
|
|
|
132
130
|
session_cache_file: str = ".cloudedge_session_cache",
|
|
133
131
|
enable_network_ping: bool = True,
|
|
134
132
|
ping_timeout: float = 2.0,
|
|
135
|
-
region: Optional[str] = None,
|
|
136
133
|
):
|
|
137
134
|
"""
|
|
138
135
|
Initialize CloudEdge API client.
|
|
@@ -146,10 +143,6 @@ class CloudEdgeClient:
|
|
|
146
143
|
session_cache_file (str): Path to session cache file
|
|
147
144
|
enable_network_ping (bool): Enable ping-based online status when on same network
|
|
148
145
|
ping_timeout (float): Ping timeout in seconds
|
|
149
|
-
region (str, optional): Force a specific region ("eu", "us", or "ap").
|
|
150
|
-
When *None* the region is derived automatically from *country_code*:
|
|
151
|
-
European countries → EU, Asia-Pacific/Oceania/ME/Africa → AP
|
|
152
|
-
(Singapore), everything else → US.
|
|
153
146
|
|
|
154
147
|
Raises:
|
|
155
148
|
ValidationError: If input validation fails
|
|
@@ -173,17 +166,18 @@ class CloudEdgeClient:
|
|
|
173
166
|
details={"field": "phone_code", "value": phone_code}
|
|
174
167
|
)
|
|
175
168
|
|
|
169
|
+
normalized_country_code = country_code.upper()
|
|
170
|
+
if normalized_country_code == "UK":
|
|
171
|
+
normalized_country_code = "GB"
|
|
172
|
+
|
|
176
173
|
self.username = username
|
|
177
174
|
self.password = password
|
|
178
|
-
self.country_code =
|
|
175
|
+
self.country_code = normalized_country_code
|
|
179
176
|
self.phone_code = phone_code if phone_code.startswith('+') else f'+{phone_code}'
|
|
180
177
|
|
|
181
|
-
#
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
self.region = resolved_region
|
|
185
|
-
self.BASE_URL = endpoints["base_url"]
|
|
186
|
-
self.OPENAPI_BASE_URL = endpoints["openapi_base_url"]
|
|
178
|
+
# Endpoints are discovered dynamically via _discover_endpoints()
|
|
179
|
+
self.BASE_URL: Optional[str] = None
|
|
180
|
+
self.OPENAPI_BASE_URL: Optional[str] = None
|
|
187
181
|
|
|
188
182
|
# Setup proper logging
|
|
189
183
|
self.logger = get_logger("client")
|
|
@@ -557,8 +551,11 @@ class CloudEdgeClient:
|
|
|
557
551
|
contains the regional ``apiServer`` and ``openapi`` domain that must be
|
|
558
552
|
used for the given account/country.
|
|
559
553
|
|
|
560
|
-
On success, ``self.BASE_URL`` and ``self.OPENAPI_BASE_URL`` are
|
|
561
|
-
|
|
554
|
+
On success, ``self.BASE_URL`` and ``self.OPENAPI_BASE_URL`` are set.
|
|
555
|
+
|
|
556
|
+
Raises:
|
|
557
|
+
NetworkError: If the redirect API call fails or returns an
|
|
558
|
+
unexpected response and no endpoints were previously set.
|
|
562
559
|
"""
|
|
563
560
|
import random
|
|
564
561
|
|
|
@@ -593,9 +590,6 @@ class CloudEdgeClient:
|
|
|
593
590
|
).hexdigest()
|
|
594
591
|
|
|
595
592
|
# X-Ca-Sign: HMAC-SHA1 with CA_SECRET as key
|
|
596
|
-
# The app builds: "api=/ppstrongs/" + getRealUrl(path) + "|X-Ca-Key=...|..."
|
|
597
|
-
# getRealUrl("/ppstrongs/redirect") returns "/ppstrongs/redirect" unchanged,
|
|
598
|
-
# so the full string is "api=/ppstrongs//ppstrongs/redirect|..."
|
|
599
593
|
ca_sign_data = (
|
|
600
594
|
f"api=/ppstrongs//ppstrongs/redirect"
|
|
601
595
|
f"|X-Ca-Key={CA_KEY}"
|
|
@@ -620,8 +614,9 @@ class CloudEdgeClient:
|
|
|
620
614
|
)
|
|
621
615
|
data = resp.json()
|
|
622
616
|
if data.get("resultCode") != "1001":
|
|
623
|
-
|
|
624
|
-
|
|
617
|
+
raise NetworkError(
|
|
618
|
+
f"Redirect discovery returned unexpected code: {data.get('resultCode')}"
|
|
619
|
+
)
|
|
625
620
|
|
|
626
621
|
result = data.get("result", {})
|
|
627
622
|
api_server = result.get("apiServer") or result.get("gwUrl") or ""
|
|
@@ -635,8 +630,15 @@ class CloudEdgeClient:
|
|
|
635
630
|
self.OPENAPI_BASE_URL = openapi_domain.rstrip("/")
|
|
636
631
|
self._log(f"Discovered OpenAPI server: {self.OPENAPI_BASE_URL}")
|
|
637
632
|
|
|
633
|
+
if not self.BASE_URL:
|
|
634
|
+
raise NetworkError(
|
|
635
|
+
"Redirect API did not return an apiServer"
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
except NetworkError:
|
|
639
|
+
raise
|
|
638
640
|
except Exception as exc:
|
|
639
|
-
|
|
641
|
+
raise NetworkError(f"Endpoint discovery failed: {exc}") from exc
|
|
640
642
|
|
|
641
643
|
def authenticate(self) -> bool:
|
|
642
644
|
"""
|
cloudedge/constants.py
CHANGED
|
@@ -2,77 +2,11 @@
|
|
|
2
2
|
Configuration constants for CloudEdge API
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
REGION_AP = "ap"
|
|
9
|
-
|
|
10
|
-
# Per-region API endpoints (static fallback when redirect discovery fails)
|
|
11
|
-
REGION_ENDPOINTS = {
|
|
12
|
-
REGION_EU: {
|
|
13
|
-
"base_url": "https://apis-eu-frankfurt.cloudedge360.com",
|
|
14
|
-
"openapi_base_url": "https://openapi-euce.mearicloud.com",
|
|
15
|
-
},
|
|
16
|
-
REGION_US: {
|
|
17
|
-
"base_url": "https://apis-us-west.cloudedge360.com",
|
|
18
|
-
"openapi_base_url": "https://openapi-uswe.mearicloud.com",
|
|
19
|
-
},
|
|
20
|
-
REGION_AP: {
|
|
21
|
-
"base_url": "https://apis-as-singapore.cloudedge360.com",
|
|
22
|
-
"openapi_base_url": "https://openapi-usce.mearicloud.com",
|
|
23
|
-
},
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
# Global redirect endpoint — used to discover the correct regional server
|
|
5
|
+
# Global redirect endpoint — used to discover the correct regional server.
|
|
6
|
+
# This is the single source of truth: the redirect API returns the correct
|
|
7
|
+
# ``apiServer`` and ``openapi`` domain for the given account/country.
|
|
27
8
|
REDIRECT_URL = "https://apis.cloudedge360.com/ppstrongs/redirect"
|
|
28
9
|
|
|
29
|
-
# Default endpoints (EU) – kept for backward compatibility
|
|
30
|
-
BASE_URL = REGION_ENDPOINTS[REGION_EU]["base_url"]
|
|
31
|
-
OPENAPI_BASE_URL = REGION_ENDPOINTS[REGION_EU]["openapi_base_url"]
|
|
32
|
-
|
|
33
|
-
# European country codes (ISO 3166-1 alpha-2)
|
|
34
|
-
EU_COUNTRY_CODES = {
|
|
35
|
-
"AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR",
|
|
36
|
-
"DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL",
|
|
37
|
-
"PL", "PT", "RO", "SK", "SI", "ES", "SE",
|
|
38
|
-
# EEA + EFTA + UK
|
|
39
|
-
"IS", "LI", "NO", "CH", "GB",
|
|
40
|
-
# Other European countries
|
|
41
|
-
"AL", "AD", "AM", "AZ", "BA", "BY", "GE", "GI", "XK", "MD",
|
|
42
|
-
"MC", "ME", "MK", "RS", "RU", "SM", "TR", "UA", "VA",
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# Asia-Pacific / Oceania / Middle East / Africa country codes
|
|
47
|
-
# These are routed through the Singapore gateway
|
|
48
|
-
AP_COUNTRY_CODES = {
|
|
49
|
-
# East Asia
|
|
50
|
-
"JP", "KR", "TW", "HK", "MO",
|
|
51
|
-
# Southeast Asia
|
|
52
|
-
"SG", "MY", "TH", "VN", "PH", "ID", "MM", "KH", "LA", "BN", "TL",
|
|
53
|
-
# South Asia
|
|
54
|
-
"IN", "PK", "BD", "LK", "NP", "BT", "MV",
|
|
55
|
-
# Oceania
|
|
56
|
-
"AU", "NZ", "FJ", "PG", "WS", "TO", "VU", "SB", "KI", "MH", "FM",
|
|
57
|
-
"PW", "NR", "TV", "CK", "NU",
|
|
58
|
-
# Middle East
|
|
59
|
-
"AE", "SA", "QA", "KW", "BH", "OM", "JO", "LB", "IQ", "IR", "YE",
|
|
60
|
-
"SY", "PS", "IL",
|
|
61
|
-
# Africa
|
|
62
|
-
"ZA", "EG", "NG", "KE", "GH", "TZ", "UG", "ET", "MA", "DZ", "TN",
|
|
63
|
-
"SN", "CI", "CM", "AO", "MZ", "ZW", "BW", "NA", "MU", "MG", "RW",
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def region_for_country(country_code: str) -> str:
|
|
68
|
-
"""Return the region key for a given ISO 3166-1 alpha-2 country code."""
|
|
69
|
-
cc = country_code.upper()
|
|
70
|
-
if cc in EU_COUNTRY_CODES:
|
|
71
|
-
return REGION_EU
|
|
72
|
-
if cc in AP_COUNTRY_CODES:
|
|
73
|
-
return REGION_AP
|
|
74
|
-
return REGION_US
|
|
75
|
-
|
|
76
10
|
# API Keys (these are public keys from the mobile app)
|
|
77
11
|
CA_KEY = "bc29be30292a4309877807e101afbd51"
|
|
78
12
|
CA_SECRET = "35a69fd1-6527-4566-b190-921f9a651488"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
cloudedge/__init__.py,sha256=l14PmA4B_JcYaFXKWhSxnJMEs3q8eCEoVliY_wlr4fQ,1465
|
|
2
|
-
cloudedge/_version.py,sha256=
|
|
2
|
+
cloudedge/_version.py,sha256=p56e4krPARNeSFFB40m4hfghTS7CXpna0hpttVgGTts,533
|
|
3
3
|
cloudedge/cli.py,sha256=E3MWYyjLGsaR8gu8dtesfBsmHuVyKlYFR5fsLRH067w,10318
|
|
4
|
-
cloudedge/client.py,sha256=
|
|
5
|
-
cloudedge/constants.py,sha256=
|
|
4
|
+
cloudedge/client.py,sha256=muYH2Xbhx4IvkQokt5esYQsDAEwjAB5RZ6H-VqGJBSE,80640
|
|
5
|
+
cloudedge/constants.py,sha256=oaop1OXIHoRhk_qaOPTz7sylmflDvGjrGSBbBqO-fyQ,1127
|
|
6
6
|
cloudedge/exceptions.py,sha256=YlSwhGPfUQyd4vclxURMBT3uh3gMF-PLtEYpNmJO2BM,903
|
|
7
7
|
cloudedge/image_decrypt.py,sha256=Hq6PD4Qm-yBiMXeocD0Z4MmUS5bwHrIxMAJmhEdCekE,3036
|
|
8
8
|
cloudedge/iot_parameters.py,sha256=HtaSwVn6Tqb7Dxwd1IQKNYBlMrq0OuMO8kzbJhxB9us,29122
|
|
@@ -10,9 +10,9 @@ cloudedge/logging_config.py,sha256=cLi5K8JnjaiXhbSjdloiUxH6dY-j2nm6C7fFnTiKpAs,1
|
|
|
10
10
|
cloudedge/mqtt.py,sha256=ha6GeWz5XiPxDULh6XHJcz4WdPH3P16kWcFNBcCuZMg,9423
|
|
11
11
|
cloudedge/utils.py,sha256=zp-GoztdJ3SFsyfKtBBLIn_w0eWDCd2pW67AUdKZYe4,3477
|
|
12
12
|
cloudedge/validators.py,sha256=kGJLODZVr5WQOS7Nsk_NNhQMU8GlJCvluvWLFTj_PdA,2536
|
|
13
|
-
pycloudedge-0.1.6.
|
|
14
|
-
pycloudedge-0.1.6.
|
|
15
|
-
pycloudedge-0.1.6.
|
|
16
|
-
pycloudedge-0.1.6.
|
|
17
|
-
pycloudedge-0.1.6.
|
|
18
|
-
pycloudedge-0.1.6.
|
|
13
|
+
pycloudedge-0.1.6.dev4.dist-info/licenses/LICENSE,sha256=85LbTeXx8Asym2aeMCC4qWMqnQNNTCLqfKmtKp6-I9E,11349
|
|
14
|
+
pycloudedge-0.1.6.dev4.dist-info/METADATA,sha256=d3UueYgq8SCqXkUjjYsnJCLPwNoYo3SRfhG3pPklAy0,18618
|
|
15
|
+
pycloudedge-0.1.6.dev4.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
16
|
+
pycloudedge-0.1.6.dev4.dist-info/entry_points.txt,sha256=dIzG_xctEzY_c1r5_P532eyR-OzyBZifrwwKE3Af3MQ,49
|
|
17
|
+
pycloudedge-0.1.6.dev4.dist-info/top_level.txt,sha256=1pbXwYPKRdEUABQrlLuTz6IbY1PCofklJ--4eg82UMQ,10
|
|
18
|
+
pycloudedge-0.1.6.dev4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|