Files
dwarf-go/dwarfctl/README.md
Jacquin Antoine c2f9e54eb4 Add camera streaming guide with all access methods
Comprehensive documentation for accessing the DWARF camera streams:
- RTSP URLs and channels (ch0=tele, ch1=wide)
- The critical prerequisite: camera must be opened via WebSocket first
- ffmpeg commands for frame capture, timelapse, and video recording
- mpv and VLC usage with TCP transport
- Python/OpenCV integration example
- Troubleshooting common issues (black image, connection refused, VLC delay)
- Comparison of RTSP vs MJPEG modes across device models

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
2026-07-13 19:56:04 +02:00

170 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# dwarfctl — Open-source DWARF telescope control CLI
A Go command-line tool for controlling **DWARF II** (and upcoming DWARF III)
smart telescopes over Wi-Fi via their WebSocket API.
Built from reverse-engineered protocol specs (see `../analysis/`).
## Quick start
```bash
make build
./dwarfctl --ip 192.168.1.100 state
```
## Prerequisites
The telescope must be connected to your Wi-Fi (or your phone joined to the
telescope's AP hotspot). Once you can ping the telescope's IP, `dwarfctl` can
reach it.
Find the IP from:
- The official DWARFLAB app's Settings → My Device
- Your router's DHCP table (hostname like `DWARFxxxx`)
- The BLE handshake (see `../analysis/API_REFERENCE.md`)
## Usage examples
```bash
# Device state
dwarfctl --ip 192.168.1.100 state
# Camera
dwarfctl camera open --cam tele
dwarfctl camera photo --cam tele
dwarfctl camera photo --cam wide --raw
dwarfctl camera burst start --cam tele
dwarfctl camera exp --cam tele 156 # 1/4s exposure
dwarfctl camera gain --cam tele 60
dwarfctl camera params --cam tele
# Motor / slew
dwarfctl motor slew 90 0.5 # angle 90°, half speed
dwarfctl motor stop 0 # stop RA motor
dwarfctl motor goto 0 45.0 5.0 # RA motor to 45° at speed 5
# Astrophotography
dwarfctl astro calibrate start
dwarfctl astro goto-dso 10.6847 41.2687 "M31 Andromeda"
dwarfctl astro goto-solar 3 # Earth = index 3
dwarfctl astro stack start
dwarfctl astro eq-solve start # polar alignment
# Focus
dwarfctl focus auto
dwarfctl focus step 1 # 1=out, 0=in
dwarfctl focus astro-af start
# Tracking
dwarfctl track start 640 360 100 100 0 # bbox at center of tele cam
dwarfctl track stop
# System
dwarfctl system sync-time
dwarfctl system set-location 48.8566 2.3522 35
# Power
dwarfctl power rgb-on
dwarfctl power rgb-off
dwarfctl power reboot
dwarfctl power off
# Monitor notifications (live status events)
dwarfctl monitor
# Visual odometry — image-based orientation (no star/plate solving)
dwarfctl orient compare before.jpg after.jpg # measure rotation between 2 frames
dwarfctl orient live --cam wide # live pointing tracker from RTSP
dwarfctl orient live --fov-h 42 --fov-v 24 # override FoV with measured values
```
## Architecture
```
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
│ ├── api/
│ │ ├── commands.go # 323 command IDs + module routing
│ │ └── client.go # typed Telescope API (camera/motor/astro/...)
│ └── odometry/ # FFT phase-correlation visual odometry
│ ├── fft.go # radix-2 Cooley-Tukey FFT (1D + 2D)
│ ├── odometry.go # Estimate() — shift between 2 frames → degrees
│ └── tracker.go # Tracker — cumulative orientation integrator
└── cmd/dwarfctl/main.go # cobra CLI
```
### Protocol summary
| Layer | Transport | Port |
|-------|-----------|------|
| Control | WebSocket (binary protobuf) | 9900 |
| Preview | RTSP (not implemented here) | 554 |
Every command is a serialized `WsPacket{major=2, minor=3, device_id,
module_id, cmd, type, data, client_id}`. The `module_id` is derived from `cmd`
by range. See `../analysis/API_REFERENCE.md` for details.
## Regenerating protos
If the proto definitions change:
```bash
# From the APK analysis directory:
python3 ../analysis/extract_protos.py ../extracted/jadx/.../proto ../analysis/protos
# Merge into unified proto:
cd dwarfctl/proto
python3 merge.py . dwarf.proto
protoc --go_out=. --go_opt=paths=source_relative dwarf.proto
```
## Roadmap
- [x] **Visual odometry** — image-based orientation via FFT phase correlation (`orient`)
- [ ] BLE discovery + handshake (DwarfPing/DwarfEcho)
- [ ] RTSP preview viewer
- [ ] Interactive REPL mode
- [ ] Schedule plan management
- [ ] OTA firmware update
- [ ] Full Notify event parsing (typed)
- [ ] Closed-loop tracking: feed `orient` output into motor corrections
## Visual odometry (`orient`)
The `orient` command estimates the telescope's pointing rotation by comparing
wide-angle frames using **FFT phase correlation**. It does NOT use star
identification or plate solving — it works on any textured scene (sky, horizon,
clouds, daytime landscape), making it suitable for:
- **Daytime airplane tracking** — the wide cam sees sky/horizon texture
- **Nighttime satellite tracking** — the wide cam sees star fields as texture
### How it works
1. Grab two wide-angle frames (via RTSP `ffmpeg` grab, same as `preview grab`)
2. Downscale both to a square grid (default 256×256, power of two)
3. Compute the 2-D FFT of each, then the normalized cross-power spectrum
4. The inverse FFT gives a correlation surface; its peak = image-plane shift
5. Sub-pixel refinement via parabolic interpolation
6. Convert pixel shift → degrees using the camera field of view
For a static alt-az mount, the accumulated shifts give the cumulative pointing
orientation relative to the starting frame — no absolute encoders or polar
alignment needed.
### Field of view calibration
The default FoV (8.0°×6.5°) comes from the DWARF Mini's display values in
`DEVICE_MODELS.md`, but the firmware-reported live FoV can differ. To calibrate:
slew the motors by a known angle and compare with the measured rotation. Override
with `--fov-h` / `--fov-v` once you have measured values.
### Prerequisites
- **ffmpeg** must be installed (for RTSP frame capture)
- The wide camera must be opened first (`camera open --cam wide`) — `orient live`
does this automatically.