infinicode 2.8.92 → 2.8.93
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.
- package/dist/kernel/federation/dashboard-html.d.ts +1 -1
- package/dist/kernel/federation/dashboard-html.js +1 -1
- package/dist/robopark/auto-start.js +51 -11
- package/dist/robopark/robot-runtime.js +48 -0
- package/dist/robopark/setup.js +4 -1
- package/dist/robopark/vision-agent-launcher.js +27 -6
- package/docs/ROBOPARK_PRODUCTION_MEMORY.md +15 -0
- package/package.json +1 -1
- package/packages/robopark/scheduler/media_lock.py +57 -0
- package/packages/robopark/scheduler/preview_agent.py +125 -45
- package/packages/robopark/scheduler/robot_supervisor.py +23 -18
- package/packages/robopark/vision/app_pi_clean.py +12 -7
- package/packages/robopark/vision/audio_server_pi.py +24 -5
|
@@ -15,8 +15,10 @@ import struct
|
|
|
15
15
|
app = Flask(__name__)
|
|
16
16
|
CORS(app)
|
|
17
17
|
|
|
18
|
-
# Camera management
|
|
19
|
-
|
|
18
|
+
# Camera management. Production installs create /dev/robopark-camera from
|
|
19
|
+
# the primary USB capture interface, avoiding /dev/videoN renumbering.
|
|
20
|
+
_configured_camera = os.getenv("ROBOPARK_CAMERA_DEVICE", "")
|
|
21
|
+
current_camera_index = _configured_camera or ("/dev/robopark-camera" if os.path.exists("/dev/robopark-camera") else 0)
|
|
20
22
|
camera = None
|
|
21
23
|
camera_lock = threading.Lock()
|
|
22
24
|
frame_condition = threading.Condition()
|
|
@@ -625,8 +627,11 @@ if __name__ == '__main__':
|
|
|
625
627
|
print("RoboVision - Raspberry Pi Vision Server (Minimal)")
|
|
626
628
|
print("=" * 60)
|
|
627
629
|
print(f"Starting Flask server on http://0.0.0.0:{args.port}")
|
|
628
|
-
if webhook_url:
|
|
629
|
-
print(f"Motion webhook: {webhook_url}")
|
|
630
|
-
print(f"Motion detection: {'ARMED' if motion_detection_active else 'off (POST /api/motion/toggle to arm)'}")
|
|
631
|
-
print("=" * 60)
|
|
632
|
-
|
|
630
|
+
if webhook_url:
|
|
631
|
+
print(f"Motion webhook: {webhook_url}")
|
|
632
|
+
print(f"Motion detection: {'ARMED' if motion_detection_active else 'off (POST /api/motion/toggle to arm)'}")
|
|
633
|
+
print("=" * 60)
|
|
634
|
+
# Start the single camera owner at boot. Production motion and MJPEG
|
|
635
|
+
# readiness must not depend on an operator opening the dashboard first.
|
|
636
|
+
_ensure_camera_worker()
|
|
637
|
+
app.run(host='0.0.0.0', port=args.port, debug=False, threaded=True)
|
|
@@ -17,12 +17,29 @@ import os
|
|
|
17
17
|
from datetime import datetime
|
|
18
18
|
import logging
|
|
19
19
|
import subprocess
|
|
20
|
-
import base64
|
|
21
|
-
|
|
20
|
+
import base64
|
|
21
|
+
import functools
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from groq import Groq
|
|
25
|
+
|
|
26
|
+
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scheduler"))
|
|
27
|
+
from media_lock import media_lock
|
|
22
28
|
|
|
23
29
|
# Configure logging
|
|
24
30
|
logging.basicConfig(level=logging.INFO, format='%(message)s')
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
31
|
+
logger = logging.getLogger(__name__)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def exclusive_media(kind: str):
|
|
35
|
+
"""Prevent diagnostics from stealing ALSA devices from production."""
|
|
36
|
+
def decorate(func):
|
|
37
|
+
@functools.wraps(func)
|
|
38
|
+
def wrapped(*args, **kwargs):
|
|
39
|
+
with media_lock(kind, timeout=3.0):
|
|
40
|
+
return func(*args, **kwargs)
|
|
41
|
+
return wrapped
|
|
42
|
+
return decorate
|
|
26
43
|
|
|
27
44
|
@asynccontextmanager
|
|
28
45
|
async def lifespan(app: FastAPI):
|
|
@@ -173,7 +190,8 @@ def find_bluetooth_devices():
|
|
|
173
190
|
# Find Bluetooth devices on startup
|
|
174
191
|
find_bluetooth_devices()
|
|
175
192
|
|
|
176
|
-
|
|
193
|
+
@exclusive_media("speaker")
|
|
194
|
+
def play_audio_file(file_path: str):
|
|
177
195
|
"""Play audio file using sounddevice (supports Bluetooth)"""
|
|
178
196
|
try:
|
|
179
197
|
logger.info(f"🔊 Playing audio: {file_path}")
|
|
@@ -231,7 +249,8 @@ def get_available_input_devices():
|
|
|
231
249
|
input_devices.append(i)
|
|
232
250
|
return input_devices
|
|
233
251
|
|
|
234
|
-
|
|
252
|
+
@exclusive_media("microphone")
|
|
253
|
+
def record_audio_with_vad():
|
|
235
254
|
"""
|
|
236
255
|
Record audio from Bluetooth microphone with Voice Activity Detection
|
|
237
256
|
Rotates through available devices if no audio detected
|