diff --git a/tools/device/start.sh b/tools/device/start.sh
new file mode 100644
index 0000000..bff12d4
--- /dev/null
+++ b/tools/device/start.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+mkdir -p /tmp/venc/c0/;
+mkdir -p /tmp/aenc/c0/;
+mkdir -p /tmp/playback/c0/;
+mkdir -p /tmp/twoway/c0/;
+mkdir -p /tmp/sr/c0/;
+mkdir -p /tmp/sdcard;
+mkdir -p /tmp/canbus/c0/;
+mount /dev/mmcblk0p1 /tmp/sdcard 2>/dev/null || true
+export LD_LIBRARY_PATH=$(pwd)/lib;
+cd ../plus/kp_firmware/kp_firmware_0/kp_firmware/bin
+./rtsps -c stream_server_config.ini &
+./kp_firmware_host_stream &
+#./rtsps -c stream_server_config.ini > /dev/null 2>&1 &
+#./kp_firmware_host_stream > /tmp/fw.log 2>&1 &
+### Notice : Codec type AAC4, sample rate 8000, bit rate 32000, raw format, stereo, mic_in ###
+#./tinyaenc_mmap -d "hw:0,0" -r 8000 -C 0 -b 32000 -t 0 -S 0 -i 0 &
+#sleep 2;
+#./volume_ctrl -i 0 -M 0 -v 96;
+#./playback_example_mmap -d "hw:0,0" -r 8000 -c 2 -C 0 &
diff --git a/web_serve.py b/web_serve.py
index 7833b3e..0ae4b55 100644
--- a/web_serve.py
+++ b/web_serve.py
@@ -46,6 +46,7 @@ DEPLOY_SRC = SCRIPT_DIR / "tools" / "device" / "deploy.sh"
DEMO_RTSP_SRC = SCRIPT_DIR / "tools" / "device" / "demo_rtsp.sh"
DEMO_HDMI_SRC = SCRIPT_DIR / "tools" / "device" / "demo_hdmi.sh"
DEMO_RTSP_HDMI_SRC = SCRIPT_DIR / "tools" / "device" / "demo_rtsp_hdmi.sh"
+START_SH_SRC = SCRIPT_DIR / "tools" / "device" / "start.sh"
NEF_DIR = SCRIPT_DIR / "nef"
KCURL_SRC = Path("/home/user/Documents/GOFACE/奧創雲/kCurl-1.1.1-release/kCurl-linux-armv7")
CONFIG_FILE = SCRIPT_DIR / ".web_config.json"
@@ -93,6 +94,7 @@ def prepare_build_dir():
(DEMO_RTSP_SRC, "demo_rtsp.sh"),
(DEMO_HDMI_SRC, "demo_hdmi.sh"),
(DEMO_RTSP_HDMI_SRC, "demo_rtsp_hdmi.sh"),
+ (START_SH_SRC, "start.sh"),
]:
if Path(src).exists():
shutil.copy2(src, BUILD_DIR / name)
@@ -521,6 +523,9 @@ def api_deploy_run():
("Pushing deploy.sh to device...",
f"wget -q {base}/deploy.sh -O /tmp/deploy.sh && chmod +x /tmp/deploy.sh && echo 'deploy.sh OK'",
False, 30),
+ ("Updating start.sh...",
+ f"wget -q {base}/start.sh -O /mnt/flash/vienna/start.sh && chmod +x /mnt/flash/vienna/start.sh && echo 'start.sh OK'",
+ False, 30),
("Downloading kCurl (event upload tool)...",
f"wget -q {base}/kCurl -O {bd}/kCurl && chmod +x {bd}/kCurl && echo 'kCurl OK'",
False, 30),
@@ -562,6 +567,89 @@ def api_deploy_run():
return Response(generate(), mimetype="text/event-stream",
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
+# ── API: deploy binary only (SSE) ────────────────────────────────────────────
+@app.route("/api/deploy/binary")
+def api_deploy_binary():
+ cfg = load_config()
+ kl_ip = request.args.get("ip", cfg["kl630_ip"])
+ h_ip = request.args.get("host_ip", cfg["host_ip"])
+ port = int(request.args.get("port", cfg["port"]))
+ base = f"http://{h_ip}:{port}"
+ fw = FW_PATH_DEVICE
+ bd = BIN_DIR_DEVICE
+ out_rtsp = request.args.get("out_rtsp", "1") == "1"
+ out_hdmi = request.args.get("out_hdmi", "0") == "1"
+
+ if out_hdmi and not out_rtsp:
+ start_cmd = f"cd {bd} && nohup sh ./ini/demo_hdmi.sh > /tmp/fw.log 2>&1 &"
+ elif out_rtsp and out_hdmi:
+ start_cmd = f"cd {bd} && nohup sh ./ini/demo_rtsp_hdmi.sh > /tmp/fw.log 2>&1 &"
+ else:
+ start_cmd = f"cd {bd} && nohup sh ./ini/demo_rtsp.sh > /tmp/fw.log 2>&1 &"
+
+ def generate():
+ yield sse(f"Connecting to {kl_ip}:23...")
+ try:
+ tn = _telnet_connect(kl_ip)
+ _drain_shell(tn)
+ yield sse("Connected.", "ok")
+
+ yield sse("Stopping firmware...")
+ for ln in _telnet_run(tn, "killall -9 kp_firmware_host_stream 2>/dev/null; killall -9 rtsps 2>/dev/null; sleep 1; rm -f /dev/shm/*", timeout=15):
+ yield sse(ln)
+
+ yield sse("Downloading binary...")
+ for ln in _telnet_run(tn, f"wget -q {base}/kp_firmware_host_stream -O {fw} && chmod +x {fw} && ls -lh {fw}", timeout=60):
+ yield sse(ln, "ok")
+
+ yield sse("Restarting firmware...")
+ for ln in _telnet_run_bg(tn, start_cmd):
+ if ln.strip(): yield sse(ln.strip())
+
+ ok, lines = _verify_firmware_running(tn)
+ for ln in lines:
+ yield sse(ln, "ok" if ok else "warn")
+ if ok:
+ yield sse("Binary updated and firmware running.", "ok")
+ else:
+ yield sse("Firmware may not have started — check /tmp/fw.log", "warn")
+ tn.close()
+ except Exception as e:
+ yield sse(f"Telnet error: {e}", "error")
+ yield sse_done()
+
+ return Response(generate(), mimetype="text/event-stream",
+ headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
+
+# ── API: deploy start.sh only (SSE) ──────────────────────────────────────────
+@app.route("/api/deploy/startsh")
+def api_deploy_startsh():
+ cfg = load_config()
+ kl_ip = request.args.get("ip", cfg["kl630_ip"])
+ h_ip = request.args.get("host_ip", cfg["host_ip"])
+ port = int(request.args.get("port", cfg["port"]))
+ base = f"http://{h_ip}:{port}"
+
+ def generate():
+ yield sse(f"Connecting to {kl_ip}:23...")
+ try:
+ tn = _telnet_connect(kl_ip)
+ _drain_shell(tn)
+ yield sse("Connected.", "ok")
+
+ yield sse("Updating start.sh...")
+ for ln in _telnet_run(tn, f"wget -q {base}/start.sh -O /mnt/flash/vienna/start.sh && chmod +x /mnt/flash/vienna/start.sh && echo 'start.sh OK'", timeout=30):
+ yield sse(ln, "ok")
+
+ tn.close()
+ yield sse("start.sh updated. Takes effect on next reboot.", "ok")
+ except Exception as e:
+ yield sse(f"Telnet error: {e}", "error")
+ yield sse_done()
+
+ return Response(generate(), mimetype="text/event-stream",
+ headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no"})
+
# ── API: SPI setup via Telnet (SSE) ─────────────────────────────────────────
@app.route("/api/spi_setup/run")
def api_spi_setup_run():
@@ -1693,6 +1781,14 @@ input:checked+.slider:before{transform:translateX(16px);background:#fff}
Deploy to KL630
+
+