python-swidget 1.4.17__tar.gz → 1.4.18__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-swidget
3
- Version: 1.4.17
3
+ Version: 1.4.18
4
4
  Summary: Python API for Swidget smart devices
5
5
  Home-page: https://github.com/swidget/python-swidget
6
6
  License: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-swidget"
3
- version = "1.4.17"
3
+ version = "1.4.18"
4
4
  description = "Python API for Swidget smart devices"
5
5
  license = "GPL-3.0-or-later"
6
6
  authors = ["Swidget"]
@@ -59,10 +59,19 @@ devices = dict()
59
59
  async def detect_secure(host: str, timeout: float = DETECT_TIMEOUT_SEC) -> bool:
60
60
  """Determine whether a Swidget device requires HTTPS+auth.
61
61
 
62
- Probes ``/api/v1/summary`` over HTTPS first (no credentials). A 403
63
- response means the firmware enforces auth the device is in secure
64
- mode. If HTTPS is unreachable, falls back to HTTP; a 200 there means
65
- the device is in plaintext mode.
62
+ Probes ``/api/v1/summary`` over HTTP first; a 200 means the device
63
+ is in plaintext mode. Secure-mode firmware running on the same port
64
+ answers 403 ("TLS required") instead, so anything non-200 falls
65
+ through to the HTTPS probe.
66
+
67
+ On HTTPS, both 401 and 403 indicate secure mode:
68
+ - **401 "Authorization Missing"** — no token in the request (our
69
+ probe doesn't carry one).
70
+ - **403 "Forbidden"** — token rejected ("Incorrect Token") or the
71
+ device's secret key has never been provisioned ("Key not set").
72
+
73
+ Both states mean "secure mode is enforced, prompt the caller for
74
+ credentials", so we collapse them into a single True return.
66
75
 
67
76
  :param host: Hostname or IP of the device.
68
77
  :param timeout: Per-request timeout in seconds. Defaults are generous
@@ -83,10 +92,12 @@ async def detect_secure(host: str, timeout: float = DETECT_TIMEOUT_SEC) -> bool:
83
92
  except (ClientError, asyncio.TimeoutError):
84
93
  pass
85
94
 
86
- # Fall back to HTTPS. A 403 means the firmware is enforcing auth.
95
+ # Fall back to HTTPS. 401 ("Authorization Missing") and 403
96
+ # ("Forbidden" — wrong token, or key not set) both mean the
97
+ # firmware is in secure mode; the caller now needs credentials.
87
98
  try:
88
99
  async with session.get(f"https://{host}/api/v1/summary") as resp:
89
- if resp.status == 403:
100
+ if resp.status in (401, 403):
90
101
  return True
91
102
  except (ClientError, asyncio.TimeoutError):
92
103
  pass