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 CHANGED
@@ -1,5 +1,6 @@
1
- # file generated by setuptools-scm
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__: VERSION_TUPLE
27
- version_tuple: VERSION_TUPLE
28
- commit_id: COMMIT_ID
29
- __commit_id__: 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.dev2'
32
- __version_tuple__ = version_tuple = (0, 1, 6, 'dev2')
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 = country_code.upper()
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
- # Resolve region and endpoints
182
- resolved_region = region if region in REGION_ENDPOINTS else region_for_country(self.country_code)
183
- endpoints = REGION_ENDPOINTS[resolved_region]
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 updated.
561
- On failure the previously configured (static) endpoints are kept.
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
- self._log(f"Redirect discovery returned {data.get('resultCode')}")
624
- return
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
- self._log(f"Endpoint discovery failed (will use static endpoints): {exc}")
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
- # Region identifiers
6
- REGION_EU = "eu"
7
- REGION_US = "us"
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pycloudedge
3
- Version: 0.1.6.dev2
3
+ Version: 0.1.6.dev4
4
4
  Summary: Python library for CloudEdge cameras
5
5
  Home-page: https://github.com/fradaloisio/pycloudedge
6
6
  Author: Francesco D'Aloisio
@@ -1,8 +1,8 @@
1
1
  cloudedge/__init__.py,sha256=l14PmA4B_JcYaFXKWhSxnJMEs3q8eCEoVliY_wlr4fQ,1465
2
- cloudedge/_version.py,sha256=PLPzXBIkQAXc-mvnIPLNmQqit_i0rmO6w4hdXJlO3xc,717
2
+ cloudedge/_version.py,sha256=p56e4krPARNeSFFB40m4hfghTS7CXpna0hpttVgGTts,533
3
3
  cloudedge/cli.py,sha256=E3MWYyjLGsaR8gu8dtesfBsmHuVyKlYFR5fsLRH067w,10318
4
- cloudedge/client.py,sha256=m2RX_GY_2-wc0hx6nDApPfXEAVNvo3NNOYdX93aLXX8,81018
5
- cloudedge/constants.py,sha256=gsUMAJhM-fg3J6OIP5jea9rVSOQY0onDXLXSJrkx1TI,3265
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.dev2.dist-info/licenses/LICENSE,sha256=85LbTeXx8Asym2aeMCC4qWMqnQNNTCLqfKmtKp6-I9E,11349
14
- pycloudedge-0.1.6.dev2.dist-info/METADATA,sha256=Gu3bM690polC2sS56QCbLhKD73q6__qsyKB5iavm8SQ,18618
15
- pycloudedge-0.1.6.dev2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
16
- pycloudedge-0.1.6.dev2.dist-info/entry_points.txt,sha256=dIzG_xctEzY_c1r5_P532eyR-OzyBZifrwwKE3Af3MQ,49
17
- pycloudedge-0.1.6.dev2.dist-info/top_level.txt,sha256=1pbXwYPKRdEUABQrlLuTz6IbY1PCofklJ--4eg82UMQ,10
18
- pycloudedge-0.1.6.dev2.dist-info/RECORD,,
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,,