python-aidot-cameras 0.11.6__tar.gz → 0.11.8__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.
- {python_aidot_cameras-0.11.6/python_aidot_cameras.egg-info → python_aidot_cameras-0.11.8}/PKG-INFO +1 -1
- python_aidot_cameras-0.11.8/aidot/__init__.py +46 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/client.py +17 -4
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/sdes_open.py +6 -3
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/pyproject.toml +1 -1
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/python_aidot_cameras.egg-info/SOURCES.txt +2 -0
- python_aidot_cameras-0.11.8/tests/test_logging_caps.py +22 -0
- python_aidot_cameras-0.11.8/tests/test_open_fail_logger.py +29 -0
- python_aidot_cameras-0.11.6/aidot/__init__.py +0 -33
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/LICENSE +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/MANIFEST.in +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/README.md +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/__main__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/clock.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/base.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/g711.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/g722.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/h264.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/opus.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/vpx.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/contrib/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/contrib/media.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/contrib/signaling.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/events.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/exceptions.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/jitterbuffer.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/mediastreams.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rate.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcconfiguration.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcdatachannel.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcdtlstransport.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcicetransport.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcpeerconnection.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpparameters.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpreceiver.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpsender.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtptransceiver.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcsctptransport.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcsessiondescription.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtp.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/sdp.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/stats.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/utils.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/aes_utils.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/constants.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/controls.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/go2rtc.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/lan_control.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/models.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/playback.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/protocol.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/sdes.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/tutk.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/webrtc.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/camera/webrtc_open.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/client.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/const.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/credentials.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/device_client.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/discover.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/exceptions.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/g711.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/login_const.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/models/__init__.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/models/device_client_model.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/models/device_model.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/models/discover_model.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/py.typed +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/python_aidot_cameras.egg-info/entry_points.txt +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/python_aidot_cameras.egg-info/requires.txt +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/python_aidot_cameras.egg-info/top_level.txt +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/setup.cfg +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_aioice_compat.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_alarm_event.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_backoff.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_deferred_hardening.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_device_login_guard.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_device_user_info_cache.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_dtls_not_ready_burst.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_dtls_pinning.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_dtls_skip_signaling_wait.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_egress_guard.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_go2rtc.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_go2rtc_cli.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_highport_nomination.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_ice_config_cache.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_keepalive_renew.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_keyframe_prompter.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_lan_control.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_live_stream_param.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_motion_poll.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_mqtt_session_reconnect.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_narrow_pc_ice.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_no_undefined_names.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_offline_keepalive_pause.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_open_gate_delay.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_persistent_mqtt.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_persistent_mqtt_robustness.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_playback_tls.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_post_merge_hardening.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_retry_policy.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_adaptive.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_echo_wait_timeout.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_fast_liveplay.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_idle_release.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_open_cleanup.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_serve_audio.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_serve_cmd.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_sprop.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_talk.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_watchdog.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_security_hardening.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_serializable_login_info.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_serve_relay.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_session_stats.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_speak.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_stream_cap.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_stream_drain_ownership.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_stream_idle.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_stream_teardown.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_talk.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_terminal_ack.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_token_file_robustness.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_token_refresh.py +0 -0
- {python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_wait_or_event.py +0 -0
{python_aidot_cameras-0.11.6/python_aidot_cameras.egg-info → python_aidot_cameras-0.11.8}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.8
|
|
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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""AiDot camera and device library."""
|
|
2
|
+
|
|
3
|
+
import logging as _logging
|
|
4
|
+
|
|
5
|
+
from .client import AidotClient
|
|
6
|
+
from .device_client import DeviceClient
|
|
7
|
+
from .discover import Discover
|
|
8
|
+
from .exceptions import (
|
|
9
|
+
AidotAuthFailed,
|
|
10
|
+
AidotAuthTokenExpired,
|
|
11
|
+
AidotCameraBusy,
|
|
12
|
+
AidotError,
|
|
13
|
+
AidotNotLogin,
|
|
14
|
+
AidotOSError,
|
|
15
|
+
AidotUserOrPassIncorrect,
|
|
16
|
+
HTTPError,
|
|
17
|
+
InvalidHost,
|
|
18
|
+
InvalidURL,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# The vendored aiortc RTP receiver/sender log EVERY media packet at DEBUG. When a
|
|
22
|
+
# user enables DEBUG on the parent ``aidot`` logger to diagnose the integration,
|
|
23
|
+
# that becomes thousands of lines per second and floods the logs (in one capture,
|
|
24
|
+
# 99% of all lines). Cap just those two per-packet loggers at INFO so enabling
|
|
25
|
+
# ``aidot`` DEBUG stays useful - the diagnostically valuable aiortc DEBUG (DTLS,
|
|
26
|
+
# ICE, SCTP/DCEP) still flows. Respect an explicit level if the user set one.
|
|
27
|
+
for _chatty in ("aidot._vendor.aiortc.rtcrtpreceiver", "aidot._vendor.aiortc.rtcrtpsender"):
|
|
28
|
+
_lg = _logging.getLogger(_chatty)
|
|
29
|
+
if _lg.level == _logging.NOTSET:
|
|
30
|
+
_lg.setLevel(_logging.INFO)
|
|
31
|
+
|
|
32
|
+
__all__ = [
|
|
33
|
+
"AidotAuthFailed",
|
|
34
|
+
"AidotAuthTokenExpired",
|
|
35
|
+
"AidotCameraBusy",
|
|
36
|
+
"AidotClient",
|
|
37
|
+
"AidotError",
|
|
38
|
+
"AidotNotLogin",
|
|
39
|
+
"AidotOSError",
|
|
40
|
+
"AidotUserOrPassIncorrect",
|
|
41
|
+
"DeviceClient",
|
|
42
|
+
"Discover",
|
|
43
|
+
"HTTPError",
|
|
44
|
+
"InvalidHost",
|
|
45
|
+
"InvalidURL",
|
|
46
|
+
]
|
|
@@ -668,7 +668,10 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
668
668
|
# as the octets, e.g. "49.57.50.46" == ASCII of "192.").
|
|
669
669
|
_ip_str = str(_dev_ip_init)
|
|
670
670
|
if _ip_looks_ascii_garbled(_ip_str):
|
|
671
|
-
|
|
671
|
+
# Benign, handled cloud quirk (not actionable by the user): the
|
|
672
|
+
# camera's LAN IP comes from WebRTC signaling, not this field.
|
|
673
|
+
# Debug, not warning, so it does not read as a problem in the log.
|
|
674
|
+
_LOGGER.debug(
|
|
672
675
|
"DeviceClient %s: ignoring ASCII-encoded IP %r from device dict "
|
|
673
676
|
"(cloud stored IP bytes as ASCII chars; real IP unknown)",
|
|
674
677
|
device.get("id") or device.get("devId"), _ip_str,
|
|
@@ -789,6 +792,16 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
789
792
|
self._cloud_online_explicit = True
|
|
790
793
|
return self.status
|
|
791
794
|
|
|
795
|
+
def _open_fail_logger(self):
|
|
796
|
+
"""Pick the log level for a stream-open failure in the serve/keepalive
|
|
797
|
+
loops: WARNING for a genuine failure, but DEBUG when the cloud has
|
|
798
|
+
explicitly reported the device offline. A dead/unpowered camera is
|
|
799
|
+
already throttled to ~probe cadence by _backoff_or_offline_pause, so its
|
|
800
|
+
expected open failures should not drip WARNINGs into the log every probe.
|
|
801
|
+
"""
|
|
802
|
+
_offline = (not self.status.online) and getattr(self, "_cloud_online_explicit", False)
|
|
803
|
+
return _LOGGER.debug if _offline else _LOGGER.warning
|
|
804
|
+
|
|
792
805
|
async def _backoff_or_offline_pause(self, delay: float) -> None:
|
|
793
806
|
"""Sleep a reconnect backoff, extended while the device is cloud-offline.
|
|
794
807
|
|
|
@@ -2729,7 +2742,7 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
2729
2742
|
"falling back to full relay path", self.device_id,
|
|
2730
2743
|
_FAST_OPEN_TIMEOUT)
|
|
2731
2744
|
_delay = _pacer.fail_delay()
|
|
2732
|
-
|
|
2745
|
+
self._open_fail_logger()(
|
|
2733
2746
|
"SDES keepalive: stream open failed for %s (retry in %.0fs): %s",
|
|
2734
2747
|
self.device_id, _delay, exc,
|
|
2735
2748
|
)
|
|
@@ -2905,7 +2918,7 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
2905
2918
|
continue
|
|
2906
2919
|
except Exception as exc:
|
|
2907
2920
|
_delay = _pacer.fail_delay()
|
|
2908
|
-
|
|
2921
|
+
self._open_fail_logger()(
|
|
2909
2922
|
"Stream open failed for %s (retry in %.0fs): %s",
|
|
2910
2923
|
self.device_id, _delay, exc,
|
|
2911
2924
|
)
|
|
@@ -3406,7 +3419,7 @@ class CameraMixin(_CameraControlsMixin, _WebRTCOpenMixin, _SdesOpenMixin):
|
|
|
3406
3419
|
continue
|
|
3407
3420
|
except Exception as exc:
|
|
3408
3421
|
_delay = _pacer.fail_delay()
|
|
3409
|
-
|
|
3422
|
+
self._open_fail_logger()(
|
|
3410
3423
|
"DTLS serve: open failed for %s (retry %.0fs): %s",
|
|
3411
3424
|
self.device_id, _delay, exc,
|
|
3412
3425
|
)
|
|
@@ -790,7 +790,10 @@ class _SdesOpenMixin:
|
|
|
790
790
|
)
|
|
791
791
|
|
|
792
792
|
sdp_path = await asyncio.get_running_loop().run_in_executor(
|
|
793
|
-
|
|
793
|
+
# _inject_sprop reads the sprop cache from disk; keep it inside the
|
|
794
|
+
# executor (not as an eagerly-evaluated arg) so the blocking open()
|
|
795
|
+
# does not run on the event loop.
|
|
796
|
+
None, lambda: _make_sdp_tempfile(_inject_sprop(ffmpeg_sdp, self.device_id)))
|
|
794
797
|
_cl(os.unlink, sdp_path) # released with the sockets on a cancelled open
|
|
795
798
|
|
|
796
799
|
# --- Send webrtcReq BEFORE releasing reservation sockets ------------- #
|
|
@@ -1772,7 +1775,7 @@ class _SdesOpenMixin:
|
|
|
1772
1775
|
)
|
|
1773
1776
|
try:
|
|
1774
1777
|
await asyncio.get_running_loop().run_in_executor(
|
|
1775
|
-
None, _write_text_file
|
|
1778
|
+
None, lambda: _write_text_file(sdp_path, _inject_sprop(_updated_sdp, self.device_id)))
|
|
1776
1779
|
except Exception as _sdp_exc:
|
|
1777
1780
|
_LOGGER.warning("_open_sdes_stream: could not rewrite SDP: %s", _sdp_exc)
|
|
1778
1781
|
|
|
@@ -2070,7 +2073,7 @@ class _SdesOpenMixin:
|
|
|
2070
2073
|
)
|
|
2071
2074
|
try:
|
|
2072
2075
|
await asyncio.get_running_loop().run_in_executor(
|
|
2073
|
-
None, _write_text_file
|
|
2076
|
+
None, lambda: _write_text_file(sdp_path, _inject_sprop(_br_sdp, self.device_id)))
|
|
2074
2077
|
except Exception as _br_sdp_exc:
|
|
2075
2078
|
_LOGGER.warning("bridge: could not rewrite SDP: %s", _br_sdp_exc)
|
|
2076
2079
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "python-aidot-cameras"
|
|
7
|
-
version = "0.11.
|
|
7
|
+
version = "0.11.8"
|
|
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"
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8/python_aidot_cameras.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.8
|
|
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
|
|
@@ -89,11 +89,13 @@ tests/test_keepalive_renew.py
|
|
|
89
89
|
tests/test_keyframe_prompter.py
|
|
90
90
|
tests/test_lan_control.py
|
|
91
91
|
tests/test_live_stream_param.py
|
|
92
|
+
tests/test_logging_caps.py
|
|
92
93
|
tests/test_motion_poll.py
|
|
93
94
|
tests/test_mqtt_session_reconnect.py
|
|
94
95
|
tests/test_narrow_pc_ice.py
|
|
95
96
|
tests/test_no_undefined_names.py
|
|
96
97
|
tests/test_offline_keepalive_pause.py
|
|
98
|
+
tests/test_open_fail_logger.py
|
|
97
99
|
tests/test_open_gate_delay.py
|
|
98
100
|
tests/test_persistent_mqtt.py
|
|
99
101
|
tests/test_persistent_mqtt_robustness.py
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Importing the library caps the vendored aiortc per-packet loggers.
|
|
2
|
+
|
|
3
|
+
aiortc's RTP receiver/sender log every media packet at DEBUG. Enabling DEBUG on
|
|
4
|
+
the parent ``aidot`` logger (the normal way to diagnose the integration) would
|
|
5
|
+
otherwise unleash thousands of lines per second. The package init caps just those
|
|
6
|
+
two loggers at INFO so DEBUG on ``aidot`` stays useful without the firehose.
|
|
7
|
+
"""
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
import aidot # noqa: F401 - import triggers the logger caps
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_vendored_aiortc_packet_loggers_capped_to_info():
|
|
14
|
+
for name in (
|
|
15
|
+
"aidot._vendor.aiortc.rtcrtpreceiver",
|
|
16
|
+
"aidot._vendor.aiortc.rtcrtpsender",
|
|
17
|
+
):
|
|
18
|
+
lg = logging.getLogger(name)
|
|
19
|
+
assert lg.level == logging.INFO, f"{name} not capped (level={lg.level})"
|
|
20
|
+
# Even with the parent 'aidot' logger at DEBUG, the per-packet DEBUG is off.
|
|
21
|
+
logging.getLogger("aidot").setLevel(logging.DEBUG)
|
|
22
|
+
assert not lg.isEnabledFor(logging.DEBUG), f"{name} still emits DEBUG"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Serve/keepalive open-failure logging level.
|
|
2
|
+
|
|
3
|
+
A stream-open failure logs at WARNING normally, but at DEBUG when the cloud has
|
|
4
|
+
explicitly reported the device offline - a dead/unpowered camera is throttled to
|
|
5
|
+
probe cadence by the offline pause and should not drip WARNINGs every probe.
|
|
6
|
+
"""
|
|
7
|
+
import types
|
|
8
|
+
|
|
9
|
+
from aidot.camera import client as camclient
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _dc(online, explicit):
|
|
13
|
+
o = types.SimpleNamespace()
|
|
14
|
+
o.status = types.SimpleNamespace(online=online)
|
|
15
|
+
o._cloud_online_explicit = explicit
|
|
16
|
+
return camclient.CameraMixin._open_fail_logger.__get__(o)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_debug_when_cloud_reports_offline():
|
|
20
|
+
assert _dc(online=False, explicit=True)() == camclient._LOGGER.debug
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_warning_when_online():
|
|
24
|
+
assert _dc(online=True, explicit=True)() == camclient._LOGGER.warning
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def test_warning_when_online_state_unknown():
|
|
28
|
+
# Never explicitly reported offline -> treat a failure as genuine (WARNING).
|
|
29
|
+
assert _dc(online=False, explicit=False)() == camclient._LOGGER.warning
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"""AiDot camera and device library."""
|
|
2
|
-
|
|
3
|
-
from .client import AidotClient
|
|
4
|
-
from .device_client import DeviceClient
|
|
5
|
-
from .discover import Discover
|
|
6
|
-
from .exceptions import (
|
|
7
|
-
AidotAuthFailed,
|
|
8
|
-
AidotAuthTokenExpired,
|
|
9
|
-
AidotCameraBusy,
|
|
10
|
-
AidotError,
|
|
11
|
-
AidotNotLogin,
|
|
12
|
-
AidotOSError,
|
|
13
|
-
AidotUserOrPassIncorrect,
|
|
14
|
-
HTTPError,
|
|
15
|
-
InvalidHost,
|
|
16
|
-
InvalidURL,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
__all__ = [
|
|
20
|
-
"AidotAuthFailed",
|
|
21
|
-
"AidotAuthTokenExpired",
|
|
22
|
-
"AidotCameraBusy",
|
|
23
|
-
"AidotClient",
|
|
24
|
-
"AidotError",
|
|
25
|
-
"AidotNotLogin",
|
|
26
|
-
"AidotOSError",
|
|
27
|
-
"AidotUserOrPassIncorrect",
|
|
28
|
-
"DeviceClient",
|
|
29
|
-
"Discover",
|
|
30
|
-
"HTTPError",
|
|
31
|
-
"InvalidHost",
|
|
32
|
-
"InvalidURL",
|
|
33
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/__init__.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/base.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/g711.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/g722.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/h264.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/opus.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/codecs/vpx.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/contrib/__init__.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/contrib/media.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/exceptions.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/jitterbuffer.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/mediastreams.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcconfiguration.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcdatachannel.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcdtlstransport.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcicetransport.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpparameters.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpreceiver.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcrtpsender.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/_vendor/aiortc/rtcsctptransport.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/aidot/models/device_client_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_deferred_hardening.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_device_login_guard.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_device_user_info_cache.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_dtls_not_ready_burst.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_dtls_skip_signaling_wait.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_highport_nomination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_mqtt_session_reconnect.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_no_undefined_names.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_offline_keepalive_pause.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_persistent_mqtt_robustness.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_post_merge_hardening.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_echo_wait_timeout.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_sdes_fast_liveplay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_security_hardening.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_serializable_login_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_stream_drain_ownership.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.11.6 → python_aidot_cameras-0.11.8}/tests/test_token_file_robustness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|