32 KiB
Bee Camera System — Full Technical Report
Generated: 2026-03-13
Executive Summary
The Hivemapper Bee dashcam uses an Intel Keem Bay SoC with an integrated Myriad X VPU for camera capture and ML inference. The camera pipeline flows from a Sony IMX378-equivalent sensor through MIPI CSI-2 to the VPU, where DepthAI firmware handles image processing and neural network inference. Frames are written to disk and exposed through multiple odc-api REST endpoints.
Key Findings:
- Camera controlled via
depthai_gate.service(Python/Flask on port 11492) - ML inference handled by
map-ai.serviceusing the VPU's Neural Compute Engine - Live frames stored in
/tmp/recording/pics/ - Landmark observation images stored in
/data/recording/cached_observations/ - Preview mode restarts the camera-bridge service with different configuration
- No direct V4L2 access — all camera access goes through DepthAI pipeline
1. Hardware
1.1 System-on-Chip: Intel Keem Bay
| Component | Specification |
|---|---|
| SoC | Intel Keem Bay (RVC2 / Robotics Vision Core 2) |
| CPU | 4× ARM Cortex-A53 @ 1.5GHz |
| VPU | Intel Movidius Myriad X (16 SHAVE cores) |
| NPU | Integrated Neural Compute Engine (hardware inference) |
| RAM | 4GB LPDDR4 (~3.5GB usable) |
| ISP | Integrated Image Signal Processor on VPU |
| Process | 10nm (Intel) |
Memory Configuration:
MemTotal: 3,584,000 kB (~3.5GB)
SwapTotal: 2,097,148 kB (~2GB)
CmaTotal: 1,408,000 kB (~1.34GB reserved for VPU/camera DMA)
1.2 Camera Sensor
| Specification | Value |
|---|---|
| Sensor | Sony IMX378 (or equivalent 12MP) |
| Resolution | 4056 × 3040 native, downscaled to 2028 × 1024 |
| Interface | MIPI CSI-2 |
| Frame Rate | Variable, typically 30 FPS |
| ISP | On-VPU processing via DepthAI |
The Bee uses a Luxonis OAK-1 compatible camera module integrated with the Keem Bay SoC. The camera sensor connects directly to the SoC's MIPI CSI-2 interface, which is managed entirely by the DepthAI/Luxonis firmware running on the Myriad X VPU.
1.3 Bus Architecture
┌─────────────────────────────────────────────────────────────────┐
│ Intel Keem Bay SoC │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ ARM Cortex │ │ Myriad X VPU │ │ Neural Compute │ │
│ │ A53 (4-core) │ │ (16 SHAVE) │ │ Engine (NCE) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ └────────┬────────┴──────────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ Internal Bus │ │
│ │ (AXI/NoC) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌─────────────┼─────────────────────────────────────┐ │
│ ┌─┴──┐ ┌────┴────┐ ┌────────┐ ┌───────────┐ │ │
│ │PCIe│ │ USB │ │ SDIO │ │ MIPI CSI │ │ │
│ └──┬─┘ └────┬────┘ └────┬───┘ └─────┬─────┘ │ │
└─────┼───────────┼──────────────┼──────────────┼────────┘ │
│ │ │ │ │
┌─────┴─────┐ ┌───┴───────┐ ┌──┴──┐ ┌────┴─────┐ │
│ Marvell │ │ Telit │ │eMMC │ │ Camera │ │
│ 88W8997 │ │ LE910C4 │ │Flash│ │ Module │ │
│ WiFi/BT │ │ LTE Modem │ │ │ │ (IMX378) │ │
└───────────┘ └───────────┘ └─────┘ └──────────┘ │
2. Kernel / V4L2
2.1 Kernel Modules
The Bee runs a custom Yocto-based Linux with Intel-specific VPU drivers:
| Module | Purpose | Status |
|---|---|---|
| kmb_cam (if present) | Keem Bay camera driver | Likely used internally |
| kmb_imx412 (if present) | Sony IMX412 sensor driver | May be loaded for sensor |
| videodev | V4L2 subsystem | Core video framework |
| v4l2_fwnode | V4L2 firmware node parsing | Device tree integration |
Note: Standard V4L2 device access (/dev/video*) is not used for normal operation. The camera is accessed exclusively through the DepthAI XLink protocol running on the VPU. The VPU owns the camera hardware completely.
2.2 VPU Sysfs Interface
The VPU is controlled via sysfs:
/sys/class/vpu/
Firmware Loading:
luxonis_vpu.bin— DepthAI firmware (Luxonis/OAK)vpu_nvr_b0.bin— Intel HDDL firmware (NOT used, conflicts)
The VPU firmware is written to a sysfs attribute (fwname) to trigger loading. The DepthAI firmware must load first, otherwise the Intel HDDL service (deviceservice) grabs the VPU and causes conflicts.
2.3 No Direct V4L2 Access
Important: You cannot access the camera via /dev/video* while depthai_gate is running. The DepthAI pipeline has exclusive ownership of the camera hardware. To get frames, you must:
- Use the existing depthai_gate/odc-api stack, OR
- Stop depthai_gate and implement your own DepthAI pipeline, OR
- Reverse-engineer XLink and write custom firmware
3. DepthAI Gate
3.1 Service Configuration
# depthai_gate.service (inferred from analysis)
[Unit]
Description=DepthAI Camera Gate
After=network.target
[Service]
Type=simple
User=root
ExecStart=/opt/depthai_gate/run.py
Restart=always
[Install]
WantedBy=multi-user.target
3.2 Technical Details
| Property | Value |
|---|---|
| Language | Python 3 + Flask |
| Port | 11492 (localhost) |
| Tasks | ~158 threads observed |
| Memory | ~200MB RSS |
| Location | /opt/depthai_gate/ (estimated) |
3.3 Responsibilities
- VPU Firmware Loading — Writes
luxonis_vpu.binto VPU sysfs - XLink Connection — Establishes PCIe XLink to Myriad X VPU
- DepthAI Pipeline — Configures camera capture and ISP settings
- Frame Capture — Captures frames at configured resolution/framerate
- Frame Output — Writes frames to
/tmp/recording/pics/
3.4 XLink Protocol
XLink is Luxonis's proprietary protocol for host-to-VPU communication:
- Transport: PCIe (on Keem Bay) or USB (on desktop OAK devices)
- Channels: Bidirectional data streams for frames, tensors, and control
- Status Values:
0= Disconnected1= Connecting / Error2= Connected (good)
Status Check (from logs):
xlink_device_status=2 # Healthy
vpu_firmware=luxonis_vpu.bin
3.5 Pipeline Configuration
The DepthAI pipeline likely includes:
- ColorCamera node — IMX378 capture at 4K, downscaled to 2028×1024
- ImageManipNode — Resize, crop, color conversion
- XLinkOut node — Send frames to host for storage
- NeuralNetwork node (optional) — On-VPU inference
Pipeline configs may exist at:
/opt/depthai_gate/pipeline.json/data/camera_config.json- Hardcoded in Python
3.6 VPU Conflict Bug
Root Cause (identified and fixed):
deviceservice.service (Intel HDDL / OpenVINO) was racing with depthai_gate.service:
- HDDL starts at boot, loads
vpu_nvr_b0.bin - depthai_gate starts, overwrites with
luxonis_vpu.bin - HDDL locked out, retries XLink every 2 seconds forever
- On depthai_gate restart, HDDL grabs VPU first → camera dead
- Watchdog (
secure-wdtclient) crash loops → memory pressure → OOM
Fix:
systemctl disable --now deviceservice
systemctl mask deviceservice # Survives OTA better
4. map-ai Pipeline
4.1 Service Configuration
# map-ai.service (inferred)
[Unit]
Description=Map AI Processing
After=depthai_gate.service
[Service]
Type=simple
User=root
ExecStart=/opt/map-ai/run.py
Restart=always
[Install]
WantedBy=multi-user.target
4.2 Technical Details
| Property | Value |
|---|---|
| Language | Python 3 |
| Model Format | ONNX (via OpenVINO or DepthAI NCE) |
| Input | Frames from depthai_gate |
| Output | Detections to Redis, blurred frames to disk |
4.3 Processing Pipeline
Frame from depthai → map-ai.py
│
▼
┌───────────────────────────────────────┐
│ ML INFERENCE (on VPU) │
│ - Road sign classifier │
│ - Face detector (privacy) │
│ - License plate detector (privacy) │
└───────────────────────┬───────────────┘
│
▼
┌───────────────────────────────────────┐
│ PRIVACY PROCESSING │
│ - PrivacyBlurNode │
│ - Gaussian blur on faces/plates │
│ - cv2.imwrite blurred frames │
└───────────────────────┬───────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
Redis ZSET (detections) Disk (blurred frames)
4.4 AI Models
| Model | Location | Purpose |
|---|---|---|
| Road Signs | /opt/object-detection/model.blob or /data/models/ |
Sign classification |
| Privacy | /opt/odc-api/python/ or /data/models/ |
Face/plate detection |
| PVC | /data/recording/models/pvc.onnx |
Unknown (227 bytes — likely index) |
Privacy Model Hash: Stored in FrameKm metadata for verification.
4.5 Redis Integration
map-ai writes to Redis status keys:
GET MAP_AI_READY → "True"
GET EXTERNAL_MODEL_CLASSIFIER_READY → "True"
Detection results stored in SQLite, not Redis ZSETs.
5. Frame Storage
5.1 Storage Locations
| Path | Type | Purpose | Persistence |
|---|---|---|---|
/tmp/recording/pics/ |
tmpfs | Live camera frames | Ephemeral |
/tmp/recording/preview/ |
tmpfs | Preview mode frames | Ephemeral |
/data/recording/cached_observations/ |
ext4 | Landmark observation images | Persistent |
/data/recording/framekm/ |
ext4 | FrameKm upload bundles | Persistent |
/tmp/rgb/ |
tmpfs | Frame list files | Ephemeral |
5.2 Frame Format
| Property | Value |
|---|---|
| Format | JPEG |
| Resolution | 2028 × 1024 |
| Quality | ~85% (estimated ~150-200KB/frame) |
| Color | RGB |
5.3 Naming Convention
Live frames (/tmp/recording/pics/):
{system_time_ms}_{frame_id}_{sequence}.jpg
Example: 1709920000123_0001_0042.jpg
Cached observations (/data/recording/cached_observations/):
{timestamp}_{subsecond}_{frame_number}.jpg
Example: 1746377552_043000_2945056.jpg
5.4 Frame Purger
The folder_purger service manages disk space:
folder-purger /tmp/recording/pic 400000000 /mnt/data/gps 2000000000 ...
When /tmp/recording/pics/ exceeds 400MB, older frames are deleted.
5.5 Database Schema
Frames are tracked in SQLite (/data/recording/odc-api.db or data-logger.v2.0.0.db):
-- frames table
CREATE TABLE frames (
system_time INTEGER PRIMARY KEY,
image_name TEXT
);
Landmark observations reference frames:
-- observations table (simplified)
CREATE TABLE observations (
id INTEGER PRIMARY KEY,
landmark_id INTEGER,
image_name TEXT,
x1 REAL, y1 REAL, x2 REAL, y2 REAL, -- bounding box
ts INTEGER,
...
);
6. video-processor
6.1 Service Details
The video-processor service is not explicitly documented in the analyzed firmware, but based on naming patterns, it likely handles:
- FrameKm Bundling — Package frames + metadata for upload
- Video Encoding — H.264/H.265 encoding for preview/streaming
- Frame Sequencing — Order frames for FrameKm creation
6.2 FrameKm Format
Purpose: Bundle ~1km of driving data for upload to Hivemapper/HERE.
Path: /data/recording/framekm/
Contents:
framekm-2024-03-08-12-34-56-abc123.tar
├── manifest.json
├── frame_0001.jpg
├── frame_0002.jpg
├── ...
├── gnss_auth_buffer.bin
└── gnss_auth_signature.bin
Manifest Fields:
{
"name": "framekm-2024-03-08-12-34-56-abc123",
"numFrames": 150,
"deviceId": "fvhL2I-iCT",
"firmwareVersion": "0.0.1",
"privacyModelHash": "sha256:abc123...",
"gnssAuthBuffer": "base64...",
"gnssAuthSignature": "base64...",
"gnssAuthPublicKey": "base64...",
"createdAt": 1709920000000
}
6.3 Relationship to Camera Frames
The video-processor does NOT produce the frames we care about for camera access. It only packages existing blurred frames for upload. For raw frame access, focus on depthai_gate and the preview system.
7. odc-api Camera Endpoints
7.1 Base URL
http://192.168.0.10:5000/api/1/
Binds to AP interface (wlp1s0f0) only — not accessible from home LAN directly.
7.2 Preview Endpoints
| Endpoint | Method | Description |
|---|---|---|
/preview/start |
GET | Start preview mode (120s timeout) |
/preview/stop |
GET | Stop preview mode |
/preview/status |
GET | Check if preview is active |
/preview/metadata |
GET | Get latest frame metadata |
Preview Implementation (util/preview.ts):
export const startPreview = async () => {
// Create preview directory
await execSync('mkdir /tmp/recording/preview');
// Write preview config
writeFileSync(IMAGER_CONFIG_PATH, JSON.stringify(getPreviewConfig()));
// Restart camera-bridge with new config
await execSync(CMD.STOP_CAMERA); // systemctl stop camera-bridge
await sleep(1000);
await execSync(CMD.START_CAMERA); // systemctl start camera-bridge
};
Preview Timeout: 120 seconds (auto-stops to preserve 4K quality recording)
7.3 Landmark Image Endpoints
| Endpoint | Method | Description |
|---|---|---|
/landmarks/images/:id |
GET | Get image paths for landmark |
/landmarks/:id/chips |
GET | Get chip endpoints for landmark |
/landmarks/:id/chips/:chip_id |
GET | Get cropped observation image (JPEG) |
/landmarks/boundingBox/:id |
GET | Get bounding box coordinates |
/landmarks/upload |
PUT | Upload landmark image to external URL |
Image Retrieval Flow:
GET /landmarks/images/123
↓
Returns: ["/data/recording/cached_observations/1746377552_043000_2945056.jpg"]
↓
GET /landmarks/123/chips/456
↓
Returns: Cropped JPEG (bounding box region)
7.4 Camera Configuration
Config Path: /opt/camera-bridge/config.json
Commands (from bee.ts):
export const CMD = {
RESTART_CAMERA: 'systemctl restart camera-bridge',
START_CAMERA: 'systemctl start camera-bridge',
STOP_CAMERA: 'systemctl stop camera-bridge',
START_PREVIEW: 'systemctl start camera-preview',
STOP_PREVIEW: 'systemctl stop camera-preview',
// ...
};
7.5 Frame Retrieval
There is no direct /camera/frame endpoint in the current odc-api. To get a camera frame:
-
Via Preview Mode:
- Call
/preview/start - Read frames from
/tmp/recording/preview/ - Call
/preview/stopwhen done
- Call
-
Via Landmark Images:
- Call
/landmarks/last/Nto get recent detections - Call
/landmarks/images/:idto get observation image paths - Call
/landmarks/:id/chips/:chip_idto get cropped JPEG
- Call
-
Direct File Access (SSH):
- Read from
/tmp/recording/pics/for latest frames - Read from
/data/recording/cached_observations/for landmark images
- Read from
8. Full Data Flow
8.1 Complete Pipeline
┌──────────────────────────────────────────────────────────────────────────────┐
│ CAMERA CAPTURE │
│ IMX378 Sensor → MIPI CSI-2 → VPU ISP → DepthAI Pipeline │
└───────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ DEPTHAI_GATE (port 11492) │
│ - XLink communication with Myriad X VPU │
│ - Frame capture from DepthAI pipeline │
│ - Writes frames to /tmp/recording/pics/ │
└───────────────────────────────────┬──────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────────────────────┐ ┌──────────────────────────────────────────┐
│ RAW FRAME STORAGE │ │ MAP-AI INFERENCE │
│ /tmp/recording/pics/ │ │ - Road sign detection (VPU NCE) │
│ - Temporary frames │ │ - Privacy blur (faces/plates) │
│ - Purged when >400MB │ │ - Outputs to Redis + SQLite │
└───────────────────────────────┘ └─────────────────┬────────────────────────┘
│
┌─────────────────────────────────┤
▼ ▼
┌───────────────────────────────────┐ ┌──────────────────────────────────────┐
│ CACHED OBSERVATIONS │ │ LANDMARK DATABASE │
│ /data/recording/ │ │ /data/recording/odc-api.db │
│ cached_observations/ │ │ - landmarks table │
│ - Persistent blurred frames │ │ - observations table │
│ - Referenced by landmark ID │ │ - frames table │
└───────────────────┬───────────────┘ └─────────────────┬────────────────────┘
│ │
└──────────────┬──────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ ODC-API (port 5000) │
│ - /preview/* — Start/stop preview mode │
│ - /landmarks/last/N — Get recent detections │
│ - /landmarks/images/:id — Get observation image paths │
│ - /landmarks/:id/chips/:chip_id — Get cropped JPEG │
└───────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ FRAMEKM BUNDLING │
│ hivemapper-data-logger │
│ - Collect ~1km of frames + metadata │
│ - Bundle with GNSS auth signatures │
│ - Store at /data/recording/framekm/ │
└───────────────────────────────────┬──────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ UPLOAD PATH │
│ odc-api → mitmdump (port 8888) → Cloudflare Workers → HERE OLP │
└──────────────────────────────────────────────────────────────────────────────┘
8.2 Single Detection Event Trace
1. Camera captures frame
└── IMX378 → MIPI → VPU ISP → depthai_gate
2. Frame written to disk
└── /tmp/recording/pics/1709920000123_0001_0042.jpg
3. map-ai reads frame
└── Runs road sign classifier on VPU NCE
4. Detection found (speed limit 35)
└── Privacy blur applied to any faces/plates
5. Observation stored
└── SQLite: observations table (landmark_id, bbox, ts, image_name)
└── File: /data/recording/cached_observations/...
6. Landmark created/updated
└── SQLite: landmarks table (class_label, lat, lon, confidence)
7. odc-api exposes data
└── GET /landmarks/last/5 returns detection
└── GET /landmarks/images/{id} returns image path
└── GET /landmarks/{id}/chips/{chip_id} returns cropped JPEG
9. Replacement Considerations
9.1 Accessing Frames Without odc-api
Option 1: Direct File Read
# SSH to Bee
ssh -p 2222 root@localhost # via Lucy tunnel
# Read latest frames
ls -lt /tmp/recording/pics/ | head -10
cp /tmp/recording/pics/latest_frame.jpg /tmp/
# Stream frames (naive)
while true; do
cp $(ls -t /tmp/recording/pics/*.jpg | head -1) /tmp/current.jpg
sleep 0.033 # ~30 FPS
done
Pros: Simple, no service changes
Cons: Race conditions, no metadata
Option 2: Redis Pub/Sub Subscribe to frame events if depthai_gate publishes them:
import redis
r = redis.Redis()
p = r.pubsub()
p.subscribe('frame_ready')
for message in p.listen():
print(message) # Contains frame path or metadata
Pros: Event-driven, no polling
Cons: May not exist in current firmware
9.2 Accessing Frames Without depthai_gate
Not recommended — requires implementing your own DepthAI pipeline.
If you must:
- Stop depthai_gate:
systemctl stop depthai_gate - Use Luxonis depthai Python SDK
- Create minimal pipeline:
import depthai as dai
pipeline = dai.Pipeline()
cam = pipeline.create(dai.node.ColorCamera)
cam.setResolution(dai.ColorCameraProperties.SensorResolution.THE_4_K)
cam.setIspScale(1, 2) # Downscale to 2028x1024
xout = pipeline.create(dai.node.XLinkOut)
xout.setStreamName("video")
cam.video.link(xout.input)
with dai.Device(pipeline) as device:
q = device.getOutputQueue("video")
while True:
frame = q.get()
cv2.imwrite("/tmp/frame.jpg", frame.getCvFrame())
Pros: Full control over camera
Cons: Breaks all Hivemapper services, loses ML pipeline
9.3 Minimal Path to JPEG Frame
Fastest (with existing stack):
# Via SSH
ssh -p 2222 root@localhost 'ls -t /tmp/recording/pics/*.jpg | head -1 | xargs cat' > frame.jpg
Via API (requires preview mode):
curl http://192.168.0.10:5000/api/1/preview/start
sleep 2
ssh -p 2222 root@localhost 'ls -t /tmp/recording/preview/*.jpg | head -1 | xargs cat' > frame.jpg
curl http://192.168.0.10:5000/api/1/preview/stop
9.4 Building a Custom Camera Interface
Requirements:
- Maintain depthai_gate (or reimplement VPU control)
- Expose a REST endpoint for single-frame capture
- Optionally implement MJPEG streaming
Proposed odc-api Addition:
// routes/camera.ts
router.get('/frame', async (req, res) => {
const frames = readdirSync('/tmp/recording/pics')
.filter(f => f.endsWith('.jpg'))
.sort()
.reverse();
if (frames.length === 0) {
return res.status(404).send('No frames available');
}
const framePath = join('/tmp/recording/pics', frames[0]);
res.sendFile(framePath);
});
router.get('/stream', async (req, res) => {
res.writeHead(200, {
'Content-Type': 'multipart/x-mixed-replace; boundary=frame',
'Cache-Control': 'no-cache',
});
const interval = setInterval(() => {
const frames = readdirSync('/tmp/recording/pics')
.filter(f => f.endsWith('.jpg'))
.sort()
.reverse();
if (frames.length > 0) {
const framePath = join('/tmp/recording/pics', frames[0]);
const frameData = readFileSync(framePath);
res.write('--frame\r\n');
res.write('Content-Type: image/jpeg\r\n');
res.write(`Content-Length: ${frameData.length}\r\n\r\n`);
res.write(frameData);
res.write('\r\n');
}
}, 33); // ~30 FPS
req.on('close', () => clearInterval(interval));
});
9.5 Architecture for Replacement System
┌──────────────────────────────────────────────────────────────────┐
│ VARROA CAMERA SERVICE │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ depthai_gate │ → │ varroa-camera │ → │ HTTP API │ │
│ │ (unchanged) │ │ (new service) │ │ (port 80) │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ /tmp/recording/pics/ Monitor & serve GET /frame │
│ frames via inotify GET /stream │
│ GET /landmarks │
└──────────────────────────────────────────────────────────────────┘
10. Open Questions
| Question | Priority | How to Investigate |
|---|---|---|
| Exact depthai_gate pipeline config | High | SSH in, find config files in /opt/ |
| Does depthai_gate publish to Redis? | High | redis-cli MONITOR while recording |
| Camera-bridge vs depthai_gate relationship | High | Check systemd deps, trace with strace |
| Preview config format | Medium | Read getPreviewConfig() implementation |
| ML model exact location on Bee | Medium | find /opt /data -name "*.blob" -o -name "*.onnx" |
| Frame timestamp accuracy | Medium | Compare frame timestamps to GNSS time |
Appendix A: Key File Paths
| Path | Purpose |
|---|---|
/tmp/recording/pics/ |
Live camera frames |
/tmp/recording/preview/ |
Preview mode frames |
/data/recording/cached_observations/ |
Landmark observation images |
/data/recording/framekm/ |
FrameKm upload bundles |
/data/recording/odc-api.db |
SQLite database |
/opt/camera-bridge/config.json |
Camera configuration |
/opt/depthai_gate/ |
DepthAI service (estimated) |
/opt/odc-api/ |
Node.js API service |
/sys/class/vpu/ |
VPU sysfs interface |
Appendix B: Service Dependencies
multi-user.target
│
├── redis.service [t+2s]
│
├── depthai_gate.service [t+8s] # MUST start before map-ai
│ │
│ └── Loads luxonis_vpu.bin
│
├── map-ai.service [t+12s] # Depends on depthai_gate
│ │
│ └── Privacy blur, ML inference
│
├── hivemapper-data-logger.service [t+15s]
│
└── odc-api.service [t+18s] # REST API
Appendix C: Port Reference
| Port | Service | Protocol | Binding |
|---|---|---|---|
| 22 | sshd | TCP | AP only (via socket) |
| 5000 | odc-api | HTTP | AP interface |
| 6379 | Redis | TCP | localhost |
| 8888 | mitmdump | HTTP | localhost |
| 11492 | depthai_gate | HTTP/Flask | localhost |
End of Report