Compare commits
No commits in common. "8b5dc220ad761eb18c74441ae7d29bfa22183784" and "fc4c2d22674ea24c3274d8072a54e6c370023020" have entirely different histories.
8b5dc220ad
...
fc4c2d2267
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1642,7 +1642,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -1676,7 +1676,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1688,7 +1688,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -472,52 +472,3 @@ async fn runtime_probe_video_packets_change_across_a_pulse_boundary() {
|
|||||||
"expected decoded pulse frame to be much brighter than decoded dark frame, got dark={dark_mean} pulse={pulse_mean}"
|
"expected decoded pulse frame to be much brighter than decoded dark frame, got dark={dark_mean} pulse={pulse_mean}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(coverage))]
|
|
||||||
#[tokio::test]
|
|
||||||
async fn runtime_probe_dark_video_packets_do_not_alternate_frame_to_frame() {
|
|
||||||
let capture = SyncProbeCapture::new(
|
|
||||||
CameraConfig {
|
|
||||||
codec: CameraCodec::Mjpeg,
|
|
||||||
width: 640,
|
|
||||||
height: 480,
|
|
||||||
fps: 20,
|
|
||||||
},
|
|
||||||
PulseSchedule::new(
|
|
||||||
Duration::from_secs(4),
|
|
||||||
Duration::from_secs(1),
|
|
||||||
Duration::from_millis(120),
|
|
||||||
5,
|
|
||||||
),
|
|
||||||
Duration::from_secs(3),
|
|
||||||
)
|
|
||||||
.expect("runtime capture");
|
|
||||||
|
|
||||||
let video_queue = capture.video_queue();
|
|
||||||
let mut dark_means = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let next = video_queue.pop_fresh().await;
|
|
||||||
let Some(packet) = next.packet else {
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
if packet.pts >= 1_000_000 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dark_means.push(decode_mjpeg_packet_mean_luma(&packet));
|
|
||||||
if dark_means.len() >= 8 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
dark_means.len() >= 4,
|
|
||||||
"expected several dark packets before the first pulse, got {dark_means:?}"
|
|
||||||
);
|
|
||||||
let min = *dark_means.iter().min().expect("dark min");
|
|
||||||
let max = *dark_means.iter().max().expect("dark max");
|
|
||||||
assert!(
|
|
||||||
max.saturating_sub(min) <= 2,
|
|
||||||
"expected consecutive dark MJPEG packets to stay visually stable, got {dark_means:?}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -221,7 +221,6 @@ Hardware-facing assumptions belong near the code that uses them; this file is th
|
|||||||
| `LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US` | server upstream playout override; shifts webcam-video presentation relative to the shared playout epoch |
|
| `LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US` | server upstream playout override; shifts webcam-video presentation relative to the shared playout epoch |
|
||||||
| `LESAVKA_UPLINK_CAMERA_PREVIEW` | client media capture/playback override |
|
| `LESAVKA_UPLINK_CAMERA_PREVIEW` | client media capture/playback override |
|
||||||
| `LESAVKA_UPLINK_MIC_LEVEL` | client media capture/playback override |
|
| `LESAVKA_UPLINK_MIC_LEVEL` | client media capture/playback override |
|
||||||
| `LESAVKA_INSTALL_UVC_CODEC` | installer override; sets the persisted default UVC webcam codec in `/etc/lesavka/server.env` and `/etc/lesavka/uvc.env` |
|
|
||||||
| `LESAVKA_USB_RECOVERY_` | USB recovery timing override |
|
| `LESAVKA_USB_RECOVERY_` | USB recovery timing override |
|
||||||
| `LESAVKA_USB_RECOVERY_CYCLE_WAIT_MS` | USB recovery timing override |
|
| `LESAVKA_USB_RECOVERY_CYCLE_WAIT_MS` | USB recovery timing override |
|
||||||
| `LESAVKA_USB_RECOVERY_FINAL_WAIT_MS` | USB recovery timing override |
|
| `LESAVKA_USB_RECOVERY_FINAL_WAIT_MS` | USB recovery timing override |
|
||||||
|
|||||||
@ -81,18 +81,6 @@ attach_gadget() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
gadget_has_expected_functions() {
|
|
||||||
[[ -d $G/functions/hid.usb0 ]] || return 1
|
|
||||||
[[ -d $G/functions/hid.usb1 ]] || return 1
|
|
||||||
if [[ -z ${DISABLE_UAC:-} ]]; then
|
|
||||||
[[ -d $G/functions/uac2.usb0 ]] || return 1
|
|
||||||
fi
|
|
||||||
if [[ -z ${DISABLE_UVC:-} ]]; then
|
|
||||||
[[ -d $G/functions/uvc.usb0 ]] || return 1
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
--detach)
|
--detach)
|
||||||
detach_gadget
|
detach_gadget
|
||||||
@ -326,13 +314,10 @@ log "✅ UDC detected: $UDC"
|
|||||||
# If a gadget is already configured, avoid tearing it down unless forced.
|
# If a gadget is already configured, avoid tearing it down unless forced.
|
||||||
if [[ -d $G && -z $ALLOW_RESET ]]; then
|
if [[ -d $G && -z $ALLOW_RESET ]]; then
|
||||||
if [[ -s $G/UDC || -d $G/configs/c.1 ]]; then
|
if [[ -s $G/UDC || -d $G/configs/c.1 ]]; then
|
||||||
if gadget_has_expected_functions; then
|
log "🔒 gadget already configured; skipping reset."
|
||||||
log "🔒 gadget already configured; skipping reset."
|
log " Set LESAVKA_ALLOW_GADGET_RESET=1 to force rebuild."
|
||||||
log " Set LESAVKA_ALLOW_GADGET_RESET=1 to force rebuild."
|
attach_gadget || true
|
||||||
attach_gadget || true
|
exit 0
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
log "⚠️ gadget is configured but missing expected functions; continuing toward rebuild."
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,6 @@ export TMPDIR=${TMPDIR:-/var/tmp}
|
|||||||
REF=${LESAVKA_REF:-master} # fallback
|
REF=${LESAVKA_REF:-master} # fallback
|
||||||
REPO_URL=${LESAVKA_REPO_URL:-}
|
REPO_URL=${LESAVKA_REPO_URL:-}
|
||||||
USER_HOME=$(getent passwd "$ORIG_USER" | cut -d: -f6)
|
USER_HOME=$(getent passwd "$ORIG_USER" | cut -d: -f6)
|
||||||
INSTALL_UVC_CODEC=${LESAVKA_INSTALL_UVC_CODEC:-mjpeg}
|
|
||||||
|
|
||||||
manifest_package_version() {
|
manifest_package_version() {
|
||||||
local manifest=$1
|
local manifest=$1
|
||||||
@ -33,7 +32,7 @@ LESAVKA_UVC_FPS=${LESAVKA_UVC_FPS:-20}
|
|||||||
LESAVKA_UVC_INTERVAL=${LESAVKA_UVC_INTERVAL:-500000}
|
LESAVKA_UVC_INTERVAL=${LESAVKA_UVC_INTERVAL:-500000}
|
||||||
LESAVKA_UVC_WIDTH=${LESAVKA_UVC_WIDTH:-640}
|
LESAVKA_UVC_WIDTH=${LESAVKA_UVC_WIDTH:-640}
|
||||||
LESAVKA_UVC_HEIGHT=${LESAVKA_UVC_HEIGHT:-480}
|
LESAVKA_UVC_HEIGHT=${LESAVKA_UVC_HEIGHT:-480}
|
||||||
LESAVKA_UVC_CODEC=${INSTALL_UVC_CODEC}
|
LESAVKA_UVC_CODEC=${LESAVKA_UVC_CODEC:-mjpeg}
|
||||||
LESAVKA_UVC_BLOCKING=${LESAVKA_UVC_BLOCKING:-1}
|
LESAVKA_UVC_BLOCKING=${LESAVKA_UVC_BLOCKING:-1}
|
||||||
LESAVKA_UVC_MAXBURST=${LESAVKA_UVC_MAXBURST:-0}
|
LESAVKA_UVC_MAXBURST=${LESAVKA_UVC_MAXBURST:-0}
|
||||||
EOF
|
EOF
|
||||||
@ -90,10 +89,6 @@ validate_uvc_gadget_ready() {
|
|||||||
echo "✅ UVC gadget output ready at ${node}"
|
echo "✅ UVC gadget output ready at ${node}"
|
||||||
}
|
}
|
||||||
|
|
||||||
uvc_gadget_present() {
|
|
||||||
[[ -d /sys/kernel/config/usb_gadget/lesavka/functions/uvc.usb0 ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
udc_state() {
|
udc_state() {
|
||||||
local udc=""
|
local udc=""
|
||||||
udc=$(ls /sys/class/udc 2>/dev/null | head -n1 || true)
|
udc=$(ls /sys/class/udc 2>/dev/null | head -n1 || true)
|
||||||
@ -572,7 +567,7 @@ fi
|
|||||||
printf 'LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US=%s\n' "${LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US:-0}"
|
printf 'LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US=%s\n' "${LESAVKA_UPSTREAM_VIDEO_PLAYOUT_OFFSET_US:-0}"
|
||||||
printf 'LESAVKA_UPSTREAM_PAIR_SLACK_US=%s\n' "${LESAVKA_UPSTREAM_PAIR_SLACK_US:-20000}"
|
printf 'LESAVKA_UPSTREAM_PAIR_SLACK_US=%s\n' "${LESAVKA_UPSTREAM_PAIR_SLACK_US:-20000}"
|
||||||
printf 'LESAVKA_UPSTREAM_STALE_DROP_MS=%s\n' "${LESAVKA_UPSTREAM_STALE_DROP_MS:-80}"
|
printf 'LESAVKA_UPSTREAM_STALE_DROP_MS=%s\n' "${LESAVKA_UPSTREAM_STALE_DROP_MS:-80}"
|
||||||
printf 'LESAVKA_UVC_CODEC=%s\n' "${INSTALL_UVC_CODEC}"
|
printf 'LESAVKA_UVC_CODEC=%s\n' "${LESAVKA_UVC_CODEC:-mjpeg}"
|
||||||
} | sudo tee /etc/lesavka/server.env >/dev/null
|
} | sudo tee /etc/lesavka/server.env >/dev/null
|
||||||
|
|
||||||
UVC_ENV_TMP=$(mktemp)
|
UVC_ENV_TMP=$(mktemp)
|
||||||
@ -648,10 +643,6 @@ sudo systemctl enable lesavka-core lesavka-server
|
|||||||
|
|
||||||
UDC_STATE=$(udc_state)
|
UDC_STATE=$(udc_state)
|
||||||
FORCE_GADGET_REBUILD=0
|
FORCE_GADGET_REBUILD=0
|
||||||
if [[ -z ${LESAVKA_DISABLE_UVC:-} ]] && ! uvc_gadget_present; then
|
|
||||||
FORCE_GADGET_REBUILD=1
|
|
||||||
echo "⚠️ UVC function is missing from the live gadget; forcing a rebuild before server start."
|
|
||||||
fi
|
|
||||||
if [[ "$UVC_ENV_CHANGED" == "1" ]] && is_attached_state "$UDC_STATE"; then
|
if [[ "$UVC_ENV_CHANGED" == "1" ]] && is_attached_state "$UDC_STATE"; then
|
||||||
FORCE_GADGET_REBUILD=1
|
FORCE_GADGET_REBUILD=1
|
||||||
echo "⚠️ UVC runtime settings changed while the host is attached; forcing a gadget rebuild so the new descriptors take effect."
|
echo "⚠️ UVC runtime settings changed while the host is attached; forcing a gadget rebuild so the new descriptors take effect."
|
||||||
@ -664,7 +655,7 @@ if [[ -n ${LESAVKA_ALLOW_GADGET_RESET:-} ]] || [[ "$FORCE_GADGET_REBUILD" == "1"
|
|||||||
LESAVKA_DETACH_CLEAR_UDC=1 \
|
LESAVKA_DETACH_CLEAR_UDC=1 \
|
||||||
LESAVKA_RELOAD_UVCVIDEO=1 \
|
LESAVKA_RELOAD_UVCVIDEO=1 \
|
||||||
LESAVKA_UVC_FALLBACK=0 \
|
LESAVKA_UVC_FALLBACK=0 \
|
||||||
LESAVKA_UVC_CODEC="${INSTALL_UVC_CODEC}" \
|
LESAVKA_UVC_CODEC="${LESAVKA_UVC_CODEC:-mjpeg}" \
|
||||||
/usr/local/bin/lesavka-core.sh
|
/usr/local/bin/lesavka-core.sh
|
||||||
sudo systemctl restart lesavka-core
|
sudo systemctl restart lesavka-core
|
||||||
echo "✅ lesavka-core installed and restarted..."
|
echo "✅ lesavka-core installed and restarted..."
|
||||||
@ -684,7 +675,7 @@ ExecStart=/usr/local/bin/lesavka-uvc.sh
|
|||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=2
|
RestartSec=2
|
||||||
KillSignal=SIGTERM
|
KillSignal=SIGTERM
|
||||||
KillMode=control-group
|
KillMode=process
|
||||||
TimeoutStopSec=10
|
TimeoutStopSec=10
|
||||||
StandardError=append:/tmp/lesavka-uvc.stderr
|
StandardError=append:/tmp/lesavka-uvc.stderr
|
||||||
User=root
|
User=root
|
||||||
@ -722,18 +713,10 @@ validate_uvc_gadget_ready
|
|||||||
sudo systemctl restart lesavka-server
|
sudo systemctl restart lesavka-server
|
||||||
INSTALLED_VERSION=$(manifest_package_version "$SRC_DIR/server/Cargo.toml" 2>/dev/null || true)
|
INSTALLED_VERSION=$(manifest_package_version "$SRC_DIR/server/Cargo.toml" 2>/dev/null || true)
|
||||||
INSTALLED_SHA=$(git -C "$SCRIPT_REPO_ROOT" rev-parse --short HEAD 2>/dev/null || true)
|
INSTALLED_SHA=$(git -C "$SCRIPT_REPO_ROOT" rev-parse --short HEAD 2>/dev/null || true)
|
||||||
PERSISTED_CAM_OUTPUT=$(grep '^LESAVKA_CAM_OUTPUT=' /etc/lesavka/server.env 2>/dev/null | tail -n1 | cut -d= -f2- || true)
|
|
||||||
PERSISTED_UVC_CODEC=$(grep '^LESAVKA_UVC_CODEC=' /etc/lesavka/uvc.env 2>/dev/null | tail -n1 | cut -d= -f2- || true)
|
|
||||||
echo "✅ lesavka-server installed and restarted..."
|
echo "✅ lesavka-server installed and restarted..."
|
||||||
if [[ -n $INSTALLED_VERSION || -n $INSTALLED_SHA ]]; then
|
if [[ -n $INSTALLED_VERSION || -n $INSTALLED_SHA ]]; then
|
||||||
echo "➡️ Installed: lesavka-server ${INSTALLED_VERSION:-unknown}${INSTALLED_SHA:+ ($INSTALLED_SHA)}"
|
echo "➡️ Installed: lesavka-server ${INSTALLED_VERSION:-unknown}${INSTALLED_SHA:+ ($INSTALLED_SHA)}"
|
||||||
fi
|
fi
|
||||||
if [[ -n $PERSISTED_CAM_OUTPUT ]]; then
|
|
||||||
echo "➡️ Camera output: ${PERSISTED_CAM_OUTPUT}"
|
|
||||||
fi
|
|
||||||
if [[ -n $PERSISTED_UVC_CODEC ]]; then
|
|
||||||
echo "➡️ UVC codec: ${PERSISTED_UVC_CODEC}"
|
|
||||||
fi
|
|
||||||
echo "➡️ Status: sudo systemctl status lesavka-server --no-pager"
|
echo "➡️ Status: sudo systemctl status lesavka-server --no-pager"
|
||||||
echo "➡️ Logs: sudo journalctl -u lesavka-server -f --no-pager"
|
echo "➡️ Logs: sudo journalctl -u lesavka-server -f --no-pager"
|
||||||
echo "✅ Installed version: lesavka-server ${INSTALLED_VERSION:-unknown}${INSTALLED_SHA:+ ($INSTALLED_SHA)}"
|
echo "✅ Installed version: lesavka-server ${INSTALLED_VERSION:-unknown}${INSTALLED_SHA:+ ($INSTALLED_SHA)}"
|
||||||
|
|||||||
@ -10,7 +10,6 @@ SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
|
|||||||
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd)"
|
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/../.." >/dev/null 2>&1 && pwd)"
|
||||||
|
|
||||||
TETHYS_HOST=${TETHYS_HOST:-tethys}
|
TETHYS_HOST=${TETHYS_HOST:-tethys}
|
||||||
LESAVKA_SERVER_HOST=${LESAVKA_SERVER_HOST:-theia}
|
|
||||||
LESAVKA_SERVER_ADDR=${LESAVKA_SERVER_ADDR:-http://38.28.125.112:50051}
|
LESAVKA_SERVER_ADDR=${LESAVKA_SERVER_ADDR:-http://38.28.125.112:50051}
|
||||||
PROBE_DURATION_SECONDS=${PROBE_DURATION_SECONDS:-10}
|
PROBE_DURATION_SECONDS=${PROBE_DURATION_SECONDS:-10}
|
||||||
PROBE_WARMUP_SECONDS=${PROBE_WARMUP_SECONDS:-4}
|
PROBE_WARMUP_SECONDS=${PROBE_WARMUP_SECONDS:-4}
|
||||||
@ -38,9 +37,6 @@ REMOTE_ANALYZE=${REMOTE_ANALYZE:-1}
|
|||||||
REMOTE_ANALYZE_BIN=${REMOTE_ANALYZE_BIN:-/tmp/lesavka-sync-analyze}
|
REMOTE_ANALYZE_BIN=${REMOTE_ANALYZE_BIN:-/tmp/lesavka-sync-analyze}
|
||||||
REMOTE_ANALYZE_COPY=${REMOTE_ANALYZE_COPY:-1}
|
REMOTE_ANALYZE_COPY=${REMOTE_ANALYZE_COPY:-1}
|
||||||
FETCH_CAPTURE=${FETCH_CAPTURE:-0}
|
FETCH_CAPTURE=${FETCH_CAPTURE:-0}
|
||||||
REMOTE_SERVER_PREFLIGHT=${REMOTE_SERVER_PREFLIGHT:-1}
|
|
||||||
REMOTE_EXPECT_CAM_OUTPUT=${REMOTE_EXPECT_CAM_OUTPUT:-uvc}
|
|
||||||
REMOTE_EXPECT_UVC_CODEC=${REMOTE_EXPECT_UVC_CODEC:-mjpeg}
|
|
||||||
|
|
||||||
mkdir -p "${LOCAL_OUTPUT_DIR}"
|
mkdir -p "${LOCAL_OUTPUT_DIR}"
|
||||||
STAMP="$(date +%Y%m%d-%H%M%S)"
|
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||||
@ -48,50 +44,6 @@ LOCAL_CAPTURE="${LOCAL_OUTPUT_DIR}/lesavka-upstream-av-sync-${STAMP}.mkv"
|
|||||||
LOCAL_ANALYSIS_JSON="${LOCAL_CAPTURE%.mkv}.json"
|
LOCAL_ANALYSIS_JSON="${LOCAL_CAPTURE%.mkv}.json"
|
||||||
LOCAL_CAPTURE_LOG="${LOCAL_CAPTURE%.mkv}.capture.log"
|
LOCAL_CAPTURE_LOG="${LOCAL_CAPTURE%.mkv}.capture.log"
|
||||||
|
|
||||||
preflight_server_path() {
|
|
||||||
[[ "${REMOTE_SERVER_PREFLIGHT}" != "0" ]] || return 0
|
|
||||||
|
|
||||||
echo "==> verifying Lesavka server path on ${LESAVKA_SERVER_HOST}"
|
|
||||||
ssh ${SSH_OPTS} "${LESAVKA_SERVER_HOST}" bash -s -- \
|
|
||||||
"${REMOTE_EXPECT_CAM_OUTPUT}" \
|
|
||||||
"${REMOTE_EXPECT_UVC_CODEC}" <<'REMOTE_PREFLIGHT'
|
|
||||||
set -euo pipefail
|
|
||||||
expect_cam_output=$1
|
|
||||||
expect_uvc_codec=$2
|
|
||||||
|
|
||||||
read_env_value() {
|
|
||||||
local key=$1
|
|
||||||
local file=$2
|
|
||||||
local value=""
|
|
||||||
value=$(grep -E "^${key}=" "$file" 2>/dev/null | tail -n1 | cut -d= -f2- || true)
|
|
||||||
printf '%s\n' "$value"
|
|
||||||
}
|
|
||||||
|
|
||||||
cam_output=$(read_env_value "LESAVKA_CAM_OUTPUT" /etc/lesavka/server.env)
|
|
||||||
server_uvc_codec=$(read_env_value "LESAVKA_UVC_CODEC" /etc/lesavka/server.env)
|
|
||||||
runtime_uvc_codec=$(read_env_value "LESAVKA_UVC_CODEC" /etc/lesavka/uvc.env)
|
|
||||||
|
|
||||||
printf ' ↪ server.env CAM_OUTPUT=%s\n' "${cam_output:-<unset>}"
|
|
||||||
printf ' ↪ server.env UVC_CODEC=%s\n' "${server_uvc_codec:-<unset>}"
|
|
||||||
printf ' ↪ uvc.env UVC_CODEC=%s\n' "${runtime_uvc_codec:-<unset>}"
|
|
||||||
|
|
||||||
if [[ -n "${expect_cam_output}" && "${cam_output}" != "${expect_cam_output}" ]]; then
|
|
||||||
printf 'expected CAM_OUTPUT=%s but found %s\n' "${expect_cam_output}" "${cam_output:-<unset>}" >&2
|
|
||||||
exit 64
|
|
||||||
fi
|
|
||||||
if [[ -n "${expect_uvc_codec}" && "${server_uvc_codec}" != "${expect_uvc_codec}" ]]; then
|
|
||||||
printf 'expected server.env UVC_CODEC=%s but found %s\n' "${expect_uvc_codec}" "${server_uvc_codec:-<unset>}" >&2
|
|
||||||
exit 65
|
|
||||||
fi
|
|
||||||
if [[ -n "${expect_uvc_codec}" && "${runtime_uvc_codec}" != "${expect_uvc_codec}" ]]; then
|
|
||||||
printf 'expected uvc.env UVC_CODEC=%s but found %s\n' "${expect_uvc_codec}" "${runtime_uvc_codec:-<unset>}" >&2
|
|
||||||
exit 66
|
|
||||||
fi
|
|
||||||
|
|
||||||
systemctl is-active lesavka-server lesavka-uvc lesavka-core >/dev/null
|
|
||||||
REMOTE_PREFLIGHT
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "${LOCAL_AUDIO_SANITY}" != "0" ]]; then
|
if [[ "${LOCAL_AUDIO_SANITY}" != "0" ]]; then
|
||||||
echo "==> verifying local speaker-to-mic sanity before upstream sync run"
|
echo "==> verifying local speaker-to-mic sanity before upstream sync run"
|
||||||
"${SCRIPT_DIR}/run_local_audio_sanity.sh"
|
"${SCRIPT_DIR}/run_local_audio_sanity.sh"
|
||||||
@ -114,8 +66,6 @@ if [[ ! -x "${ANALYZE_BIN}" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
preflight_server_path
|
|
||||||
|
|
||||||
echo "==> starting Tethys capture on ${TETHYS_HOST}"
|
echo "==> starting Tethys capture on ${TETHYS_HOST}"
|
||||||
ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
||||||
"${REMOTE_CAPTURE}" \
|
"${REMOTE_CAPTURE}" \
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.14.30"
|
version = "0.14.26"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,6 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_HEIGHT:-1080}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_HEIGHT:-1080}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_FPS:-30}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_CAM_FPS:-30}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_CAM_OUTPUT:-uvc}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_CAM_OUTPUT:-uvc}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_INSTALL_UVC_CODEC:-mjpeg}"));
|
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_WIDTH:-1920}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_WIDTH:-1920}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_HEIGHT:-1080}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_HEIGHT:-1080}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_SINK:-fbdevsink}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_HDMI_SINK:-fbdevsink}"));
|
||||||
@ -50,10 +49,7 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_INTERVAL:-500000}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_INTERVAL:-500000}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_WIDTH:-640}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_WIDTH:-640}"));
|
||||||
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_HEIGHT:-480}"));
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_HEIGHT:-480}"));
|
||||||
assert!(
|
assert!(SERVER_INSTALL.contains("${LESAVKA_UVC_CODEC:-mjpeg}"));
|
||||||
!SERVER_INSTALL.contains("LESAVKA_UVC_CODEC=${LESAVKA_UVC_CODEC:-mjpeg}"),
|
|
||||||
"install script should not let ambient LESAVKA_UVC_CODEC leak into persisted defaults"
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("EnvironmentFile=-/etc/lesavka/uvc.env"),
|
SERVER_INSTALL.contains("EnvironmentFile=-/etc/lesavka/uvc.env"),
|
||||||
"install script should feed live UVC runtime settings into services"
|
"install script should feed live UVC runtime settings into services"
|
||||||
@ -70,14 +66,6 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
SERVER_INSTALL.contains("validate_uvc_gadget_ready"),
|
SERVER_INSTALL.contains("validate_uvc_gadget_ready"),
|
||||||
"install script should verify that the UVC gadget comes back before declaring success"
|
"install script should verify that the UVC gadget comes back before declaring success"
|
||||||
);
|
);
|
||||||
assert!(
|
|
||||||
SERVER_INSTALL.contains("uvc_gadget_present"),
|
|
||||||
"install script should detect when the live gadget is missing the expected UVC function"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
SERVER_INSTALL.contains("UVC function is missing from the live gadget; forcing a rebuild before server start."),
|
|
||||||
"install script should force a rebuild when the live gadget is attached but missing UVC"
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("video-output node did not appear after rebuild"),
|
SERVER_INSTALL.contains("video-output node did not appear after rebuild"),
|
||||||
"install script should explain why it refuses a half-applied UVC install"
|
"install script should explain why it refuses a half-applied UVC install"
|
||||||
@ -86,10 +74,6 @@ fn server_install_pins_hdmi_camera_and_display_defaults() {
|
|||||||
!SERVER_INSTALL.contains("RefuseManualStop=yes"),
|
!SERVER_INSTALL.contains("RefuseManualStop=yes"),
|
||||||
"install script should not generate a UVC unit that blocks legitimate refreshes"
|
"install script should not generate a UVC unit that blocks legitimate refreshes"
|
||||||
);
|
);
|
||||||
assert!(
|
|
||||||
SERVER_INSTALL.contains("KillMode=control-group"),
|
|
||||||
"install script should stop the whole UVC helper cgroup instead of leaving child processes behind"
|
|
||||||
);
|
|
||||||
assert!(
|
assert!(
|
||||||
SERVER_INSTALL.contains("lesavka-uvc already active; runtime settings unchanged."),
|
SERVER_INSTALL.contains("lesavka-uvc already active; runtime settings unchanged."),
|
||||||
"install script should avoid unnecessary UVC restarts when nothing changed"
|
"install script should avoid unnecessary UVC restarts when nothing changed"
|
||||||
@ -114,14 +98,6 @@ fn server_install_reports_installed_version_and_revision() {
|
|||||||
SERVER_INSTALL.contains("git -C \"$SCRIPT_REPO_ROOT\" rev-parse --short HEAD"),
|
SERVER_INSTALL.contains("git -C \"$SCRIPT_REPO_ROOT\" rev-parse --short HEAD"),
|
||||||
"install script should print the installed git revision for operator clarity"
|
"install script should print the installed git revision for operator clarity"
|
||||||
);
|
);
|
||||||
assert!(
|
|
||||||
SERVER_INSTALL.contains("Camera output:"),
|
|
||||||
"install script should print the persisted camera output in the footer"
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
SERVER_INSTALL.contains("UVC codec:"),
|
|
||||||
"install script should print the persisted UVC codec in the footer"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user