diff --git a/dwarfctl/README.md b/dwarfctl/README.md index ecf25e0..4dd8131 100644 --- a/dwarfctl/README.md +++ b/dwarfctl/README.md @@ -85,17 +85,100 @@ dwarfctl/ ├── proto/dwarf.proto # unified proto3 definitions (397 messages) ├── proto/dwarf.pb.go # generated Go bindings (24948 lines) ├── internal/ -│ ├── transport/client.go # WebSocket client + WsPacket envelope +│ ├── transport/client.go # WebSocket client + WsPacket envelope + heartbeat │ ├── api/ │ │ ├── commands.go # 323 command IDs + module routing │ │ └── client.go # typed Telescope API (camera/motor/astro/...) +│ ├── daemon/ # persistent server with HTTP control API +│ │ ├── server.go # WebSocket + camera + odometry manager +│ │ └── client.go # thin HTTP client for the daemon +│ ├── rtspgrab/ # RTSP frame capture via ffmpeg │ └── odometry/ # FFT phase-correlation visual odometry │ ├── fft.go # radix-2 Cooley-Tukey FFT (1D + 2D) -│ ├── odometry.go # Estimate() — shift between 2 frames → degrees +│ ├── odometry.go # Estimate() — translation + rotation +│ ├── rotation.go # log-polar phase correlation (rotation only) +│ ├── rotate.go # image rotation for de-rotation pass │ └── tracker.go # Tracker — cumulative orientation integrator └── cmd/dwarfctl/main.go # cobra CLI ``` +## Daemon mode + +The `serve` subcommand runs dwarfctl as a **persistent background service** that +keeps the WebSocket connection, camera, and odometry tracker alive — exposing a +local HTTP API for short-lived clients to query state or issue commands without +reconnecting each time. + +```bash +# Start the daemon (connects to telescope, opens camera, starts odometry loop) +dwarfctl serve --ip 192.168.88.1 --cam wide + +# With custom settings +dwarfctl serve --ip 192.168.88.1 --cam wide --addr 127.0.0.1:7777 \ + --interval 5s --fov-h 8.0 --fov-v 6.5 +``` + +### How it works + +1. Connects to the telescope WebSocket (port 9900) and keeps it alive with + periodic ping/pong heartbeats +2. Switches to shooting mode 1 (photo/preview), then opens the camera — this + activates the RTSP server +3. Starts the odometry loop: grabs frames at the configured interval, feeds + them to the Tracker, logs cumulative orientation +4. Serves the HTTP API on the configured address until SIGTERM/SIGINT + +The odometry loop **auto-pauses** during motor slew (to avoid motion blur) +and resumes after a settle delay (default 3 s). You can also pause and +resume it manually via the HTTP API. + +### HTTP API + +All endpoints are relative to the daemon address (default `http://127.0.0.1:7777`). + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/health` | Daemon status, IP, camera state | +| `GET` | `/orientation` | Cumulative pan/tilt/rotation in degrees | +| `GET` | `/grab?path=/tmp/x.jpg&raw=1` | Capture RTSP frame (returns path or raw JPEG) | +| `POST` | `/reset` | Zero the odometry tracker | +| `POST` | `/camera?action=open&cam=wide` | Open or close a camera | +| `POST` | `/slew` | Slew joystick (`{"angle":90,"length":0.5}`) | +| `POST` | `/stop` | Stop all motors | +| `GET` | `/pause` | Pause odometry frame capture | +| `GET` | `/resume` | Resume odometry frame capture | +| `POST` | `/fov` | Override FoV (`{"h":8.0,"v":6.5}`) | + +### Using the daemon client + +The `--daemon` flag points CLI commands at a running daemon instead of connecting +directly to the telescope: + +```bash +# Terminal 1: start daemon +dwarfctl serve --ip 192.168.88.1 + +# Terminal 2: query orientation via daemon +dwarfctl --daemon 127.0.0.1:7777 state + +# Or use curl directly +curl http://127.0.0.1:7777/orientation +curl http://127.0.0.1:7777/health +curl -X POST http://127.0.0.1:7777/slew -d '{"angle":90,"length":0.3}' +``` + +### systemd deployment + +A systemd unit is provided in `deploy/dwarfctl.service`. Install it with: + +```bash +sudo cp deploy/dwarfctl.service /etc/systemd/system/ +sudo systemctl daemon-reload +sudo systemctl enable --now dwarfctl +``` + +Edit the unit to adjust `--ip`, `--cam`, and `--addr` to match your setup. + ### Protocol summary | Layer | Transport | Port |