python-aidot-cameras 0.7.22__tar.gz → 0.7.24__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.
Files changed (59) hide show
  1. {python_aidot_cameras-0.7.22/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.24}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/pyproject.toml +1 -1
  3. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/client.py +23 -4
  4. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  5. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_sdes_fast_liveplay.py +16 -0
  6. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/LICENSE +0 -0
  7. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/MANIFEST.in +0 -0
  8. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/README.md +0 -0
  9. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/setup.cfg +0 -0
  10. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/__init__.py +0 -0
  11. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/aes_utils.py +0 -0
  12. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/__init__.py +0 -0
  13. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/constants.py +0 -0
  14. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/controls.py +0 -0
  15. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/go2rtc.py +0 -0
  16. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/lan_control.py +0 -0
  17. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/models.py +0 -0
  18. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/playback.py +0 -0
  19. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/protocol.py +0 -0
  20. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/sdes.py +0 -0
  21. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/tutk.py +0 -0
  22. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/camera/webrtc.py +0 -0
  23. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/client.py +0 -0
  24. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/const.py +0 -0
  25. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/credentials.py +0 -0
  26. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/device_client.py +0 -0
  27. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/discover.py +0 -0
  28. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/exceptions.py +0 -0
  29. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/g711.py +0 -0
  30. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/login_const.py +0 -0
  31. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/models/__init__.py +0 -0
  32. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/models/device_client_model.py +0 -0
  33. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/models/device_model.py +0 -0
  34. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/models/discover_model.py +0 -0
  35. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/aidot/py.typed +0 -0
  36. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  37. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  38. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
  39. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
  40. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_alarm_event.py +0 -0
  41. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_backoff.py +0 -0
  42. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_go2rtc.py +0 -0
  43. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_highport_nomination.py +0 -0
  44. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_lan_control.py +0 -0
  45. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_live_stream_param.py +0 -0
  46. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_motion_poll.py +0 -0
  47. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_no_undefined_names.py +0 -0
  48. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_post_merge_hardening.py +0 -0
  49. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_sdes_idle_release.py +0 -0
  50. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_sdes_sprop.py +0 -0
  51. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_sdes_talk.py +0 -0
  52. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_sdes_watchdog.py +0 -0
  53. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_serve_relay.py +0 -0
  54. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_speak.py +0 -0
  55. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_stream_cap.py +0 -0
  56. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_stream_idle.py +0 -0
  57. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_talk.py +0 -0
  58. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_terminal_ack.py +0 -0
  59. {python_aidot_cameras-0.7.22 → python_aidot_cameras-0.7.24}/tests/test_token_refresh.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.7.22
3
+ Version: 0.7.24
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-aidot-cameras"
7
- version = "0.7.22"
7
+ version = "0.7.24"
8
8
  description = "Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -543,6 +543,14 @@ class CameraMixin(_CameraControlsMixin):
543
543
  # data-channel-less; it's parked on the SDES/TUTK side anyway.
544
544
  _NO_DATACHANNEL_MODELS: frozenset = frozenset({"LK.IPC.A001064"})
545
545
 
546
+ # A001064's role-reversal handshake (the camera echoes our offer back as its
547
+ # own webrtcReq before doing ICE, and won't stream until it gets our
548
+ # webrtcResp) needs the camera armed BEFORE our webrtcReq. sdes_fast_liveplay
549
+ # sends webrtcReq ~4.5 s earlier, which degrades A001064 media reliability
550
+ # (2/2 -> 1/2 media in a live A/B; the flag was soak-validated only on the
551
+ # A001513 battery cameras). Exclude role-reversal models from the flag.
552
+ _NO_FAST_LIVEPLAY_MODELS: frozenset = frozenset({"LK.IPC.A001064"})
553
+
546
554
  @property
547
555
  def _offer_should_include_datachannel(self) -> bool:
548
556
  model = getattr(getattr(self, "info", None), "model_id", None)
@@ -2532,11 +2540,19 @@ class CameraMixin(_CameraControlsMixin):
2532
2540
  return 120.0
2533
2541
 
2534
2542
  def _resolve_sdes_fast_liveplay(self) -> bool:
