python-aidot-cameras 0.7.24__tar.gz → 0.7.25__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.24/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.25}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/pyproject.toml +1 -1
  3. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/client.py +39 -8
  4. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  5. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/LICENSE +0 -0
  6. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/MANIFEST.in +0 -0
  7. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/README.md +0 -0
  8. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/setup.cfg +0 -0
  9. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/__init__.py +0 -0
  10. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/aes_utils.py +0 -0
  11. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/__init__.py +0 -0
  12. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/constants.py +0 -0
  13. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/controls.py +0 -0
  14. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/go2rtc.py +0 -0
  15. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/lan_control.py +0 -0
  16. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/models.py +0 -0
  17. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/playback.py +0 -0
  18. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/protocol.py +0 -0
  19. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/sdes.py +0 -0
  20. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/tutk.py +0 -0
  21. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/camera/webrtc.py +0 -0
  22. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/client.py +0 -0
  23. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/const.py +0 -0
  24. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/credentials.py +0 -0
  25. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/device_client.py +0 -0
  26. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/discover.py +0 -0
  27. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/exceptions.py +0 -0
  28. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/g711.py +0 -0
  29. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/login_const.py +0 -0
  30. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/models/__init__.py +0 -0
  31. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/models/device_client_model.py +0 -0
  32. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/models/device_model.py +0 -0
  33. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/models/discover_model.py +0 -0
  34. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/aidot/py.typed +0 -0
  35. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  36. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  37. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
  38. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
  39. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_alarm_event.py +0 -0
  40. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_backoff.py +0 -0
  41. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_go2rtc.py +0 -0
  42. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_highport_nomination.py +0 -0
  43. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_lan_control.py +0 -0
  44. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_live_stream_param.py +0 -0
  45. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_motion_poll.py +0 -0
  46. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_no_undefined_names.py +0 -0
  47. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_post_merge_hardening.py +0 -0
  48. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_sdes_fast_liveplay.py +0 -0
  49. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_sdes_idle_release.py +0 -0
  50. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_sdes_sprop.py +0 -0
  51. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_sdes_talk.py +0 -0
  52. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_sdes_watchdog.py +0 -0
  53. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_serve_relay.py +0 -0
  54. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_speak.py +0 -0
  55. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_stream_cap.py +0 -0
  56. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_stream_idle.py +0 -0
  57. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_talk.py +0 -0
  58. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/tests/test_terminal_ack.py +0 -0
  59. {python_aidot_cameras-0.7.24 → python_aidot_cameras-0.7.25}/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.24
3
+ Version: 0.7.25
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.24"
7
+ version = "0.7.25"
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"
@@ -3720,7 +3720,14 @@ class CameraMixin(_CameraControlsMixin):
3720
3720
  or msg.get("devId") == device_id):
3721
3721
  loop.call_soon_threadsafe(camera_ready_ev.set)
3722
3722
  # livePlayResp: explicit camera ack/nack for start-play command.
3723
- if method == "livePlayResp" and inner.get("devId") == device_id:
3723
+ # The camera echoes our peer_id (verified live); its payload has NO
3724
+ # devId, so the old devId-only match never fired and this future never
3725
+ # resolved (the wait always timed out). Match on the echoed peer_id
3726
+ # (per-open, precise); keep devId as a fallback for any camera that
3727
+ # does send it. dstAddr is the account-wide userId - too loose to use.
3728
+ if method == "livePlayResp" and (
3729
+ inner.get("peerid") == peer_id
3730
+ or inner.get("devId") == device_id):
3724
3731
  if not liveplay_resp_fut.done():
3725
3732
  loop.call_soon_threadsafe(liveplay_resp_fut.set_result, inner)
3726
3733
  # livePlayReq echo: broker/camera confirmed delivery of our livePlayReq.
@@ -4186,9 +4193,19 @@ class CameraMixin(_CameraControlsMixin):
4186
4193
  _lp_arrived = True
