infinicode 2.8.26 → 2.8.28

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.
@@ -350,6 +350,23 @@ class PreviewAgent:
350
350
  return dt.timestamp()
351
351
 
352
352
  async def _end_vision_session(self) -> None:
353
+ # Tell the scheduler too, not just the local publisher/LiveKit
354
+ # connection — otherwise the sessions row never gets ended_at set,
355
+ # and the server's active_sessions count climbs forever until it
356
+ # hits max_sessions and silently blocks the room getting genuinely
357
+ # picked up (unrelated to this specific dispatch, but a real bug:
358
+ # every silence-timeout before this fix leaked a permanently
359
+ # "active" session).
360
+ if self._session and self.device_token:
361
+ try:
362
+ await self._session.post(
363
+ f"{self.scheduler_url.rstrip('/')}/api/robots/{self.device_id or self.robot_id}/end-session",
364
+ params={"reason": "silence"},
365
+ headers={"Authorization": f"Bearer {self.device_token}"},
366
+ timeout=10.0,
367
+ )
368
+ except Exception as e:
369
+ logger.warning(f"failed to notify scheduler of session end: {e}")
353
370
  self._vision_session_id = None
354
371
  self._vision_hard_deadline = 0.0
355
372
  self._vision_last_activity = 0.0
@@ -492,11 +509,18 @@ class PreviewAgent:
492
509
  room=data.get("room_name"),
493
510
  )
494
511
  session_id = data.get("session_id")
512
+ voice_config = data.get("voice_config")
495
513
  now = time.time()
496
514
  self._vision_session_id = session_id
497
515
  self._vision_hard_deadline = now + self.vision_session_seconds
498
516
  self._vision_last_activity = now
499
517
  self._current_state = state
518
+ # If the scheduler returned a voice config, let the agent know by
519
+ # posting it to our local webhook endpoint. The preview agent itself
520
+ # does not consume it, but this makes the config observable locally
521
+ # and lets downstream components (audio server, vision, etc.) adapt.
522
+ if voice_config and session_id:
523
+ logger.info(f"scheduler voice config for session {session_id}: {voice_config}")
500
524
  await self._start_publisher(state)
501
525
  if session_id and self._session:
502
526
  try:
