230 lines
6.7 KiB
Markdown
230 lines
6.7 KiB
Markdown
# Truck Bee Access Plan
|
|
_Updated 2026-03-22 — read this before touching the Bee_
|
|
|
|
---
|
|
|
|
## Network Topology (important)
|
|
|
|
```
|
|
Cobb's phone ──── Bee AP (wlp1s0f0, 192.168.0.10) ──── phone gets 192.168.0.x
|
|
ROUTING CONFLICT on phone
|
|
(both AP and zerocool are 192.168.0.0/24)
|
|
|
|
Bee WiFi client (wlp1s0f1) ──── zerocool ──── Lucy (192.168.0.5) ──── OpenClaw
|
|
```
|
|
|
|
**Key facts:**
|
|
- sshd on Bee binds ONLY to `192.168.0.10` (AP interface) — confirmed from recon
|
|
- The reverse tunnel OUTBOUND uses `wlp1s0f1` (zerocool) — do NOT kill this interface
|
|
- Routing conflict is on Cobb's PHONE (both AP and zerocool are 192.168.0.0/24)
|
|
- Killing wlp1s0f1 kills zerocool → kills the tunnel path → wrong
|
|
|
|
---
|
|
|
|
## Step 1 — Get Clean Access
|
|
|
|
### 1a. Phone connects to Bee AP
|
|
Connect to `dashcam-4A928016A02C1046`, SSH to `root@192.168.0.10`
|
|
|
|
### 1b. Start reverse tunnel FROM THE BEE immediately
|
|
Run this on the Bee before the routing conflict kicks you off:
|
|
```bash
|
|
ssh -R 2222:192.168.0.10:22 -N -o StrictHostKeyChecking=no root@192.168.0.5 &
|
|
```
|
|
- Goes OUTBOUND via wlp1s0f1 (zerocool) to Lucy
|
|
- AP interface not involved in this path
|
|
- Even if your phone SSH session dies, tunnel stays alive
|
|
- Lucy will show `127.0.0.1:2222` listening
|
|
|
|
**Auth requirement:** Bee needs a key that Lucy's `root` authorized_keys accepts.
|
|
- Check what's in `/root/.ssh/` on the Bee
|
|
- If nothing: during the phone session, generate a key on Bee and add pubkey to Lucy's authorized_keys
|
|
|
|
### 1c. Verify from OpenClaw
|
|
```bash
|
|
ssh lucy "ss -tlnp | grep 2222"
|
|
# Should show: LISTEN 0 128 127.0.0.1:2222
|
|
```
|
|
|
|
---
|
|
|
|
## Step 2 — Read-Only Recon (NO WRITES)
|
|
|
|
### 2a. Storage inventory
|
|
```bash
|
|
df -h
|
|
du -sh /data/recording/*/
|
|
sqlite3 /data/odc-api.db ".tables"
|
|
sqlite3 /data/odc-api.db ".schema framekms"
|
|
sqlite3 /data/odc-api.db "SELECT COUNT(*) FROM framekms;"
|
|
ls /data/recording/ml_metadata/ | head -20
|
|
cat $(ls /data/recording/ml_metadata/ | head -1) 2>/dev/null
|
|
```
|
|
|
|
### 2b. Redis — find detection keys
|
|
```bash
|
|
redis-cli keys "*"
|
|
# Look specifically for detection/landmark keys:
|
|
redis-cli keys "*landmark*"
|
|
redis-cli keys "*detection*"
|
|
redis-cli keys "*sign*"
|
|
redis-cli keys "*ai*"
|
|
# Check GNSSFusion30Hz (may not appear until Bee has been running a while):
|
|
redis-cli type GNSSFusion30Hz 2>/dev/null
|
|
redis-cli zrevrange GNSSFusion30Hz 0 2 2>/dev/null
|
|
```
|
|
|
|
### 2c. Find detection key in odc-api source
|
|
```bash
|
|
grep -in "redis\|landmark\|detection\|zadd\|rpush\|publish" /opt/odc-api/odc-api-bee.js | head -40
|
|
```
|
|
|
|
### 2d. Find detection key in map-ai source
|
|
```bash
|
|
ls /opt/map-ai/
|
|
grep -in "redis\|landmark\|detection\|zadd\|rpush\|publish" /opt/map-ai/map-ai.py 2>/dev/null | head -40
|
|
```
|
|
|
|
### 2e. Frame storage format
|
|
```bash
|
|
ls /tmp/recording/pics/ | head -5
|
|
ls /tmp/recording/pics/ | wc -l
|
|
```
|
|
|
|
### 2f. SSH keys on Bee
|
|
```bash
|
|
ls -la /root/.ssh/ 2>/dev/null
|
|
cat /root/.ssh/authorized_keys 2>/dev/null
|
|
ls /root/.ssh/id_* 2>/dev/null
|
|
```
|
|
|
|
### 2g. map-ai service file
|
|
```bash
|
|
systemctl cat map-ai.service
|
|
```
|
|
|
|
---
|
|
|
|
## Step 3 — Decisions Based on Recon
|
|
|
|
| Finding | Decision |
|
|
|---------|----------|
|
|
| Detection Redis key found | Forwarder polls Redis directly |
|
|
| No detection Redis key | Use ml_metadata files or poll odc-api at low frequency |
|
|
| ml_metadata has detection files | Primary source, tail by mtime |
|
|
| Large stored framekm backlog | Plan backfill to ADAMaps before liberation |
|
|
|
|
---
|
|
|
|
## Step 4 — Liberation (v0.6)
|
|
|
|
### Kill list
|
|
```
|
|
hivemapper-data-logger ← MUST — the uploader
|
|
mitmproxy ← MUST — Hivemapper proxy
|
|
beekeeper-plugin ← kill — Hivemapper telemetry
|
|
here-plugin ← kill — HERE Maps
|
|
mender-client ← kill — OTA updates (USB recovery still works)
|
|
odc-api ← kill — Node.js bloat (we read Redis/files directly)
|
|
```
|
|
|
|
### Keep list
|
|
```
|
|
redis ← IPC backbone
|
|
depthai_gate ← Camera hardware init
|
|
map-ai ← ML inference — THIS IS THE VALUE
|
|
jpeg-recorder ← Frame storage
|
|
video-processor ← Frame pipeline
|
|
RedisHandler ← Sensor fusion
|
|
datalogger ← GPS/IMU logging to SQLite
|
|
hostapd / dnsmasq ← AP + DHCP
|
|
```
|
|
|
|
### New service: adacam-forwarder (rewritten)
|
|
- Polls detection Redis key for new entries
|
|
- Grabs JPEG from `/tmp/recording/pics/` by timestamp
|
|
- POSTs to ADAMaps `/api/ingest` + `/api/images`
|
|
- Tracks state in `/data/adacam/forwarder-state.json`
|
|
- Runs every 30s, pure Python, minimal CPU
|
|
|
|
### systemd drop-in (removes odc-api dep from map-ai)
|
|
```ini
|
|
# /etc/systemd/system/map-ai.service.d/no-odc-api.conf
|
|
[Unit]
|
|
Requires=redis.service
|
|
# Overrides Requires=odc-api.service from base unit
|
|
```
|
|
|
|
### SSH keys
|
|
Drop to `/root/.ssh/authorized_keys`:
|
|
```
|
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOQxwJU91TCxds34P18D3xRbu7rxlrgTUoml/H8nxeDK kayos@openclaw
|
|
```
|
|
|
|
### Domain blocks (/etc/hosts)
|
|
```
|
|
0.0.0.0 data.api.hivemapper.com
|
|
0.0.0.0 api.hivemapper.com
|
|
0.0.0.0 edge.hereapi.com
|
|
0.0.0.0 direct.data.api.platform.here.com
|
|
0.0.0.0 account.api.here.com
|
|
0.0.0.0 mender.io
|
|
0.0.0.0 s3.amazonaws.com
|
|
```
|
|
|
|
### Do NOT touch
|
|
- `/etc/ssh/sshd_config`
|
|
- AP config / SSID / IP
|
|
- Firewall (no rules yet)
|
|
|
|
---
|
|
|
|
## Step 5 — Test
|
|
|
|
1. `redis-cli get MAP_AI_READY` → should be "True"
|
|
2. Check forwarder log → detections posting to ADAMaps
|
|
3. Verify no Hivemapper traffic (`nmap` or check `/etc/hosts` working)
|
|
4. Check `/data/adacam/forwarder-state.json` updating
|
|
|
|
---
|
|
|
|
## Step 6 — bee-tunnel.service (permanent remote access)
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=AdaCam Reverse Tunnel to Lucy
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=/usr/bin/ssh -N \
|
|
-R 2222:192.168.0.10:22 \
|
|
-o StrictHostKeyChecking=no \
|
|
-o ServerAliveInterval=30 \
|
|
-o ServerAliveCountMax=3 \
|
|
-o ExitOnForwardFailure=yes \
|
|
root@192.168.0.5
|
|
Restart=always
|
|
RestartSec=30
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
Goes outbound via wlp1s0f1 (zerocool) — AP interface not involved.
|
|
|
|
---
|
|
|
|
## Known Issues
|
|
|
|
| Issue | Notes |
|
|
|-------|-------|
|
|
| sshd binds to 192.168.0.10 only | Reverse tunnel must use `192.168.0.10:22` not `localhost:22` |
|
|
| Routing conflict on phone | AP + zerocool both 192.168.0.0/24 — start tunnel BEFORE conflict kicks you |
|
|
| wlp1s0f1 must stay UP | It's the zerocool path — tunnel dies without it |
|
|
| depthai-device-kb at 98% CPU | Normal — VPU running ML inference |
|
|
| rngd at 20% CPU | Investigate — may be killable |
|
|
| Redis localhost:6379 only | Must be on Bee or tunneled in to query |
|
|
| GNSSFusion30Hz absent at boot | Appears after GNSS warms up (~5-10 min) |
|
|
| Bee has stored framekm backlog | Plan backfill to ADAMaps |
|
|
| Bee-to-Lucy auth key unknown | Resolve during first phone session |
|