2535
- """Whether to skip the ~2 s livePlayResp wait for SDES (P5, EXPERIMENTAL).
2543
+ """Whether to use SDES fast-liveplay (shorten the always-timing-out
2544
+ echo/livePlayResp signaling) - validated in soak, opt-in, default off.
2536
2545
 
2537
2546
  Per-camera ``sdes_fast_liveplay`` (set via start_keepalive) wins; else the
2538
2547
  ``AIDOT_SDES_FAST_LIVEPLAY`` env (truthy = 1/true/yes/on), default off.
2539
- Only consulted for SDES cameras (the caller gates on is_sdes_camera)."""
2548
+ Only consulted for SDES cameras (the caller gates on is_sdes_camera).
2549
+
2550
+ Role-reversal models (``_NO_FAST_LIVEPLAY_MODELS``, e.g. A001064) are always
2551
+ excluded - their handshake needs the camera armed before our webrtcReq, so
2552
+ the flag's early webrtcReq degrades their media reliability."""
2553
+ model = getattr(getattr(self, "info", None), "model_id", None)
2554
+ if model in self._NO_FAST_LIVEPLAY_MODELS:
2555
+ return False
2540
2556
  opt = getattr(self, "_sdes_fast_liveplay_opt", None)
2541
2557
  if opt is not None:
2542
2558
  return bool(opt)
@@ -7047,13 +7063,16 @@ class CameraMixin(_CameraControlsMixin):
7047
7063
  # webrtcReq. The echo confirms the MQTT pipeline to this device is live
7048
7064
  # and the broker session is registered. Fall through after 5 s if it
7049
7065
  # never arrives (same safety as the old fixed 0.5 s sleep, but adaptive).
7050
- # P5 (experimental, opt-in via sdes_fast_liveplay): instrumentation showed
7066
+ # SDES fast-liveplay (opt-in via sdes_fast_liveplay): instrumentation showed
7051
7067
  # the echo and livePlayResp waits BOTH always time out for the SDES cameras
7052
7068
  # measured (echo/resp never arrive) yet streaming succeeds - i.e. ~6 s of
7053
7069
  # dead padding. When the flag is on, cap the echo wait short and skip the
7054
7070
  # livePlayResp wait; the full ICE/TURN/SCTP handshake is untouched. This
7055
7071
  # is the SDES path's OWN livePlay waits (the DTLS gate above never runs for
7056
- # SDES: use_sdes is True there).
7072
+ # SDES: use_sdes is True there). VALIDATED in a 3 h live soak (15 SDES
7073
+ # opens across battery cameras, flag engaged on all, 0 churn / 0 fail,
7074
+ # ~4.5 s signaling saved); kept off by default pending broader multi-day
7075
+ # use (per-open + near-term stability proven, long-haul not yet).
7057
7076
  _skip_lp = self._resolve_sdes_fast_liveplay()
7058
7077
  _echo_timeout = 1.5 if _skip_lp else 5.0
7059
7078
  _echo_t0 = time.monotonic()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.7.22
3
+ Version: 0.7.24
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -38,6 +38,22 @@ def test_env_falsey_values(monkeypatch):
38
38
  assert _cam()._resolve_sdes_fast_liveplay() is False, val
39
39
 
40
40
 
41
+ def test_role_reversal_model_always_excluded(monkeypatch):
42
+ # A001064 (role-reversal) must NOT use the flag even when opt/env force it on -
43
+ # the early webrtcReq degrades its media reliability.
44
+ from types import SimpleNamespace
45
+ monkeypatch.setenv("AIDOT_SDES_FAST_LIVEPLAY", "1")
46
+ cam = _cam()
47
+ cam.info = SimpleNamespace(model_id="LK.IPC.A001064")
48
+ cam._sdes_fast_liveplay_opt = True
49
+ assert cam._resolve_sdes_fast_liveplay() is False
50
+ # a non-excluded SDES model still honours the flag
51
+ cam2 = _cam()
52
+ cam2.info = SimpleNamespace(model_id="LK.IPC.A001513")
53
+ cam2._sdes_fast_liveplay_opt = True
54
+ assert cam2._resolve_sdes_fast_liveplay() is True
55
+
56
+
41
57
  def test_kwarg_option_wins_over_env(monkeypatch):
42
58
  monkeypatch.setenv("AIDOT_SDES_FAST_LIVEPLAY", "1")
43
59
  cam = _cam()