@@ -1,9 +1,9 @@
1
- # Python deps for the ROBOT/PI side only (preview_agent.py) — a subset of
2
- # requirements.txt, which also covers the scheduler server (fastapi/uvicorn/
3
- # aiosqlite/etc). Keeping this split means a Pi/robot install doesn't pull in
4
- # server-only packages it will never use.
5
- httpx==0.27.2
6
- livekit>=0.18
7
- opencv-python>=4.8
8
- pyaudio>=0.2
9
- picamera2>=0.3; platform_machine == 'aarch64' or platform_machine == 'arm64'
1
+ # Python deps for the ROBOT/PI side only (preview_agent.py) — a subset of
2
+ # requirements.txt, which also covers the scheduler server (fastapi/uvicorn/
3
+ # aiosqlite/etc). Keeping this split means a Pi/robot install doesn't pull in
4
+ # server-only packages it will never use.
5
+ httpx==0.27.2
6
+ livekit>=0.18
7
+ opencv-python>=4.8
8
+ pyaudio>=0.2
9
+ picamera2>=0.3; platform_machine == 'aarch64' or platform_machine == 'arm64'
@@ -1,66 +1,66 @@
1
- # RoboVision — camera/motion detection (robot-side)
2
-
3
- Runs on the robot. A Flask server (`app_pi_clean.py`, port 5000 by default)
4
- that:
5
-
6
- - Streams the camera at `/video_feed` (MJPEG, with OpenCV-drawn bounding
7
- boxes/labels baked into the frame) — this is what the Park dashboard's
8
- "Show overlay" button in the camera drawer points at directly.
9
- - Runs OpenCV DNN object detection (MobileNet SSD) on every frame —
10
- `/api/detections` for the latest results.
11
- - Runs frame-diff motion detection, toggled via `POST /api/motion/toggle
12
- {"active": true}` — when motion is detected it POSTs a JPEG snapshot to a
13
- configurable webhook (`POST /api/motion/webhook {"url": "..."}`).
14
-
15
- ## Wiring it to an actual session (the production trigger)
16
-
17
- RoboVision only *detects*; it doesn't itself start a robot session. The
18
- scheduler's `preview_agent.py` (in `../scheduler/`) now runs a small built-in
19
- listener for exactly this webhook and turns a motion event into a real,
20
- presence-triggered session (`POST /api/devices/{id}/request-session`),
21
- publishing camera + mic into the resulting LiveKit room. Point RoboVision at
22
- it:
23
-
24
- Both of these calls go to RoboVision's own server (port 5000 by default —
25
- NOT the scheduler on 8080):
26
-
27
- ```
28
- curl -X POST http://localhost:5000/api/motion/webhook \
29
- -H "Content-Type: application/json" \
30
- -d '{"url": "http://localhost:5057/"}'
31
- curl -X POST http://localhost:5000/api/motion/toggle \
32
- -H "Content-Type: application/json" -d '{"active": true}'
33
- ```
34
-
35
- (`5057` is `preview_agent.py`'s default `--vision-webhook-port`; override with
36
- `--vision-webhook-port` if RoboVision runs on a different host than the
37
- preview agent.)
38
-
39
- ## Required model files (NOT bundled)
40
-
41
- `app_pi_clean.py` needs two Caffe model files that are **not shipped** in this
42
- npm package (the weights are ~23MB and would bloat every `infinicode`/
43
- `robopark` install, including installs that never touch RoboPark):
44
-
45
- ```
46
- deploy.prototxt
47
- mobilenet_iter_73000.caffemodel
48
- ```
49
-
50
- Download the standard MobileNet-SSD (VOC) weights (e.g. from
51
- chuanqi305/MobileNet-SSD) into this directory before running. Without them,
52
- `app_pi_clean.py` still runs — object detection is silently disabled, motion
53
- detection still works.
54
-
55
- ## Running
56
-
57
- Pure Python + OpenCV (Flask, cv2, numpy) — cross-platform, no bash required:
58
-
59
- ```
60
- pip install -r requirements_pi_unified.txt
61
- python app_pi_clean.py
62
- ```
63
-
64
- `install.sh`/`run.sh` are Linux/Pi convenience wrappers (venv + systemd-style
65
- process management) — not required on Windows/macOS, just run the script
66
- directly.
1
+ # RoboVision — camera/motion detection (robot-side)
2
+
3
+ Runs on the robot. A Flask server (`app_pi_clean.py`, port 5000 by default)
4
+ that:
5
+
6
+ - Streams the camera at `/video_feed` (MJPEG, with OpenCV-drawn bounding
7
+ boxes/labels baked into the frame) — this is what the Park dashboard's
8
+ "Show overlay" button in the camera drawer points at directly.
9
+ - Runs OpenCV DNN object detection (MobileNet SSD) on every frame —
10
+ `/api/detections` for the latest results.
11
+ - Runs frame-diff motion detection, toggled via `POST /api/motion/toggle
12
+ {"active": true}` — when motion is detected it POSTs a JPEG snapshot to a
13
+ configurable webhook (`POST /api/motion/webhook {"url": "..."}`).
14
+
15
+ ## Wiring it to an actual session (the production trigger)
16
+
17
+ RoboVision only *detects*; it doesn't itself start a robot session. The
18
+ scheduler's `preview_agent.py` (in `../scheduler/`) now runs a small built-in
19
+ listener for exactly this webhook and turns a motion event into a real,
20
+ presence-triggered session (`POST /api/devices/{id}/request-session`),
21
+ publishing camera + mic into the resulting LiveKit room. Point RoboVision at
22
+ it:
23
+
24
+ Both of these calls go to RoboVision's own server (port 5000 by default —
25
+ NOT the scheduler on 8080):
26
+
27
+ ```
28
+ curl -X POST http://localhost:5000/api/motion/webhook \
29
+ -H "Content-Type: application/json" \
30
+ -d '{"url": "http://localhost:5057/"}'
31
+ curl -X POST http://localhost:5000/api/motion/toggle \
32
+ -H "Content-Type: application/json" -d '{"active": true}'
33
+ ```
34
+
35
+ (`5057` is `preview_agent.py`'s default `--vision-webhook-port`; override with
36
+ `--vision-webhook-port` if RoboVision runs on a different host than the
37
+ preview agent.)
38
+
39
+ ## Required model files (NOT bundled)
40
+
41
+ `app_pi_clean.py` needs two Caffe model files that are **not shipped** in this
42
+ npm package (the weights are ~23MB and would bloat every `infinicode`/
43
+ `robopark` install, including installs that never touch RoboPark):
44
+
45
+ ```
46
+ deploy.prototxt
47
+ mobilenet_iter_73000.caffemodel
48
+ ```
49
+
50
+ Download the standard MobileNet-SSD (VOC) weights (e.g. from
51
+ chuanqi305/MobileNet-SSD) into this directory before running. Without them,
52
+ `app_pi_clean.py` still runs — object detection is silently disabled, motion
53
+ detection still works.
54
+
55
+ ## Running
56
+
57
+ Pure Python + OpenCV (Flask, cv2, numpy) — cross-platform, no bash required:
58
+
59
+ ```
60
+ pip install -r requirements_pi_unified.txt
61
+ python app_pi_clean.py
62
+ ```
63
+
64
+ `install.sh`/`run.sh` are Linux/Pi convenience wrappers (venv + systemd-style
65
+ process management) — not required on Windows/macOS, just run the script
66
+ directly.
@@ -1,16 +1,16 @@
1
- # Non-Pi (Windows/macOS/Linux dev laptop) requirements for app_pi_clean.py.
2
- #
3
- # requirements_pi_unified.txt deliberately excludes opencv-python (Pi installs
4
- # it via `apt install python3-opencv` for the ARM-optimized system build) —
5
- # that's wrong off a real Pi, where plain `pip install opencv-python` is the
6
- # normal path. Use this file for a demo/dev machine; use
7
- # requirements_pi_unified.txt (+ apt) on an actual Raspberry Pi.
8
- # numpy is intentionally unpinned on the upper end — modern opencv-python
9
- # wheels are built against numpy 2.x, and pinning <2 forces pip to source-
10
- # build an old numpy with no prebuilt wheel for current Python versions
11
- # (needs a C/C++ compiler most demo machines don't have installed).
12
- flask==3.0.0
13
- flask-cors==4.0.0
14
- opencv-python>=4.8
15
- numpy>=1.24
16
- requests>=2.31
1
+ # Non-Pi (Windows/macOS/Linux dev laptop) requirements for app_pi_clean.py.
2
+ #
3
+ # requirements_pi_unified.txt deliberately excludes opencv-python (Pi installs
4
+ # it via `apt install python3-opencv` for the ARM-optimized system build) —
5
+ # that's wrong off a real Pi, where plain `pip install opencv-python` is the
6
+ # normal path. Use this file for a demo/dev machine; use
7
+ # requirements_pi_unified.txt (+ apt) on an actual Raspberry Pi.
8
+ # numpy is intentionally unpinned on the upper end — modern opencv-python
9
+ # wheels are built against numpy 2.x, and pinning <2 forces pip to source-
10
+ # build an old numpy with no prebuilt wheel for current Python versions
11
+ # (needs a C/C++ compiler most demo machines don't have installed).
12
+ flask==3.0.0
13
+ flask-cors==4.0.0
14
+ opencv-python>=4.8
15
+ numpy>=1.24
16
+ requests>=2.31