python-aidot-cameras 0.7.30__tar.gz → 0.7.31__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 (61) hide show
  1. {python_aidot_cameras-0.7.30/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.31}/PKG-INFO +1 -1
  2. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/pyproject.toml +1 -1
  3. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/sdes.py +5 -0
  4. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/webrtc.py +17 -0
  5. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  6. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/LICENSE +0 -0
  7. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/MANIFEST.in +0 -0
  8. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/README.md +0 -0
  9. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/setup.cfg +0 -0
  10. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/__init__.py +0 -0
  11. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/aes_utils.py +0 -0
  12. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/__init__.py +0 -0
  13. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/client.py +0 -0
  14. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/constants.py +0 -0
  15. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/controls.py +0 -0
  16. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/go2rtc.py +0 -0
  17. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/lan_control.py +0 -0
  18. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/models.py +0 -0
  19. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/playback.py +0 -0
  20. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/protocol.py +0 -0
  21. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/camera/tutk.py +0 -0
  22. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/client.py +0 -0
  23. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/const.py +0 -0
  24. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/credentials.py +0 -0
  25. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/device_client.py +0 -0
  26. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/discover.py +0 -0
  27. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/exceptions.py +0 -0
  28. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/g711.py +0 -0
  29. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/login_const.py +0 -0
  30. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/models/__init__.py +0 -0
  31. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/models/device_client_model.py +0 -0
  32. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/models/device_model.py +0 -0
  33. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/models/discover_model.py +0 -0
  34. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/aidot/py.typed +0 -0
  35. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/python_aidot_cameras.egg-info/SOURCES.txt +0 -0
  36. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  37. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
  38. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
  39. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_alarm_event.py +0 -0
  40. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_backoff.py +0 -0
  41. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_go2rtc.py +0 -0
  42. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_highport_nomination.py +0 -0
  43. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_lan_control.py +0 -0
  44. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_live_stream_param.py +0 -0
  45. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_motion_poll.py +0 -0
  46. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_no_undefined_names.py +0 -0
  47. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_persistent_mqtt.py +0 -0
  48. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_post_merge_hardening.py +0 -0
  49. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_adaptive.py +0 -0
  50. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_fast_liveplay.py +0 -0
  51. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_idle_release.py +0 -0
  52. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_sprop.py +0 -0
  53. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_talk.py +0 -0
  54. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_sdes_watchdog.py +0 -0
  55. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_serve_relay.py +0 -0
  56. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_speak.py +0 -0
  57. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_stream_cap.py +0 -0
  58. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_stream_idle.py +0 -0
  59. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_talk.py +0 -0
  60. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/tests/test_terminal_ack.py +0 -0
  61. {python_aidot_cameras-0.7.30 → python_aidot_cameras-0.7.31}/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.30
3
+ Version: 0.7.31
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.30"
7
+ version = "0.7.31"
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"
@@ -173,6 +173,11 @@ class SdesSession:
173
173
  if not self._talk_state.get("speaker_on"):
174
174
  break
175
175
  await asyncio.sleep(0.02)
176
+ # speaker_on flips once the bridge SENDS SPEAKERSTOP(849); give the
177
+ # camera a brief window to PROCESS it over the still-live SCTP before
178
+ # we tear down, so its talk channel is actually freed (avoids the
179
+ # next session getting 851 "mic occupied").
180
+ await asyncio.sleep(0.3)
176
181
  self._talk_state["stop"] = True
177
182
  self._talk_state["provider"] = None
178
183
  self._proc.terminate()
@@ -91,6 +91,7 @@ class WebRTCSession:
91
91
  return False
92
92
  # IOTYPE_USER_IPCAM_SPEAKERSTART = 848 (AVIOCTRLDEFs.java), 8-byte channel=0 payload.
93
93
  self._avio_cmd(848, b"\x00" * 8)
94
+ self._talk_holder["was_active"] = True # ensure stop() releases the speaker
94
95
  return True
95
96
 
96
97
  async def async_stop_talk(self) -> bool:
@@ -111,6 +112,22 @@ class WebRTCSession:
111
112
 
112
113
  async def stop(self) -> None:
113
114
  """Tear down the stream: close peer connection and MQTT session."""
115
+ # If two-way talk was active this session, RELEASE the camera speaker
116
+ # before closing the PeerConnection: send SPEAKERSTOP(849), idle the track,
117
+ # and give the SCTP DataChannel a brief flush window so the camera actually
118
+ # processes the release. Otherwise the camera keeps its talk channel bound
119
+ # to this (now-dead) connection and the next app/HA push-to-talk gets 851
120
+ # "mic occupied". Idempotent (harmless if the speaker was already closed).
121
+ if self.talk_supported and self._talk_holder.get("was_active"):
122
+ try:
123
+ self._avio_cmd(849, b"\x00" * 8)
124
+ if self._audio_sender is not None:
125
+ self._audio_sender.replaceTrack(None)
126
+ self._talk_holder["provider"] = None
127
+ self._talk_holder["was_active"] = False
128
+ await asyncio.sleep(0.4) # let the DataChannel deliver SPEAKERSTOP
129
+ except Exception:
130
+ _LOGGER.debug("camera %s: swallowed exception", 'stop', exc_info=True)
114
131
  for task in self._track_tasks:
115
132
  task.cancel()
116
133
  if self._recorder is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 0.7.30
3
+ Version: 0.7.31
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