python-aidot-cameras 0.7.20__tar.gz → 0.7.22__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.7.20/src/python_aidot_cameras.egg-info → python_aidot_cameras-0.7.22}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/pyproject.toml +1 -1
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/client.py +91 -20
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22/src/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/python_aidot_cameras.egg-info/SOURCES.txt +1 -0
- python_aidot_cameras-0.7.22/tests/test_sdes_fast_liveplay.py +70 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/LICENSE +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/MANIFEST.in +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/README.md +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/setup.cfg +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/__init__.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/aes_utils.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/__init__.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/constants.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/controls.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/go2rtc.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/lan_control.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/models.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/playback.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/protocol.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/sdes.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/tutk.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/camera/webrtc.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/client.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/const.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/credentials.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/device_client.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/discover.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/exceptions.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/g711.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/login_const.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/__init__.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/device_client_model.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/device_model.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/discover_model.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/py.typed +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/python_aidot_cameras.egg-info/requires.txt +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/python_aidot_cameras.egg-info/top_level.txt +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_alarm_event.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_backoff.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_go2rtc.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_highport_nomination.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_lan_control.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_live_stream_param.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_motion_poll.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_no_undefined_names.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_post_merge_hardening.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_sdes_idle_release.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_sdes_sprop.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_sdes_talk.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_sdes_watchdog.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_serve_relay.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_speak.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_stream_cap.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_stream_idle.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_talk.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_terminal_ack.py +0 -0
- {python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/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.
|
|
3
|
+
Version: 0.7.22
|
|
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.
|
|
7
|
+
version = "0.7.22"
|
|
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"
|
|
@@ -1950,6 +1950,7 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
1950
1950
|
live_stream_param: Optional[bool] = None,
|
|
1951
1951
|
serve_relay: Optional[bool] = None,
|
|
1952
1952
|
stream_idle_s: Optional[float] = None,
|
|
1953
|
+
sdes_fast_liveplay: Optional[bool] = None,
|
|
1953
1954
|
) -> None:
|
|
1954
1955
|
"""Start a persistent stream that keeps the camera session alive.
|
|
1955
1956
|
|
|
@@ -1998,6 +1999,8 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
1998
1999
|
self._serve_relay_opt = serve_relay
|
|
1999
2000
|
if stream_idle_s is not None:
|
|
2000
2001
|
self._stream_idle_opt = stream_idle_s
|
|
2002
|
+
if sdes_fast_liveplay is not None:
|
|
2003
|
+
self._sdes_fast_liveplay_opt = sdes_fast_liveplay
|
|
2001
2004
|
if self._stream_task is not None and not self._stream_task.done():
|
|
2002
2005
|
return
|
|
2003
2006
|
self._keepalive_rtsp_url = rtsp_push_url
|
|
@@ -2528,6 +2531,18 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
2528
2531
|
except (TypeError, ValueError):
|
|
2529
2532
|
return 120.0
|
|
2530
2533
|
|
|
2534
|
+
def _resolve_sdes_fast_liveplay(self) -> bool:
|
|
2535
|
+
"""Whether to skip the ~2 s livePlayResp wait for SDES (P5, EXPERIMENTAL).
|
|
2536
|
+
|
|
2537
|
+
Per-camera ``sdes_fast_liveplay`` (set via start_keepalive) wins; else the
|
|
2538
|
+
``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)."""
|
|
2540
|
+
opt = getattr(self, "_sdes_fast_liveplay_opt", None)
|
|
2541
|
+
if opt is not None:
|
|
2542
|
+
return bool(opt)
|
|
2543
|
+
return os.environ.get("AIDOT_SDES_FAST_LIVEPLAY", "").strip().lower() in (
|
|
2544
|
+
"1", "true", "yes", "on")
|
|
2545
|
+
|
|
2531
2546
|
def _maybe_start_serve_relay(self, serve_url: Optional[str]) -> "Optional[_ServeRelay]":
|
|
2532
2547
|
"""Hold the public serve port via a _ServeRelay so an eager go2rtc pull
|
|
2533
2548
|
connects-and-waits instead of hitting ECONNREFUSED during the ~16-25s
|
|
@@ -3337,6 +3352,17 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
3337
3352
|
if self.is_sdes_camera:
|
|
3338
3353
|
_fast_connect = False
|
|
3339
3354
|
|
|
3355
|
+
# P5 EXPERIMENT (opt-in): skip ONLY the livePlayResp blocking wait (~2 s)
|
|
3356
|
+
# for SDES, while keeping the full ICE/TURN/SCTP handshake. Rationale: the
|
|
3357
|
+
# SDES instability that forces _fast_connect off comes from skipping the
|
|
3358
|
+
# ICE/TURN waits + stripping TURN (under-arming SCTP) - NOT from skipping
|
|
3359
|
+
# the livePlayResp ack, which is purely a camera accept/reject we don't
|
|
3360
|
+
# need to block on (the official app never waits for it). So this targeted
|
|
3361
|
+
# skip is expected to be SCTP-safe and shave ~2 s off the SDES cold start.
|
|
3362
|
+
# Off by default, pending live validation. Applied in _open_sdes_stream
|
|
3363
|
+
# (the SDES path has its own livePlayResp wait); start_keepalive(
|
|
3364
|
+
# sdes_fast_liveplay=...) wins, else AIDOT_SDES_FAST_LIVEPLAY env.
|
|
3365
|
+
|
|
3340
3366
|
# Wake battery cameras via the cloud HTTP low-power endpoint before the
|
|
3341
3367
|
# handshake (matches the app, which fires the HTTP wake so a sleeping camera
|
|
3342
3368
|
# gets the signal even with no live MQTT session; the MQTT
|
|
@@ -4123,11 +4149,25 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
4123
4149
|
# (parity-confirmed). AIDOT_FAST_CONNECT skips it and proceeds to
|
|
4124
4150
|
# SDP/ICE immediately - losing fast-fail on rejection (rare; ICE then
|
|
4125
4151
|
# fails instead) in exchange for ~2 s off every LAN connect.
|
|
4126
|
-
if
|
|
4152
|
+
if _fast_connect:
|
|
4153
|
+
_LOGGER.info(
|
|
4154
|
+
"signaling-wait[%s] livePlayResp skipped (fast_connect)",
|
|
4155
|
+
self.device_id)
|
|
4156
|
+
_status(
|
|
4157
|
+
"AIDOT_FAST_CONNECT: skipping livePlayResp wait (~2s) -"
|
|
4158
|
+
" proceeding to SDP/ICE (app-parity, no fast-fail on reject)"
|
|
4159
|
+
)
|
|
4160
|
+
else:
|
|
4161
|
+
# Instrumented: how long this wait actually costs (it returns as
|
|
4162
|
+
# soon as livePlayResp arrives; the 2s is only paid on timeout).
|
|
4163
|
+
# This is exactly the cost the sdes_fast_liveplay experiment skips.
|
|
4164
|
+
_lp_t0 = time.monotonic()
|
|
4165
|
+
_lp_arrived = False
|
|
4127
4166
|
try:
|
|
4128
4167
|
_lp_resp = await asyncio.wait_for(
|
|
4129
4168
|
asyncio.shield(liveplay_resp_fut), timeout=2.0
|
|
4130
4169
|
)
|
|
4170
|
+
_lp_arrived = True
|
|
4131
4171
|
_lp_code = int(_lp_resp.get("code", 200))
|
|
4132
4172
|
_lp_on = int(_lp_resp.get("livePlay", 1))
|
|
4133
4173
|
if _lp_code not in (0, 200) or _lp_on == 0:
|
|
@@ -4136,11 +4176,10 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
4136
4176
|
)
|
|
4137
4177
|
except TimeoutError:
|
|
4138
4178
|
pass
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
)
|
|
4179
|
+
_LOGGER.info(
|
|
4180
|
+
"signaling-wait[%s] livePlayResp elapsed=%dms arrived=%s",
|
|
4181
|
+
self.device_id,
|
|
4182
|
+
int((time.monotonic() - _lp_t0) * 1000), _lp_arrived)
|
|
4144
4183
|
# Short extra wait for getIceConfigResp - the server may only respond
|
|
4145
4184
|
# once a live camera session is active (i.e. after livePlayReq).
|
|
4146
4185
|
# Waiting here ensures TURN credentials arrive before RTCPeerConnection
|
|
@@ -4152,11 +4191,18 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
4152
4191
|
# per-session TURN relay credentials, which LAN-direct doesn't need;
|
|
4153
4192
|
# remote/strict-NAT cameras do, hence this is opt-in (see flag above).
|
|
4154
4193
|
if not ice_config_fut.done() and not _fast_connect:
|
|
4194
|
+
_ic_t0 = time.monotonic()
|
|
4195
|
+
_ic_arrived = False
|
|
4155
4196
|
try:
|
|
4156
4197
|
await asyncio.wait_for(asyncio.shield(ice_config_fut), timeout=3.0)
|
|
4198
|
+
_ic_arrived = True
|
|
4157
4199
|
_status("getIceConfigResp received (post-livePlayReq)")
|
|
4158
4200
|
except TimeoutError:
|
|
4159
4201
|
pass # proceed without TURN; synthetic candidates are fallback
|
|
4202
|
+
_LOGGER.info(
|
|
4203
|
+
"signaling-wait[%s] getIceConfigResp elapsed=%dms arrived=%s",
|
|
4204
|
+
self.device_id,
|
|
4205
|
+
int((time.monotonic() - _ic_t0) * 1000), _ic_arrived)
|
|
4160
4206
|
elif _fast_connect:
|
|
4161
4207
|
_status(
|
|
4162
4208
|
"AIDOT_FAST_CONNECT: skipping getIceConfigResp wait"
|
|
@@ -7001,24 +7047,49 @@ class CameraMixin(_CameraControlsMixin):
|
|
|
7001
7047
|
# webrtcReq. The echo confirms the MQTT pipeline to this device is live
|
|
7002
7048
|
# and the broker session is registered. Fall through after 5 s if it
|
|
7003
7049
|
# 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
|
|
7051
|
+
# the echo and livePlayResp waits BOTH always time out for the SDES cameras
|
|
7052
|
+
# measured (echo/resp never arrive) yet streaming succeeds - i.e. ~6 s of
|
|
7053
|
+
# dead padding. When the flag is on, cap the echo wait short and skip the
|
|
7054
|
+
# livePlayResp wait; the full ICE/TURN/SCTP handshake is untouched. This
|
|
7055
|
+
# is the SDES path's OWN livePlay waits (the DTLS gate above never runs for
|
|
7056
|
+
# SDES: use_sdes is True there).
|
|
7057
|
+
_skip_lp = self._resolve_sdes_fast_liveplay()
|
|
7058
|
+
_echo_timeout = 1.5 if _skip_lp else 5.0
|
|
7059
|
+
_echo_t0 = time.monotonic()
|
|
7004
7060
|
try:
|
|
7005
|
-
await _asyncio.wait_for(liveplay_echo_ev.wait(), timeout=
|
|
7061
|
+
await _asyncio.wait_for(liveplay_echo_ev.wait(), timeout=_echo_timeout)
|
|
7006
7062
|
_status("livePlayReq echo received - sending webrtcReq, ICE, then launching ffmpeg")
|
|
7007
7063
|
except TimeoutError:
|
|
7008
|
-
_status("no livePlayReq echo in
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
|
|
7012
|
-
|
|
7013
|
-
|
|
7014
|
-
|
|
7015
|
-
|
|
7016
|
-
|
|
7017
|
-
|
|
7018
|
-
|
|
7064
|
+
_status(f"no livePlayReq echo in {_echo_timeout:.1f}s - sending webrtcReq,"
|
|
7065
|
+
" ICE, then launching ffmpeg anyway")
|
|
7066
|
+
_LOGGER.info(
|
|
7067
|
+
"signaling-wait[%s] livePlayReq-echo elapsed=%dms (timeout=%.1fs)",
|
|
7068
|
+
self.device_id, int((time.monotonic() - _echo_t0) * 1000), _echo_timeout)
|
|
7069
|
+
# livePlayResp: explicit camera accept/reject before SDP/ICE.
|
|
7070
|
+
if _skip_lp:
|
|
7071
|
+
_LOGGER.info(
|
|
7072
|
+
"signaling-wait[%s] livePlayResp skipped (sdes_fast_liveplay)",
|
|
7073
|
+
self.device_id)
|
|
7074
|
+
else:
|
|
7075
|
+
_lp_t0 = time.monotonic()
|
|
7076
|
+
_lp_arrived = False
|
|
7077
|
+
try:
|
|
7078
|
+
_lp_resp_sdes = await _asyncio.wait_for(
|
|
7079
|
+
_asyncio.shield(liveplay_resp_fut), timeout=1.0
|
|
7019
7080
|
)
|
|
7020
|
-
|
|
7021
|
-
|
|
7081
|
+
_lp_arrived = True
|
|
7082
|
+
_lp_code_sdes = int(_lp_resp_sdes.get("code", 200))
|
|
7083
|
+
_lp_on_sdes = int(_lp_resp_sdes.get("livePlay", 1))
|
|
7084
|
+
if _lp_code_sdes not in (0, 200) or _lp_on_sdes == 0:
|
|
7085
|
+
raise RuntimeError(
|
|
7086
|
+
f"livePlay rejected by camera (code={_lp_code_sdes}, livePlay={_lp_on_sdes})"
|
|
7087
|
+
)
|
|
7088
|
+
except TimeoutError:
|
|
7089
|
+
pass
|
|
7090
|
+
_LOGGER.info(
|
|
7091
|
+
"signaling-wait[%s] livePlayResp elapsed=%dms arrived=%s",
|
|
7092
|
+
self.device_id, int((time.monotonic() - _lp_t0) * 1000), _lp_arrived)
|
|
7022
7093
|
|
|
7023
7094
|
# --- Build local-receiver SDP for ffmpeg ----------------------------- #
|
|
7024
7095
|
# Built BEFORE sending webrtcReq so ffmpeg is already listening on the
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-aidot-cameras
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.22
|
|
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,70 @@
|
|
|
1
|
+
"""Unit tests for _resolve_sdes_fast_liveplay - the P5 flag (EXPERIMENTAL).
|
|
2
|
+
|
|
3
|
+
P5 skips only the ~2s livePlayResp wait for SDES cameras. This locks the
|
|
4
|
+
opt/env precedence (per-camera kwarg wins over AIDOT_SDES_FAST_LIVEPLAY env,
|
|
5
|
+
default off) so the wiring is verifiable without a camera. The actual stability
|
|
6
|
+
effect is validated by real-world soak (see scripts/sdes_soak_monitor.py), not
|
|
7
|
+
here.
|
|
8
|
+
"""
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "src"))
|
|
13
|
+
|
|
14
|
+
import aidot.camera.client as cc
|
|
15
|
+
|
|
16
|
+
_CAM = next(v for v in vars(cc).values()
|
|
17
|
+
if isinstance(v, type) and "_resolve_sdes_fast_liveplay" in v.__dict__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _cam():
|
|
21
|
+
return _CAM.__new__(_CAM)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_default_off(monkeypatch):
|
|
25
|
+
monkeypatch.delenv("AIDOT_SDES_FAST_LIVEPLAY", raising=False)
|
|
26
|
+
assert _cam()._resolve_sdes_fast_liveplay() is False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_env_truthy_values(monkeypatch):
|
|
30
|
+
for val in ("1", "true", "TRUE", "yes", "on", " On "):
|
|
31
|
+
monkeypatch.setenv("AIDOT_SDES_FAST_LIVEPLAY", val)
|
|
32
|
+
assert _cam()._resolve_sdes_fast_liveplay() is True, val
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_env_falsey_values(monkeypatch):
|
|
36
|
+
for val in ("0", "false", "no", "off", ""):
|
|
37
|
+
monkeypatch.setenv("AIDOT_SDES_FAST_LIVEPLAY", val)
|
|
38
|
+
assert _cam()._resolve_sdes_fast_liveplay() is False, val
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_kwarg_option_wins_over_env(monkeypatch):
|
|
42
|
+
monkeypatch.setenv("AIDOT_SDES_FAST_LIVEPLAY", "1")
|
|
43
|
+
cam = _cam()
|
|
44
|
+
cam._sdes_fast_liveplay_opt = False # start_keepalive(sdes_fast_liveplay=False)
|
|
45
|
+
assert cam._resolve_sdes_fast_liveplay() is False
|
|
46
|
+
|
|
47
|
+
cam2 = _cam()
|
|
48
|
+
monkeypatch.delenv("AIDOT_SDES_FAST_LIVEPLAY", raising=False)
|
|
49
|
+
cam2._sdes_fast_liveplay_opt = True
|
|
50
|
+
assert cam2._resolve_sdes_fast_liveplay() is True
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
import traceback
|
|
55
|
+
|
|
56
|
+
class _MP:
|
|
57
|
+
def setenv(self, k, v): os.environ[k] = v
|
|
58
|
+
def delenv(self, k, raising=False): os.environ.pop(k, None)
|
|
59
|
+
|
|
60
|
+
_fail = 0
|
|
61
|
+
for _k, _v in sorted(globals().items()):
|
|
62
|
+
if _k.startswith("test_"):
|
|
63
|
+
try:
|
|
64
|
+
_v(_MP()) if _v.__code__.co_argcount else _v()
|
|
65
|
+
print(f"PASS {_k}")
|
|
66
|
+
except Exception:
|
|
67
|
+
_fail += 1
|
|
68
|
+
print(f"FAIL {_k}")
|
|
69
|
+
traceback.print_exc()
|
|
70
|
+
raise SystemExit(1 if _fail else 0)
|
|
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.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/device_client_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/device_model.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/src/aidot/models/discover_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
|
{python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_highport_nomination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_no_undefined_names.py
RENAMED
|
File without changes
|
{python_aidot_cameras-0.7.20 → python_aidot_cameras-0.7.22}/tests/test_post_merge_hardening.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
|