4187
4194
  _lp_code = int(_lp_resp.get("code", 200))
4188
4195
  _lp_on = int(_lp_resp.get("livePlay", 1))
4189
- if _lp_code not in (0, 200) or _lp_on == 0:
4196
+ # Fast-fail only on an unambiguous refusal (livePlay=0).
4197
+ # Other non-OK codes (incl. -50019 "not ready") are
4198
+ # transient on battery cameras and recover via ICE; abort
4199
+ # there would spuriously kill otherwise-good streams.
4200
+ if _lp_on == 0:
4190
4201
  raise RuntimeError(
4191
- f"livePlay rejected by camera (code={_lp_code}, livePlay={_lp_on})"
4202
+ f"livePlay refused by camera (livePlay=0, code={_lp_code})"
4203
+ )
4204
+ elif _lp_code not in (0, 200):
4205
+ _status(
4206
+ f"livePlayResp: non-OK code {_lp_code}"
4207
+ f"{' (not ready, transient)' if _lp_code == -50019 else ''}"
4208
+ " - proceeding"
4192
4209
  )
4193
4210
  except TimeoutError:
4194
4211
  pass
@@ -4231,9 +4248,15 @@ class CameraMixin(_CameraControlsMixin):
4231
4248
  _lp_resp2 = liveplay_resp_fut.result()
4232
4249
  _lp_code2 = int(_lp_resp2.get("code", 200))
4233
4250
  _lp_on2 = int(_lp_resp2.get("livePlay", 1))
4234
- if _lp_code2 not in (0, 200) or _lp_on2 == 0:
4251
+ if _lp_on2 == 0:
4235
4252
  raise RuntimeError(
4236
- f"livePlay rejected by camera (code={_lp_code2}, livePlay={_lp_on2})"
4253
+ f"livePlay refused by camera (livePlay=0, code={_lp_code2})"
4254
+ )
4255
+ elif _lp_code2 not in (0, 200):
4256
+ _status(
4257
+ f"livePlayResp: non-OK code {_lp_code2}"
4258
+ f"{' (not ready, transient)' if _lp_code2 == -50019 else ''}"
4259
+ " - proceeding"
4237
4260
  )
4238
4261
  except RuntimeError:
4239
4262
  raise
@@ -7100,10 +7123,18 @@ class CameraMixin(_CameraControlsMixin):
7100
7123
  _lp_arrived = True
7101
7124
  _lp_code_sdes = int(_lp_resp_sdes.get("code", 200))
7102
7125
  _lp_on_sdes = int(_lp_resp_sdes.get("livePlay", 1))
7103
- if _lp_code_sdes not in (0, 200) or _lp_on_sdes == 0:
7126
+ # Only an explicit livePlay=0 is an unambiguous refusal (fast-fail).
7127
+ # Numeric codes (e.g. -50019 "not ready" on a waking battery cam)
7128
+ # are transient - the camera recovers and streams - so log and
7129
+ # proceed rather than abort on a code we can't classify as terminal
7130
+ # (genuine terminal rejects are still caught on the webrtcResp ack).
7131
+ if _lp_on_sdes == 0:
7104
7132
  raise RuntimeError(
7105
- f"livePlay rejected by camera (code={_lp_code_sdes}, livePlay={_lp_on_sdes})"
7106
- )
7133
+ f"livePlay refused by camera (livePlay=0, code={_lp_code_sdes})")
7134
+ elif _lp_code_sdes not in (0, 200):
7135
+ _status(f"livePlayResp: non-OK code {_lp_code_sdes}"
7136
+ f"{' (not ready, transient)' if _lp_code_sdes == -50019 else ''}"
7137
+ " - proceeding")
7107
7138
  except TimeoutError:
7108
7139
  pass
7109
7140
  _LOGGER.info(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.7.24
3
+ Version: 0.7.25
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