Reverse-engineer DWARF II telescope API and build open-source Go client
Complete reverse-engineering of the DWARFLAB Android app (v3.4.0) protocol
and implementation of a working CLI tool to control DWARF II telescopes.
Analysis (from APK decompilation with jadx):
- Extracted 17 protobuf definitions (382 messages) from embedded descriptors
- Mapped all 323 WebSocket command IDs across 16 modules
- Documented the full protocol: BLE discovery, WebSocket control (port 9900),
RTSP preview, WsPacket envelope (proto v2.3)
- Documented the Android UI structure (screens, navigation, shooting modes)
- Key discovery: telescope responds with type=3 (reply), not type=1 (response),
and several commands are fire-and-forget (RGB, camera open/close)
dwarfctl Go client:
- Protobuf bindings generated from extracted .proto files (397 messages)
- WebSocket transport layer with request-response matching and notification fan-out
- Typed API covering cameras, motors, astrophotography, focus, tracking, system, power
- Cobra CLI with 30+ subcommands and --debug traffic logging
- 57 unit tests (transport round-trip, command routing, proto encoding)
- Validated on real hardware: state, photo, motor slew (all directions/speeds),
focus, RGB, time/location sync all confirmed working
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# Binaries
|
||||||
|
DWARFLAB.apk
|
||||||
|
*.apk
|
||||||
|
dwarfctl/dwarfctl
|
||||||
|
|
||||||
|
# Large extracted/decompiled artifacts (regenerable)
|
||||||
|
extracted/
|
||||||
|
tools/
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Go
|
||||||
|
*.test
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
109
AGENTS.md
Normal file
109
AGENTS.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# AGENTS.md — DWARFLAB APK reverse-engineering workspace
|
||||||
|
|
||||||
|
This directory reverse-engineers the DWARFLAB Android app to document the
|
||||||
|
DWARF II telescope control protocol for an open-source client.
|
||||||
|
|
||||||
|
## What's here
|
||||||
|
|
||||||
|
```
|
||||||
|
DWARFLAB.apk original APK (v3.4.0, com.convergence.dwarflab)
|
||||||
|
tools/jadx/ jadx 1.5.6 decompiler (run tools/jadx/bin/jadx)
|
||||||
|
extracted/raw/ unzip of the APK (dex, assets, lib/*.so, manifest)
|
||||||
|
extracted/jadx/ jadx decompiled Java sources (23968 classes)
|
||||||
|
analysis/
|
||||||
|
extract_protos.py regenerates clean .proto from jadx *Proto.java
|
||||||
|
protos/ 17 recovered .proto files (382 messages) ← THE API
|
||||||
|
CMD_TABLE.md all 323 command ids ↔ modules (auto-generated)
|
||||||
|
API_REFERENCE.md full protocol spec (read this first)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Start with `analysis/API_REFERENCE.md`** — it explains BLE discovery →
|
||||||
|
WebSocket control (port 9900) → RTSP preview, the `WsPacket` envelope, and how
|
||||||
|
command routing works.
|
||||||
|
|
||||||
|
## The protocol in one paragraph
|
||||||
|
|
||||||
|
Phone discovers telescope over **BLE** (`ble.proto`, gets IP/SSID/PSK via
|
||||||
|
`DwarfEcho`), joins its Wi-Fi, opens `ws://<ip>:9900/?client_id=<id>`, then sends
|
||||||
|
**binary protobuf `WsPacket`** frames `{major=2, minor=3, device_id, module_id,
|
||||||
|
cmd, type, data, client_id}`. `cmd` (10000–17099) selects the operation;
|
||||||
|
`module_id` is *derived* from `cmd` by range; `data` is a serialized inner proto
|
||||||
|
(`Req*`/`Res*`). Live preview is a separate **RTSP** stream (`stream0`).
|
||||||
|
|
||||||
|
## Commands for working here
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Re-decompile (only if APK changes)
|
||||||
|
tools/jadx/bin/jadx --show-bad-code --deobf -d extracted/jadx DWARFLAB.apk
|
||||||
|
|
||||||
|
# Regenerate .proto files after re-decompile
|
||||||
|
python3 analysis/extract_protos.py \
|
||||||
|
extracted/jadx/sources/com/convergence/dwarflab/proto analysis/protos
|
||||||
|
|
||||||
|
# Regenerate the command table
|
||||||
|
python3 -c "…" # see the inline script that built analysis/CMD_TABLE.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Both extractors are deterministic — re-running after a new APK version produces a
|
||||||
|
clean diff for tracking protocol changes.
|
||||||
|
|
||||||
|
## Where things live in the decompiled source
|
||||||
|
|
||||||
|
All paths relative to `extracted/jadx/sources/`.
|
||||||
|
|
||||||
|
| Looking for… | Go to… |
|
||||||
|
|---|---|
|
||||||
|
| Protobuf message definitions | `com/convergence/dwarflab/proto/*Proto.java` → run extractor → `analysis/protos/` |
|
||||||
|
| All command IDs | `com/convergence/dwarflab/data/bean/p021ws/WsCmd.java` |
|
||||||
|
| Module enum (camera/astro/motor…) | `…/p021ws/WsModuleId.java` |
|
||||||
|
| Message type enum (req/resp/notify) | `…/p021ws/WsMessageType.java` |
|
||||||
|
| Request interface + sender | `…/p021ws/request/WsMessageReq.java`, `p000/d49.java` |
|
||||||
|
| WsPacket envelope builder | `p000/e49.java` (`C9312a.m36361a`) |
|
||||||
|
| WebSocket connection / URL / port | `p000/v55.java` (field `f43155b`, method `m55420t`) |
|
||||||
|
| OkHttp WebSocket wrapper | `p000/b49.java` |
|
||||||
|
| Inbound dispatch / req-resp matching | `com/convergence/dwarflab/data/websocket/WsRequestHandle.java`, `WsResponseHandle.java` |
|
||||||
|
| Per-module handlers | `com/convergence/dwarflab/data/websocket/<module>/*WsResponseHandle.java` |
|
||||||
|
| RTSP preview player | `com/convergence/dwarflab/media/RtspPlayerView.java`, `…/activity/capture/CaptureActivity.java` |
|
||||||
|
| BLE handshake | `com/convergence/dwarflab/data/bluetooth/`, `…/data/bean/ble/` |
|
||||||
|
| Camera param value maps | APK `assets/params_range.json`, `assets/shoot_plan_config.json` |
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **`p000/` is the obfuscated package.** R8 minification collapsed most app
|
||||||
|
internals into 1–4 char names there (`v55`, `b49`, `e49`, `d49`, `jc0`…).
|
||||||
|
Kotlin metadata comments (`@Metadata(d2={…})`) often still carry the original
|
||||||
|
readable names — read them when a class is opaque.
|
||||||
|
- **`module_id` is never stored** on a command — it is computed by range checks
|
||||||
|
in `WsCmd.getModuleId()`. Don't grep for "set module id"; read that method.
|
||||||
|
- **Some command IDs appear as symbolic constants** in `WsCmd.java` (jadx didn't
|
||||||
|
inline them). Resolved values: `IMediaPlayer.MEDIA_INFO_*` = 10004/10006/10008/10009,
|
||||||
|
`RequestManager.NOTIFY_CONNECT_*` = 10011/10012/10013, `ComposeVersion.version`
|
||||||
|
= 13000, `FirebaseError.ERROR_INVALID_CUSTOM_TOKEN` = 17000,
|
||||||
|
`ERROR_CUSTOM_TOKEN_MISMATCH` = 17002. These are already resolved in
|
||||||
|
`CMD_TABLE.md`.
|
||||||
|
- **Notifications outnumber requests.** ~130 of the 323 cmds are `CMD_NOTIFY_*`
|
||||||
|
(15200–15303). They are server-pushed (`type=2`), not requestable. An OSS
|
||||||
|
client must subscribe to them for live state.
|
||||||
|
- **Two telescopes share one app.** "DWARF II" (current, id 1) and "Bilbo"
|
||||||
|
(codename for the next model, likely DWARF III) appear in `shoot_plan_config.json`
|
||||||
|
and `www/modules/eq/indexBilbo.html`. Capability detection should key off
|
||||||
|
`StationModel` from `DwarfEcho`, not hardcode.
|
||||||
|
- **`type` field (WsMessageType):** request=0, response=1, notification=2,
|
||||||
|
reply=3. Responses usually reuse the request's `cmd`; match on `cmd`.
|
||||||
|
- **RTSP uses TCP.** The app sets `rtsp_transport=tcp` (`RtspPlayerView.java:195`).
|
||||||
|
Path is `rtsp://<ip>/<stream_selector>/stream0`.
|
||||||
|
- **jadx reports ~294 decompile errors** out of ~24k classes — expected and
|
||||||
|
irrelevant for the proto/command extraction (those come from clean descriptor
|
||||||
|
data, not decompiled bodies).
|
||||||
|
|
||||||
|
## Conventions when extending this analysis
|
||||||
|
|
||||||
|
- Keep generated artifacts regenerable: `extract_protos.py` + the CMD_TABLE
|
||||||
|
inline script read only from `extracted/jadx`. Never hand-edit `protos/` or
|
||||||
|
`CMD_TABLE.md`.
|
||||||
|
- When a command's payload type is unclear, find the `WsMessageReq` subclass in
|
||||||
|
`data/bean/p021ws/request/` — `getMessage()` returns the proto, `getCmd()`
|
||||||
|
returns the `WsCmd`.
|
||||||
|
- Cloud/relay features (`app.dwarflabapp.com/uls`, NetEase IM `nim/`, Huawei HMS,
|
||||||
|
Firebase analytics, Meizu push, ByteDance ASR) are NOT part of telescope
|
||||||
|
control — ignore them unless working on remote/cloud access.
|
||||||
323
analysis/API_REFERENCE.md
Normal file
323
analysis/API_REFERENCE.md
Normal file
@ -0,0 +1,323 @@
|
|||||||
|
# DWARFLAB Telescope — API Reference (reverse-engineered)
|
||||||
|
|
||||||
|
Reverse-engineered from `DWARFLAB.apk` v3.4.0 (build 629), package `com.convergence.dwarflab`.
|
||||||
|
This document describes the protocol used by the official Android app to talk to
|
||||||
|
DWARF II (and the in-development "Bilbo"/DWARF III) smart telescopes.
|
||||||
|
|
||||||
|
> Goal: enable an open-source client implementation. All command IDs, the wire
|
||||||
|
> envelope, and the inner protobuf payloads were recovered from the APK; nothing
|
||||||
|
> here is guessed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Architecture at a glance
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────┐ BLE (GATT) ┌───────────┐
|
||||||
|
│ Phone app │ ───────────────▶ │ Telescope │ 1. discovery + Wi-Fi creds exchange
|
||||||
|
│ │ ◀── DwarfEcho ── │ │ (DwarfPing / DwarfEcho, see ble.proto)
|
||||||
|
└──────┬──────┘ └─────┬─────┘
|
||||||
|
│ joins telescope Wi-Fi │
|
||||||
|
│ (AP mode, or shared STA) │
|
||||||
|
│ │
|
||||||
|
│ WebSocket (binary) │ RTSP (TCP)
|
||||||
|
│ ws://<ip>:9900/?client_id=.. │ rtsp://<ip>/<cam>/stream0
|
||||||
|
▼ ▼
|
||||||
|
┌───────────────────────────┐ ┌──────────────┐
|
||||||
|
│ Control plane │ │ Live preview │
|
||||||
|
│ WsPacket (protobuf) │ │ ijkplayer / │
|
||||||
|
│ 323 commands, 17 modules │ │ ExoPlayer │
|
||||||
|
└───────────────────────────┘ └──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
Two distinct data planes:
|
||||||
|
|
||||||
|
| Plane | Transport | Port | Encoding | Purpose |
|
||||||
|
|-------|-----------|------|----------|---------|
|
||||||
|
| **Control** | WebSocket (binary frames) | **9900** | protobuf `WsPacket` envelope | All telescope commands & status |
|
||||||
|
| **Preview** | RTSP over TCP | 554 (std) | H.264/H.265 | Live camera viewfinder |
|
||||||
|
| **Discovery** | BLE GATT | — | protobuf (`ble.proto`) | Find telescope, get IP/SSID/PSK |
|
||||||
|
|
||||||
|
There is also a **cloud relay**: `https://app.dwarflabapp.com/app/uls/connect?d=…`
|
||||||
|
("ULS") used for remote access when the phone is not on the telescope's Wi-Fi.
|
||||||
|
Local LAN control (the focus of an OSS client) needs only BLE + WebSocket + RTSP.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Connection flow
|
||||||
|
|
||||||
|
### 2.1 Discovery & credentials (BLE)
|
||||||
|
The telescope advertises over BLE. The app sends a `DwarfPing` / `ReqGetconfig`
|
||||||
|
and receives a **`DwarfEcho`** (`ble.proto`) containing everything needed to
|
||||||
|
connect over IP:
|
||||||
|
|
||||||
|
```proto
|
||||||
|
message DwarfEcho {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
uint64 timestamp = 2;
|
||||||
|
bytes magic = 3;
|
||||||
|
uint64 ts_ping = 4;
|
||||||
|
bytes mac_address = 5;
|
||||||
|
StationModel model = 6; // telescope family + revision
|
||||||
|
string sn = 7; // serial number
|
||||||
|
string name = 8; // advertised name
|
||||||
|
string psw = 9; // device password
|
||||||
|
string fw_version = 10;
|
||||||
|
string ws_scheme = 11; // "ws" or "wss"
|
||||||
|
uint32 session = 12;
|
||||||
|
NifAP ap = 13; // AP network (ifname/ssid/psw/ipv4/ipv6)
|
||||||
|
NifSTA sta = 14; // STA network (ifname/ssid/psw/rssi/ipv4/ipv6)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`ble_psd` (BLE password) + `client_id` authenticate the BLE requests
|
||||||
|
(`ReqGetconfig`, `ReqSta`, `ReqAp`, `ReqSetblewifi`). Responses carry the
|
||||||
|
**`ip`** field (`ResGetconfig.ip` / `ResSta.ip`) that the app feeds into the
|
||||||
|
WebSocket URL.
|
||||||
|
|
||||||
|
### 2.2 WebSocket control channel
|
||||||
|
Once the phone is on the telescope's network:
|
||||||
|
|
||||||
|
```
|
||||||
|
ws://<telescope_ip>:9900/?client_id=<client_id>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Plain `ws://` by default; `wss://` if `ws_scheme == "wss"`.
|
||||||
|
- `client_id` is a client-generated identifier (`y32…m58158c()`).
|
||||||
|
- Source: `v55.java` field `f43155b` / method `m55420t(ip)`.
|
||||||
|
- **device_id** field in the envelope selects which telescope (multi-device),
|
||||||
|
defaults to `1` for the first/only connected scope.
|
||||||
|
|
||||||
|
### 2.3 RTSP preview
|
||||||
|
```
|
||||||
|
rtsp://<telescope_ip>/<stream_selector>/stream0
|
||||||
|
```
|
||||||
|
- `<stream_selector>` comes from `StreamTypeAnn` (`com.convergence.dwarflab.data.bean.camera`).
|
||||||
|
- Player options force `rtsp_transport = tcp` (see `RtspPlayerView.java:195`).
|
||||||
|
- Two cameras exist: **Tele** (main/long-focus) and **Wide** (wide-angle/guide).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Wire format — `WsPacket` envelope
|
||||||
|
|
||||||
|
Every WebSocket binary frame is **one serialized `WsPacket`** (`base.proto`):
|
||||||
|
|
||||||
|
```proto
|
||||||
|
message WsPacket {
|
||||||
|
uint32 major_version = 1; // = 2 (WS_MAJOR_VERSION_NUMBER)
|
||||||
|
uint32 minor_version = 2; // = 3 (WS_MINOR_VERSION_NUMBER) → protocol v2.3
|
||||||
|
uint32 device_id = 3; // telescope index, default 1
|
||||||
|
uint32 module_id = 4; // derived from cmd (see §4)
|
||||||
|
uint32 cmd = 5; // operation id (10000–17099)
|
||||||
|
uint32 type = 6; // 0=request 1=response 2=notification 3=reply
|
||||||
|
bytes data = 7; // inner protobuf message, serialized
|
||||||
|
string client_id = 8; // same client_id as the WS URL
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirmed build code (`e49.java`, `C9312a.m36361a`):
|
||||||
|
```java
|
||||||
|
WsPacket.newBuilder()
|
||||||
|
.setMajorVersion(2)
|
||||||
|
.setMinorVersion(3)
|
||||||
|
.setDeviceId(connectedDeviceId != null ? connectedDeviceId : 1)
|
||||||
|
.setModuleId(wsCmd.getModuleId().ordinal()) // derived from cmd range
|
||||||
|
.setCmd(wsCmd.getCmd())
|
||||||
|
.setType(wsCmd.getMessageType().ordinal()) // request=0
|
||||||
|
.setData(ByteString.copyFrom(innerProto.toByteArray()))
|
||||||
|
.setClientId(clientId)
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
`type` enum (`WsMessageType`): `request=0`, `response=1`, `notification=2`, `reply=3`.
|
||||||
|
|
||||||
|
### 3.1 Request/response matching
|
||||||
|
Responses are matched by **`cmd`**. The app registers a pending continuation
|
||||||
|
keyed by the expected response `cmd`; an incoming `WsPacket` whose `cmd` matches
|
||||||
|
is parsed (`WsRequestHandle.mo7785d` → `BaseProto.WsPacket.parseFrom`, then the
|
||||||
|
inner `data` is parsed into the expected proto class).
|
||||||
|
|
||||||
|
For most commands the **response uses the same `cmd`** as the request
|
||||||
|
(`WsMessageReq.getResponseCmd()` defaults to `getCmd()`, see `d49.m35708a`).
|
||||||
|
|
||||||
|
**IMPORTANT — discovered via live testing (not in the APK code):**
|
||||||
|
The telescope uses **`type=3` (REPLY)** for direct responses, not `type=1`
|
||||||
|
(RESPONSE). Additionally, not all commands get a reply:
|
||||||
|
|
||||||
|
| Response model | Commands (tested) | Implementation |
|
||||||
|
|---------------|-------------------|----------------|
|
||||||
|
| **type=3 reply (same cmd)** | photo (10002), photo wide (12022), focus auto (15000), focus step (15001), state (16405), sync-time (13000), set-location (13010) | request-response with timeout |
|
||||||
|
| **notification only (type=2)** | RGB on/off (13500/13501), camera open/close (10000/10001), camera params GET (10036) | fire-and-forget; verify via `state` |
|
||||||
|
| **fire-and-forget native** | motor slew (14006), motor stop (14002) | no ack expected |
|
||||||
|
|
||||||
|
Commands that only produce notifications still execute successfully — the
|
||||||
|
state change is visible in `GetDeviceState` (e.g. `rgb_state:{}` after RGB off).
|
||||||
|
|
||||||
|
### 3.2 Notifications
|
||||||
|
The telescope pushes `WsPacket` frames with `type=2` (notification) and `cmd` in
|
||||||
|
the **15200–15303** range (`CMD_NOTIFY_*`). An OSS client must listen for these
|
||||||
|
to reflect state changes (track results, burst/record progress, temperatures,
|
||||||
|
calibration state, SD-card info, power, etc.). See `Notify.proto` (81 messages)
|
||||||
|
and `CMD_TABLE.md` (NOTIFY module).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Command routing
|
||||||
|
|
||||||
|
`module_id` is **not** stored per-command — it is derived from `cmd` by range
|
||||||
|
checks in `WsCmd.getModuleId()`:
|
||||||
|
|
||||||
|
| cmd range | module_id (ordinal) | module | proto file |
|
||||||
|
|-----------|---------------------|--------|------------|
|
||||||
|
| 10000–10499 | 1 | CAMERA_TELE | `Camera.proto` |
|
||||||
|
| 11000–11499 | 3 | ASTRO | `Astro.proto` |
|
||||||
|
| 12000–12499 | 2 | CAMERA_WIDE | `Camera.proto` |
|
||||||
|
| 13000–13299 | 4 | SYSTEM | `System.proto` |
|
||||||
|
| 13500–13799 | 5 | RGB_POWER | (RGB led / power) |
|
||||||
|
| 14000–14499 | 6 | MOTOR | `MotorControl.proto` |
|
||||||
|
| 14800–14899 | 7 | TRACK | `Track.proto` |
|
||||||
|
| 15000–15199 | 8 | FOCUS | `Focus.proto` |
|
||||||
|
| 15200–15499 | 9 | NOTIFY | `Notify.proto` |
|
||||||
|
| 15500–15599 | 10 | PANORAMA | `Panorama.proto` |
|
||||||
|
| 15700–15799 | 11 | ITIPS | `ITips.proto` |
|
||||||
|
| 16100–16399 | 13 | SHOOTING_SCHEDULE | `Schedule.proto` |
|
||||||
|
| 16400–16599 | 14 | TASK_CENTER | `TaskCenter.proto` |
|
||||||
|
| 16700–16799 | 15 | PARAM | `Param.proto` |
|
||||||
|
| 16800–16899 | 16 | VOICE_ASSISTANT | `VoiceAssistant.proto` |
|
||||||
|
| 17000–17099 | 18 | DEVICE | `Device.proto` |
|
||||||
|
|
||||||
|
**Full table of all 323 commands → see [`CMD_TABLE.md`](CMD_TABLE.md).**
|
||||||
|
|
||||||
|
The mapping from command → inner protobuf message type lives in the
|
||||||
|
`data/websocket/<module>/` handlers (`*WsResponseHandle.java`) and the
|
||||||
|
`data/bean/p021ws/request/` request classes. To find the payload type for a
|
||||||
|
given cmd, grep the request package.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Proto definitions
|
||||||
|
|
||||||
|
Regenerated cleanly from the embedded `FileDescriptorProto` descriptors in the
|
||||||
|
APK — **17 files, 382 messages**. Located in `analysis/protos/`:
|
||||||
|
|
||||||
|
| File | msgs | Covers |
|
||||||
|
|------|------|--------|
|
||||||
|
| `Base.proto` | 6 | WsPacket envelope, ComResponse, CommonParam |
|
||||||
|
| `Camera.proto` | 55 | Both cameras: exp/gain/WB/ISP/RAW/record/burst/resolution |
|
||||||
|
| `Astro.proto` | 67 | Calibration, GOTO (DSO/solar), live-stacking, darks, EQ solving, AI enhance, mosaic, sky-finder |
|
||||||
|
| `MotorControl.proto` | 14 | RA/DEC motors: run/stop/runTo/joystick/reset/positions |
|
||||||
|
| `Track.proto` | 9 | Tracking, sentry mode, MOT, UFO (multi-object track) |
|
||||||
|
| `Focus.proto` | 9 | Auto-focus (normal + astro), manual continuous, user infinity |
|
||||||
|
| `Panorama.proto` | 18 | Grid/stitch/framing/upload/compress |
|
||||||
|
| `Notify.proto` | 81 | All async server-push events |
|
||||||
|
| `Schedule.proto` | 20 | Shooting plan sync/cancel/lock |
|
||||||
|
| `TaskCenter.proto` | 26 | Global task manager, state info, mode/tech switch |
|
||||||
|
| `System.proto` | 14 | Time/timezone, location, MTP, CPU mode, activation, low-temp protection |
|
||||||
|
| `Param.proto` | 8 | Generic param set (exposure/gain/WB/int/float/bool/auto) |
|
||||||
|
| `Device.proto` | 3 | Lens defog, auto-cooling, auto-shutdown |
|
||||||
|
| `Ble.proto` | 25 | BLE handshake (DwarfPing/DwarfEcho/config/AP/STA/wifi-scan) |
|
||||||
|
| `VoiceAssistant.proto` | 16 | On-device voice assistant tasking |
|
||||||
|
| `RGB.proto` | 6 | RGB LED ring / power indicator |
|
||||||
|
| `ITips.proto` | 5 | Tips content |
|
||||||
|
|
||||||
|
To regenerate: `python3 analysis/extract_protos.py <jadx proto dir> <out dir>`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Worked example — take a photo with the Tele camera
|
||||||
|
|
||||||
|
1. **(once)** BLE: connect, get `DwarfEcho` → extract `sta.ipv4`/`ap.ipv4`,
|
||||||
|
`psw`, join Wi-Fi.
|
||||||
|
2. Open WebSocket `ws://<ip>:9900/?client_id=droid-oss-001`.
|
||||||
|
3. Open the Tele camera: send `WsPacket{cmd=10000, data=ReqOpenCamera}`,
|
||||||
|
wait for `ComResponse{code=0}`.
|
||||||
|
4. Set exposure (optional): `cmd=10009` with `ReqSetExp{…}`.
|
||||||
|
5. Photograph: `cmd=10002` (`CMD_CAMERA_TELE_PHOTOGRAPH`).
|
||||||
|
6. Watch notifications `15273` (PHOTO_STATE) / `15274` (BURST_STATE) for result.
|
||||||
|
|
||||||
|
Common response type is `ComResponse{ int32 code = 1; }` — `code==0` means OK.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Parameter value maps (assets)
|
||||||
|
|
||||||
|
The APK ships ready-made enum maps that constrain valid values:
|
||||||
|
|
||||||
|
- **`assets/params_range.json`** — exposure index ↔ `"1/N"` label (0…full
|
||||||
|
mapping, e.g. index 0 = "1/10000", step 3).
|
||||||
|
- **`assets/shoot_plan_config.json`** — per-device capability matrix. Defines
|
||||||
|
DWARF II (id=1, fw 2.1.6): two cameras (`Tele` id=0, `Wide` implicit),
|
||||||
|
their FoV (`fvWidth/fvHeight`), preview size (1280×720), and every supported
|
||||||
|
param with `min/max/step/defaultValue/valueType` + Gear vs Continue modes.
|
||||||
|
This file is the authoritative source for **what values each camera accepts**.
|
||||||
|
- **`assets/astronomy_data.db`** — SQLite of celestial objects (GOTO targets).
|
||||||
|
- **`assets/www/modules/eq/`** — Three.js 3D equatorial-alignment helper
|
||||||
|
(polar-alignment UI). "Bilbo" = next-gen model codename (DWARF III).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Multi-device & activation notes
|
||||||
|
|
||||||
|
- `device_id` in `WsPacket` selects the active telescope when several are on the
|
||||||
|
same network; default `1`.
|
||||||
|
- Some telescopes are **factory-activated** via `CMD_SYSTEM_*` (13005–13008):
|
||||||
|
`ReqGetDeviceActivateInfo`, `ReqDeviceActivateWriteFile`, activation-notify,
|
||||||
|
factory-test un-activate. An OSS client should generally leave activation
|
||||||
|
alone.
|
||||||
|
- `CMD_SYSTEM_SET_MASTER` (13004) toggles master/slave mode
|
||||||
|
(`ReqsetMasterLock{bool lock}`).
|
||||||
|
- MTP mode (`CMD_SYSTEM_SET_MTP_MODE`, 13002) switches the telescope between
|
||||||
|
Mass-Storage (mount SD card over USB) and normal modes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Suggested open-source client architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
dwarf-oss/
|
||||||
|
├── proto/ ← copy analysis/protos/*.proto here
|
||||||
|
├── ble/ ← BLE scanner + DwarfPing/DwarfEcho handshake (ble.proto)
|
||||||
|
├── transport/
|
||||||
|
│ ├── ws_client.py ← ws://<ip>:9900/?client_id=…, send/recv WsPacket
|
||||||
|
│ ├── envelope.py ← WsPacket build/parse (Base.proto)
|
||||||
|
│ └── dispatcher.py ← cmd → pending-request matching, NOTIFY fan-out
|
||||||
|
├── rtsp/ ← GStreamer/ffmpeg/PyAV pull of rtsp://<ip>/<cam>/stream0
|
||||||
|
├── modules/
|
||||||
|
│ ├── camera.py ← cmds 10000/12000 (Tele/Wide)
|
||||||
|
│ ├── motor.py ← cmds 14000 (point/slew)
|
||||||
|
│ ├── astro.py ← cmds 11000 (calib/goto/stacking/darks)
|
||||||
|
│ ├── focus.py ← cmds 15000
|
||||||
|
│ ├── track.py ← cmds 14800
|
||||||
|
│ └── task.py ← cmds 16400 (one-click shooting)
|
||||||
|
└── cli.py ← `dwarf photo`, `dwarf goto M31`, `dwarf slew 1.2 0`
|
||||||
|
```
|
||||||
|
|
||||||
|
Key implementation tips:
|
||||||
|
- Send `major_version=2, minor_version=3` always.
|
||||||
|
- Reuse one persistent WebSocket; don't reconnect per command.
|
||||||
|
- Maintain a registry of `cmd → asyncio.Future` for request/response; a single
|
||||||
|
inbound dispatcher handles both responses and notifications.
|
||||||
|
- Start with `CMD_GLOBAL_TASK_GET_DEVICE_STATE_INFO` (16405) after connect to
|
||||||
|
snapshot the current state, then rely on NOTIFY pushes.
|
||||||
|
- For live view, a separate RTSP consumer is simpler than multiplexing over the
|
||||||
|
WebSocket.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Tooling used / how to reproduce
|
||||||
|
|
||||||
|
```
|
||||||
|
tools/jadx/bin/jadx -d extracted/jadx DWARFLAB.apk # decompile
|
||||||
|
python3 analysis/extract_protos.py extracted/.../proto analysis/protos
|
||||||
|
# WsCmd / WsModuleId / WsMessageType enums → analysis/CMD_TABLE.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Key source locations inside `extracted/jadx/sources/`:
|
||||||
|
- `com/convergence/dwarflab/proto/` — 17 `*Proto.java` (descriptors).
|
||||||
|
- `com/convergence/dwarflab/data/bean/p021ws/WsCmd.java` — all command ids.
|
||||||
|
- `…/WsModuleId.java`, `…/WsMessageType.java` — enums.
|
||||||
|
- `…/request/WsMessageReq.java` — request interface (`d49.java` = sender).
|
||||||
|
- `com/convergence/dwarflab/data/websocket/<module>/` — per-module handlers.
|
||||||
|
- `p000/e49.java` — WsPacket builder (`C9312a.m36361a`).
|
||||||
|
- `p000/v55.java` — WebSocket connection manager (URL/port 9900).
|
||||||
|
- `p000/b49.java` — OkHttp WebSocket wrapper.
|
||||||
330
analysis/CMD_TABLE.md
Normal file
330
analysis/CMD_TABLE.md
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
# DWARFLAB Command Routing Table
|
||||||
|
|
||||||
|
Auto-extracted from `WsCmd.java` + `WsModuleId.java`. `module_id` is derived from `cmd` by range.
|
||||||
|
Total: **323 commands** across **16 modules**.
|
||||||
|
|
||||||
|
| cmd | module | name |
|
||||||
|
|-----|--------|------|
|
||||||
|
| 10000 | CAMERA_TELE | CMD_CAMERA_TELE_OPEN_CAMERA |
|
||||||
|
| 10001 | CAMERA_TELE | CMD_CAMERA_TELE_CLOSE_CAMERA |
|
||||||
|
| 10002 | CAMERA_TELE | CMD_CAMERA_TELE_PHOTOGRAPH |
|
||||||
|
| 10003 | CAMERA_TELE | CMD_CAMERA_TELE_BURST |
|
||||||
|
| 10004 | CAMERA_TELE | CMD_CAMERA_TELE_STOP_BURST |
|
||||||
|
| 10005 | CAMERA_TELE | CMD_CAMERA_TELE_START_RECORD |
|
||||||
|
| 10006 | CAMERA_TELE | CMD_CAMERA_TELE_STOP_RECORD |
|
||||||
|
| 10007 | CAMERA_TELE | CMD_CAMERA_TELE_SET_EXP_MODE |
|
||||||
|
| 10008 | CAMERA_TELE | CMD_CAMERA_TELE_GET_EXP_MODE |
|
||||||
|
| 10009 | CAMERA_TELE | CMD_CAMERA_TELE_SET_EXP |
|
||||||
|
| 10010 | CAMERA_TELE | CMD_CAMERA_TELE_GET_EXP |
|
||||||
|
| 10011 | CAMERA_TELE | CMD_CAMERA_TELE_SET_GAIN_MODE |
|
||||||
|
| 10012 | CAMERA_TELE | CMD_CAMERA_TELE_GET_GAIN_MODE |
|
||||||
|
| 10013 | CAMERA_TELE | CMD_CAMERA_TELE_SET_GAIN |
|
||||||
|
| 10014 | CAMERA_TELE | CMD_CAMERA_TELE_GET_GAIN |
|
||||||
|
| 10015 | CAMERA_TELE | CMD_CAMERA_TELE_SET_BRIGHTNESS |
|
||||||
|
| 10016 | CAMERA_TELE | CMD_CAMERA_TELE_GET_BRIGHTNESS |
|
||||||
|
| 10017 | CAMERA_TELE | CMD_CAMERA_TELE_SET_CONTRAST |
|
||||||
|
| 10018 | CAMERA_TELE | CMD_CAMERA_TELE_GET_CONTRAST |
|
||||||
|
| 10019 | CAMERA_TELE | CMD_CAMERA_TELE_SET_SATURATION |
|
||||||
|
| 10020 | CAMERA_TELE | CMD_CAMERA_TELE_GET_SATURATION |
|
||||||
|
| 10021 | CAMERA_TELE | CMD_CAMERA_TELE_SET_HUE |
|
||||||
|
| 10022 | CAMERA_TELE | CMD_CAMERA_TELE_GET_HUE |
|
||||||
|
| 10023 | CAMERA_TELE | CMD_CAMERA_TELE_SET_SHARPNESS |
|
||||||
|
| 10024 | CAMERA_TELE | CMD_CAMERA_TELE_GET_SHARPNESS |
|
||||||
|
| 10025 | CAMERA_TELE | CMD_CAMERA_TELE_SET_WB_MODE |
|
||||||
|
| 10026 | CAMERA_TELE | CMD_CAMERA_TELE_GET_WB_MODE |
|
||||||
|
| 10027 | CAMERA_TELE | CMD_CAMERA_TELE_SET_WB_SCENE |
|
||||||
|
| 10028 | CAMERA_TELE | CMD_CAMERA_TELE_GET_WB_SCENE |
|
||||||
|
| 10029 | CAMERA_TELE | CMD_CAMERA_TELE_SET_WB_CT |
|
||||||
|
| 10030 | CAMERA_TELE | CMD_CAMERA_TELE_GET_WB_CT |
|
||||||
|
| 10031 | CAMERA_TELE | CMD_CAMERA_TELE_SET_IRCUT |
|
||||||
|
| 10032 | CAMERA_TELE | CMD_CAMERA_TELE_GET_IRCUT |
|
||||||
|
| 10033 | CAMERA_TELE | CMD_CAMERA_TELE_START_TIMELAPSE_PHOTO |
|
||||||
|
| 10034 | CAMERA_TELE | CMD_CAMERA_TELE_STOP_TIMELAPSE_PHOTO |
|
||||||
|
| 10035 | CAMERA_TELE | CMD_CAMERA_TELE_SET_ALL_PARAMS |
|
||||||
|
| 10036 | CAMERA_TELE | CMD_CAMERA_TELE_GET_ALL_PARAMS |
|
||||||
|
| 10037 | CAMERA_TELE | CMD_CAMERA_TELE_SET_FEATURE_PARAM |
|
||||||
|
| 10038 | CAMERA_TELE | CMD_CAMERA_TELE_GET_ALL_FEATURE_PARAMS |
|
||||||
|
| 10039 | CAMERA_TELE | CMD_CAMERA_TELE_GET_SYSTEM_WORKING_STATE |
|
||||||
|
| 10040 | CAMERA_TELE | CMD_CAMERA_TELE_SET_JPG_QUALITY |
|
||||||
|
| 10041 | CAMERA_TELE | CMD_CAMERA_TELE_PHOTO_RAW |
|
||||||
|
| 10042 | CAMERA_TELE | CMD_CAMERA_TELE_SET_RTSP_BITRATE_TYPE |
|
||||||
|
| 10043 | CAMERA_TELE | CMD_CAMERA_TELE_DISABLE_ALL_ISP_PROCESSING |
|
||||||
|
| 10044 | CAMERA_TELE | CMD_CAMERA_TELE_ENABLE_ALL_ISP_PROCESSING |
|
||||||
|
| 10045 | CAMERA_TELE | CMD_CAMERA_TELE_SET_ISP_MODULE_STATE |
|
||||||
|
| 10046 | CAMERA_TELE | CMD_CAMERA_TELE_GET_ISP_MODULE_STATE |
|
||||||
|
| 10047 | CAMERA_TELE | CMD_CAMERA_TELE_SWITCH_RESOLUTION |
|
||||||
|
| 10048 | CAMERA_TELE | CMD_CAMERA_TELE_SWITCH_FRAMERATE |
|
||||||
|
| 10049 | CAMERA_TELE | CMD_CAMERA_TELE_SWITCH_CROP_RATIO |
|
||||||
|
| 10050 | CAMERA_TELE | CMD_CAMERA_TELE_SET_PREVIEW_QUALITY |
|
||||||
|
| 11000 | ASTRO | CMD_ASTRO_START_CALIBRATION |
|
||||||
|
| 11001 | ASTRO | CMD_ASTRO_STOP_CALIBRATION |
|
||||||
|
| 11002 | ASTRO | CMD_ASTRO_START_GOTO_DSO |
|
||||||
|
| 11003 | ASTRO | CMD_ASTRO_START_GOTO_SOLAR_SYSTEM |
|
||||||
|
| 11004 | ASTRO | CMD_ASTRO_STOP_GOTO |
|
||||||
|
| 11005 | ASTRO | CMD_ASTRO_START_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 11006 | ASTRO | CMD_ASTRO_STOP_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 11007 | ASTRO | CMD_ASTRO_START_CAPTURE_RAW_DARK |
|
||||||
|
| 11008 | ASTRO | CMD_ASTRO_STOP_CAPTURE_RAW_DARK |
|
||||||
|
| 11009 | ASTRO | CMD_ASTRO_CHECK_GOT_DARK |
|
||||||
|
| 11010 | ASTRO | CMD_ASTRO_GO_LIVE |
|
||||||
|
| 11011 | ASTRO | CMD_ASTRO_START_TRACK_SPECIAL_TARGET |
|
||||||
|
| 11012 | ASTRO | CMD_ASTRO_STOP_TRACK_SPECIAL_TARGET |
|
||||||
|
| 11013 | ASTRO | CMD_ASTRO_START_ONE_CLICK_GOTO_DSO |
|
||||||
|
| 11014 | ASTRO | CMD_ASTRO_START_ONE_CLICK_GOTO_SOLAR_SYSTEM |
|
||||||
|
| 11015 | ASTRO | CMD_ASTRO_STOP_ONE_CLICK_GOTO |
|
||||||
|
| 11016 | ASTRO | CMD_ASTRO_START_WIDE_CAPTURE_LIVE_STACKING |
|
||||||
|
| 11017 | ASTRO | CMD_ASTRO_STOP_WIDE_CAPTURE_LIVE_STACKING |
|
||||||
|
| 11018 | ASTRO | CMD_ASTRO_START_EQ_SOLVING |
|
||||||
|
| 11019 | ASTRO | CMD_ASTRO_STOP_EQ_SOLVING |
|
||||||
|
| 11020 | ASTRO | CMD_ASTRO_WIDE_GO_LIVE |
|
||||||
|
| 11021 | ASTRO | CMD_ASTRO_START_CAPTURE_RAW_DARK_WITH_PARAM |
|
||||||
|
| 11022 | ASTRO | CMD_ASTRO_STOP_CAPTURE_RAW_DARK_WITH_PARAM |
|
||||||
|
| 11023 | ASTRO | CMD_ASTRO_GET_DARK_FRAME_LIST |
|
||||||
|
| 11024 | ASTRO | CMD_ASTRO_DEL_DARK_FRAME_LIST |
|
||||||
|
| 11025 | ASTRO | CMD_ASTRO_START_CAPTURE_WIDE_RAW_DARK_WITH_PARAM |
|
||||||
|
| 11026 | ASTRO | CMD_ASTRO_STOP_CAPTURE_WIDE_RAW_DARK_WITH_PARAM |
|
||||||
|
| 11027 | ASTRO | CMD_ASTRO_GET_WIDE_DARK_FRAME_LIST |
|
||||||
|
| 11028 | ASTRO | CMD_ASTRO_DEL_WIDE_DARK_FRAME_LIST |
|
||||||
|
| 11029 | ASTRO | CMD_ASTRO_START_AI_ENHANCE |
|
||||||
|
| 11030 | ASTRO | CMD_ASTRO_STOP_AI_ENHANCE |
|
||||||
|
| 11031 | ASTRO | CMD_ASTRO_START_TELE_MOSAIC |
|
||||||
|
| 11032 | ASTRO | CMD_ASTRO_CHECK_IF_RESTACKABLE |
|
||||||
|
| 11033 | ASTRO | CMD_ASTRO_START_MAKE_FITS_THUMB |
|
||||||
|
| 11034 | ASTRO | CMD_ASTRO_STOP_MAKE_FITS_THUMB |
|
||||||
|
| 11035 | ASTRO | CMD_ASTRO_START_RESTACKED |
|
||||||
|
| 11036 | ASTRO | CMD_ASTRO_STOP_RESTACKED |
|
||||||
|
| 11037 | ASTRO | CMD_ASTRO_FAST_STOP_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 11038 | ASTRO | CMD_ASTRO_FAST_STOP_WIDE_CAPTURE_LIVE_STACKING |
|
||||||
|
| 11039 | ASTRO | CMD_ASTRO_GET_ASTRO_SHOOTING_TIME |
|
||||||
|
| 11040 | ASTRO | CMD_ASTRO_GET_QUICK_SET_LIST |
|
||||||
|
| 11041 | ASTRO | CMD_ASTRO_SET_QUICK_SET |
|
||||||
|
| 11042 | ASTRO | CMD_ASTRO_START_ONE_CLICK_SHOOTING |
|
||||||
|
| 11043 | ASTRO | CMD_ASTRO_GET_CALI_FRAME_LIST |
|
||||||
|
| 11044 | ASTRO | CMD_ASTRO_DEL_CALI_FRAME_LIST |
|
||||||
|
| 11045 | ASTRO | CMD_ASTRO_START_CAPTURE_CALI_FRAME |
|
||||||
|
| 11046 | ASTRO | CMD_ASTRO_STOP_CAPTURE_CALI_FRAME |
|
||||||
|
| 11047 | ASTRO | CMD_ASTRO_START_SKY_TARGET_FINDER |
|
||||||
|
| 11048 | ASTRO | CMD_ASTRO_STOP_SKY_TARGET_FINDER |
|
||||||
|
| 12000 | CAMERA_WIDE | CMD_CAMERA_WIDE_OPEN_CAMERA |
|
||||||
|
| 12001 | CAMERA_WIDE | CMD_CAMERA_WIDE_CLOSE_CAMERA |
|
||||||
|
| 12002 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_EXP_MODE |
|
||||||
|
| 12003 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_EXP_MODE |
|
||||||
|
| 12004 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_EXP |
|
||||||
|
| 12005 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_EXP |
|
||||||
|
| 12006 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_GAIN |
|
||||||
|
| 12007 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_GAIN |
|
||||||
|
| 12008 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_BRIGHTNESS |
|
||||||
|
| 12009 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_BRIGHTNESS |
|
||||||
|
| 12010 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_CONTRAST |
|
||||||
|
| 12011 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_CONTRAST |
|
||||||
|
| 12012 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_SATURATION |
|
||||||
|
| 12013 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_SATURATION |
|
||||||
|
| 12014 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_HUE |
|
||||||
|
| 12015 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_HUE |
|
||||||
|
| 12016 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_SHARPNESS |
|
||||||
|
| 12017 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_SHARPNESS |
|
||||||
|
| 12018 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_WB_MODE |
|
||||||
|
| 12019 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_WB_MODE |
|
||||||
|
| 12020 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_WB_CT |
|
||||||
|
| 12021 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_WB_CT |
|
||||||
|
| 12022 | CAMERA_WIDE | CMD_CAMERA_WIDE_PHOTOGRAPH |
|
||||||
|
| 12023 | CAMERA_WIDE | CMD_CAMERA_WIDE_BURST |
|
||||||
|
| 12024 | CAMERA_WIDE | CMD_CAMERA_WIDE_STOP_BURST |
|
||||||
|
| 12025 | CAMERA_WIDE | CMD_CAMERA_WIDE_START_TIMELAPSE_PHOTO |
|
||||||
|
| 12026 | CAMERA_WIDE | CMD_CAMERA_WIDE_STOP_TIMELAPSE_PHOTO |
|
||||||
|
| 12027 | CAMERA_WIDE | CMD_CAMERA_WIDE_GET_ALL_PARAMS |
|
||||||
|
| 12028 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_ALL_PARAMS |
|
||||||
|
| 12029 | CAMERA_WIDE | CMD_CAMERA_WIDE_PHOTO_RAW |
|
||||||
|
| 12030 | CAMERA_WIDE | CMD_CAMERA_WIDE_START_RECORD |
|
||||||
|
| 12031 | CAMERA_WIDE | CMD_CAMERA_WIDE_STOP_RECORD |
|
||||||
|
| 12032 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_RTSP_BITRATE_TYPE |
|
||||||
|
| 12035 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_WB_SCENE |
|
||||||
|
| 12036 | CAMERA_WIDE | CMD_CAMERA_WIDE_SET_PREVIEW_QUALITY |
|
||||||
|
| 13000 | SYSTEM | CMD_SYSTEM_SET_TIME |
|
||||||
|
| 13001 | SYSTEM | CMD_SYSTEM_SET_TIME_ZONE |
|
||||||
|
| 13002 | SYSTEM | CMD_SYSTEM_SET_MTP_MODE |
|
||||||
|
| 13003 | SYSTEM | CMD_SYSTEM_SET_CPU_MODE |
|
||||||
|
| 13004 | SYSTEM | CMD_SYSTEM_SET_MASTER |
|
||||||
|
| 13005 | SYSTEM | CMD_SYSTEM_GET_DEVICE_ACTIVATE_INFO |
|
||||||
|
| 13006 | SYSTEM | CMD_SYSTEM_DEVICE_ACTIVATE_WRITE_FILE |
|
||||||
|
| 13007 | SYSTEM | CMD_SYSTEM_DEVICE_ACTIVATE_NOTIFY_ACTIVATE_SUCCESSFULL |
|
||||||
|
| 13008 | SYSTEM | CMD_SYSTEM_FACTORY_TEST_UN_ACTIVATE |
|
||||||
|
| 13009 | SYSTEM | CMD_SYSTEM_SET_LOW_TEMP_PROTECTION_MODE |
|
||||||
|
| 13010 | SYSTEM | CMD_SYSTEM_SET_LOCATION |
|
||||||
|
| 13500 | RGB_POWER | CMD_RGB_POWER_OPEN_RGB |
|
||||||
|
| 13501 | RGB_POWER | CMD_RGB_POWER_CLOSE_RGB |
|
||||||
|
| 13502 | RGB_POWER | CMD_RGB_POWER_POWER_DOWN |
|
||||||
|
| 13503 | RGB_POWER | CMD_RGB_POWER_POWERIND_ON |
|
||||||
|
| 13504 | RGB_POWER | CMD_RGB_POWER_POWERIND_OFF |
|
||||||
|
| 13505 | RGB_POWER | CMD_RGB_POWER_REBOOT |
|
||||||
|
| 14000 | MOTOR | CMD_STEP_MOTOR_RUN |
|
||||||
|
| 14002 | MOTOR | CMD_STEP_MOTOR_STOP |
|
||||||
|
| 14006 | MOTOR | CMD_STEP_MOTOR_SERVICE_JOYSTICK |
|
||||||
|
| 14007 | MOTOR | CMD_STEP_MOTOR_SERVICE_JOYSTICK_FIXED_ANGLE |
|
||||||
|
| 14008 | MOTOR | CMD_STEP_MOTOR_SERVICE_JOYSTICK_STOP |
|
||||||
|
| 14009 | MOTOR | CMD_STEP_MOTOR_SERVICE_DUAL_CAMERA_LINKAGE |
|
||||||
|
| 14800 | TRACK | CMD_TRACK_START_TRACK |
|
||||||
|
| 14801 | TRACK | CMD_TRACK_STOP_TRACK |
|
||||||
|
| 14802 | TRACK | CMD_SENTRY_MODE_START |
|
||||||
|
| 14803 | TRACK | CMD_SENTRY_MODE_STOP |
|
||||||
|
| 14804 | TRACK | CMD_MOT_START |
|
||||||
|
| 14805 | TRACK | CMD_MOT_TRACK_ONE |
|
||||||
|
| 14806 | TRACK | CMD_UFOTRACK_MODE_START |
|
||||||
|
| 14807 | TRACK | CMD_UFOTRACK_MODE_STOP |
|
||||||
|
| 14808 | TRACK | CMD_MOT_WIDE_TRACK_ONE |
|
||||||
|
| 14809 | TRACK | CMD_SWITCH_MAIN_PREVIEW |
|
||||||
|
| 14810 | TRACK | CMD_UFO_HAND_AOTO_MODE |
|
||||||
|
| 14811 | TRACK | CMD_SENTRY_SCENE_SELECT |
|
||||||
|
| 14812 | TRACK | CMD_TRACK_START_CLICK |
|
||||||
|
| 15000 | FOCUS | CMD_FOCUS_AUTO_FOCUS |
|
||||||
|
| 15001 | FOCUS | CMD_FOCUS_MANUAL_SINGLE_STEP_FOCUS |
|
||||||
|
| 15002 | FOCUS | CMD_FOCUS_START_MANUAL_CONTINU_FOCUS |
|
||||||
|
| 15003 | FOCUS | CMD_FOCUS_STOP_MANUAL_CONTINU_FOCUS |
|
||||||
|
| 15004 | FOCUS | CMD_FOCUS_START_ASTRO_AUTO_FOCUS |
|
||||||
|
| 15005 | FOCUS | CMD_FOCUS_STOP_ASTRO_AUTO_FOCUS |
|
||||||
|
| 15011 | FOCUS | CMD_FOCUS_GET_USER_INFINITY_POS |
|
||||||
|
| 15012 | FOCUS | CMD_FOCUS_SET_USER_INFINITY_POS |
|
||||||
|
| 15200 | NOTIFY | CMD_NOTIFY_TELE_WIDE_PICTURE_MATCHING |
|
||||||
|
| 15201 | NOTIFY | CMD_NOTIFY_ELE |
|
||||||
|
| 15202 | NOTIFY | CMD_NOTIFY_CHARGE |
|
||||||
|
| 15203 | NOTIFY | CMD_NOTIFY_SDCARD_INFO |
|
||||||
|
| 15204 | NOTIFY | CMD_NOTIFY_TELE_RECORD_TIME |
|
||||||
|
| 15205 | NOTIFY | CMD_NOTIFY_TELE_TIMELAPSE_OUT_TIME |
|
||||||
|
| 15206 | NOTIFY | CMD_NOTIFY_STATE_CAPTURE_RAW_DARK |
|
||||||
|
| 15207 | NOTIFY | CMD_NOTIFY_PROGRASS_CAPTURE_RAW_DARK |
|
||||||
|
| 15208 | NOTIFY | CMD_NOTIFY_STATE_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 15209 | NOTIFY | CMD_NOTIFY_PROGRASS_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 15210 | NOTIFY | CMD_NOTIFY_STATE_ASTRO_CALIBRATION |
|
||||||
|
| 15211 | NOTIFY | CMD_NOTIFY_STATE_ASTRO_GOTO |
|
||||||
|
| 15212 | NOTIFY | CMD_NOTIFY_STATE_ASTRO_TRACKING |
|
||||||
|
| 15213 | NOTIFY | CMD_NOTIFY_TELE_SET_PARAM |
|
||||||
|
| 15214 | NOTIFY | CMD_NOTIFY_WIDE_SET_PARAM |
|
||||||
|
| 15215 | NOTIFY | CMD_NOTIFY_TELE_FUNCTION_STATE |
|
||||||
|
| 15216 | NOTIFY | CMD_NOTIFY_WIDE_FUNCTION_STATE |
|
||||||
|
| 15217 | NOTIFY | CMD_NOTIFY_SET_FEATURE_PARAM |
|
||||||
|
| 15218 | NOTIFY | CMD_NOTIFY_TELE_BURST_PROGRESS |
|
||||||
|
| 15219 | NOTIFY | CMD_NOTIFY_PANORAMA_PROGRESS |
|
||||||
|
| 15220 | NOTIFY | CMD_NOTIFY_WIDE_BURST_PROGRESS |
|
||||||
|
| 15221 | NOTIFY | CMD_NOTIFY_RGB_STATE |
|
||||||
|
| 15222 | NOTIFY | CMD_NOTIFY_POWER_IND_STATE |
|
||||||
|
| 15223 | NOTIFY | CMD_NOTIFY_WS_HOST_SLAVE_MODE |
|
||||||
|
| 15224 | NOTIFY | CMD_NOTIFY_MTP_STATE |
|
||||||
|
| 15225 | NOTIFY | CMD_NOTIFY_TRACK_RESULT |
|
||||||
|
| 15226 | NOTIFY | CMD_NOTIFY_WIDE_TIMELAPSE_OUT_TIME |
|
||||||
|
| 15227 | NOTIFY | CMD_NOTIFY_CPU_MODE |
|
||||||
|
| 15228 | NOTIFY | CMD_NOTIFY_STATE_ASTRO_TRACKING_SPECIAL |
|
||||||
|
| 15229 | NOTIFY | CMD_NOTIFY_POWER_OFF |
|
||||||
|
| 15230 | NOTIFY | CMD_NOTIFY_ALBUM_UPDATE |
|
||||||
|
| 15231 | NOTIFY | CMD_NOTIFY_SENTRY_MODE_STATE |
|
||||||
|
| 15232 | NOTIFY | CMD_NOTIFY_SENTRY_MODE_TRACK_RESULT |
|
||||||
|
| 15233 | NOTIFY | CMD_NOTIFY_STATE_ASTRO_ONE_CLICK_GOTO |
|
||||||
|
| 15234 | NOTIFY | CMD_NOTIFY_STREAM_TYPE |
|
||||||
|
| 15235 | NOTIFY | CMD_NOTIFY_WIDE_RECORD_TIME |
|
||||||
|
| 15236 | NOTIFY | CMD_NOTIFY_STATE_WIDE_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 15237 | NOTIFY | CMD_NOTIFY_PROGRASS_WIDE_CAPTURE_RAW_LIVE_STACKING |
|
||||||
|
| 15238 | NOTIFY | CMD_NOTIFY_MULTI_TRACK_RESULT |
|
||||||
|
| 15239 | NOTIFY | CMD_NOTIFY_EQ_SOLVING_STATE |
|
||||||
|
| 15240 | NOTIFY | CMD_NOTIFY_UFO_MODE_STATE |
|
||||||
|
| 15241 | NOTIFY | CMD_NOTIFY_TELE_LONG_EXP_PROGRESS |
|
||||||
|
| 15242 | NOTIFY | CMD_NOTIFY_WIDE_LONG_EXP_PROGRESS |
|
||||||
|
| 15243 | NOTIFY | CMD_NOTIFY_TEMPERATURE |
|
||||||
|
| 15244 | NOTIFY | CMD_NOTIFY_PANORAMA_UPLOAD_COMPRESS_PROGRESS |
|
||||||
|
| 15245 | NOTIFY | CMD_NOTIFY_PANORAMA_UPLOAD_COMPLETE |
|
||||||
|
| 15245 | NOTIFY | CMD_NOTIFY_PANORAMA_UPLOAD_UPLOAD_PROGRESS |
|
||||||
|
| 15247 | NOTIFY | CMD_NOTIFY_STATE_CAPTURE_WIDE_RAW_DARK |
|
||||||
|
| 15248 | NOTIFY | CMD_NOTIFY_SHOOTING_SCHEDULE_RESULT_AND_STATE |
|
||||||
|
| 15249 | NOTIFY | CMD_NOTIFY_SHOOTING_TASK_STATE |
|
||||||
|
| 15250 | NOTIFY | CMD_NOTIFY_SKY_SEACHER_STATE |
|
||||||
|
| 15251 | NOTIFY | CMD_NOTIFY_WIDE_MULTI_TRACK_RESULT |
|
||||||
|
| 15252 | NOTIFY | CMD_NOTIFY_WIDE_TRACK_RESULT |
|
||||||
|
| 15253 | NOTIFY | CMD_NOTIFY_STATE_AI_ENHANCE |
|
||||||
|
| 15254 | NOTIFY | CMD_NOTIFY_PROGRESS_AI_ENHANCE |
|
||||||
|
| 15255 | NOTIFY | CMD_NOTIFY_WAIT_SHOOTING_PROGRESS |
|
||||||
|
| 15256 | NOTIFY | CMD_NOTIFY_CALIBRATION_RESULT |
|
||||||
|
| 15257 | NOTIFY | CMD_NOTIFY_FOCUS_POSITION |
|
||||||
|
| 15258 | NOTIFY | CMD_NOTIFY_UFO_AUTO_HAND_MODE |
|
||||||
|
| 15259 | NOTIFY | CMD_NOTIFY_CURRENT_PANORAMA_UPLOAD_STATE |
|
||||||
|
| 15260 | NOTIFY | CMD_NOTIFY_LOW_TEMP_PROTECTION_MODE |
|
||||||
|
| 15261 | NOTIFY | CMD_NOTIFY_EXCLUSIVE_SYSTEM_IO_TASK_STATE |
|
||||||
|
| 15262 | NOTIFY | CMD_NOTIFY_BODY_STATUS |
|
||||||
|
| 15263 | NOTIFY | CMD_NOTIFY_PROGRESS_CAPTURE_MOSAIC |
|
||||||
|
| 15264 | NOTIFY | CMD_NOTIFY_GENERAL_INT_PARAM |
|
||||||
|
| 15265 | NOTIFY | CMD_NOTIFY_GENERAL_FLOAT_PARAM |
|
||||||
|
| 15266 | NOTIFY | CMD_NOTIFY_GENERAL_BOOL_PARAM |
|
||||||
|
| 15267 | NOTIFY | CMD_NOTIFY_SWITCH_SHOOTING_MODE |
|
||||||
|
| 15268 | NOTIFY | CMD_NOTIFY_TELE_SWITCH_CROP_RATIO |
|
||||||
|
| 15269 | NOTIFY | CMD_NOTIFY_TELE_SHOOTING_TECH_STATE |
|
||||||
|
| 15270 | NOTIFY | CMD_NOTIFY_WB |
|
||||||
|
| 15271 | NOTIFY | CMD_NOTIFY_WIDE_SHOOTING_TECH_STATE |
|
||||||
|
| 15272 | NOTIFY | CMD_NOTIFY_RESOLUTION_PARAM |
|
||||||
|
| 15273 | NOTIFY | CMD_NOTIFY_PHOTO_STATE |
|
||||||
|
| 15274 | NOTIFY | CMD_NOTIFY_BURST_STATE |
|
||||||
|
| 15275 | NOTIFY | CMD_NOTIFY_RECORD_STATE |
|
||||||
|
| 15276 | NOTIFY | CMD_NOTIFY_TIMELAPSE_STATE |
|
||||||
|
| 15277 | NOTIFY | CMD_NOTIFY_PANORAMA_STATE |
|
||||||
|
| 15278 | NOTIFY | CMD_NOTIFY_ASTRO_AUTO_FOCUS_STATE |
|
||||||
|
| 15279 | NOTIFY | CMD_NOTIFY_NORMAL_AUTO_FOCUS_STATE |
|
||||||
|
| 15280 | NOTIFY | CMD_NOTIFY_ASTRO_AUTO_FOCUS_FAST_STATE |
|
||||||
|
| 15281 | NOTIFY | CMD_NOTIFY_AREA_AUTO_FOCUS_STATE |
|
||||||
|
| 15282 | NOTIFY | CMD_NOTIFY_DUAL_CAMERA_LINKAGE_STATE |
|
||||||
|
| 15283 | NOTIFY | CMD_NOTIFY_RESOLUTION_FPS_STATE |
|
||||||
|
| 15284 | NOTIFY | CMD_NOTIFY_NORMAL_TRACK_STATE |
|
||||||
|
| 15285 | NOTIFY | CMD_NOTIFY_BURST_PROGRESS |
|
||||||
|
| 15286 | NOTIFY | CMD_NOTIFY_RECORD_TIME |
|
||||||
|
| 15287 | NOTIFY | CMD_NOTIFY_TIMELAPSE_OUT_TIME |
|
||||||
|
| 15288 | NOTIFY | CMD_NOTIFY_LONG_EXP_PROGRESS |
|
||||||
|
| 15289 | NOTIFY | CMD_NOTIFY_SENTRY_MOTOR_STATE |
|
||||||
|
| 15290 | NOTIFY | CMD_NOTIFY_STATE_CAPTURE_CALI_FRAME |
|
||||||
|
| 15291 | NOTIFY | CMD_NOTIFY_PROGRESS_CAPTURE_CALI_FRAME |
|
||||||
|
| 15292 | NOTIFY | CMD_NOTIFY_CMOS_TEMPERATURE |
|
||||||
|
| 15293 | NOTIFY | CMD_NOTIFY_PANORAMA_COMPRESS_PROGRESS |
|
||||||
|
| 15294 | NOTIFY | CMD_NOTIFY_PANORAMA_COMPRESS_COMPLETE |
|
||||||
|
| 15295 | NOTIFY | CMD_NOTIFY_DEVICE_ATTITUDE |
|
||||||
|
| 15296 | NOTIFY | CMD_NOTIFY_SKY_TARGET_FINDER_STATE |
|
||||||
|
| 15297 | NOTIFY | CMD_NOTIFY_PANO_FRAMING_RECT_UPDATE |
|
||||||
|
| 15298 | NOTIFY | CMD_NOTIFY_PANO_FRAMING_THUMBNAIL_UPDATE |
|
||||||
|
| 15299 | NOTIFY | CMD_NOTIFY_PANO_FRAMING_STATE |
|
||||||
|
| 15300 | NOTIFY | CMD_NOTIFY_WIDE_FOCUS_POSITION |
|
||||||
|
| 15301 | NOTIFY | CMD_NOTIFY_LENS_DEFOG_STATE |
|
||||||
|
| 15302 | NOTIFY | CMD_NOTIFY_AUTO_COOLING_STATE |
|
||||||
|
| 15303 | NOTIFY | CMD_NOTIFY_AUTO_SHUTDOWN_STATE |
|
||||||
|
| 15500 | PANORAMA | CMD_PANORAMA_START_GRID |
|
||||||
|
| 15501 | PANORAMA | CMD_PANORAMA_STOP |
|
||||||
|
| 15503 | PANORAMA | CMD_PANORAMA_START_STITCH_UPLOAD |
|
||||||
|
| 15504 | PANORAMA | CMD_PANORAMA_STOP_STITCH_UPLOAD |
|
||||||
|
| 15505 | PANORAMA | CMD_PANORAMA_GET_CURRENT_UPLOAD_STATE |
|
||||||
|
| 15506 | PANORAMA | CMD_PANORAMA_GET_UPLOAD_PREDICT |
|
||||||
|
| 15507 | PANORAMA | CMD_PANORAMA_START_COMPRESS |
|
||||||
|
| 15508 | PANORAMA | CMD_PANORAMA_STOP_COMPRESS |
|
||||||
|
| 15509 | PANORAMA | CMD_PANORAMA_START_FRAMING |
|
||||||
|
| 15510 | PANORAMA | CMD_PANORAMA_STOP_FRAMING |
|
||||||
|
| 15511 | PANORAMA | CMD_PANORAMA_RESET_FRAMING |
|
||||||
|
| 15512 | PANORAMA | CMD_PANORAMA_UPDATE_FRAMING_RECT |
|
||||||
|
| 15513 | PANORAMA | CMD_PANORAMA_STOP_FRAMEING_AND_START_GRID |
|
||||||
|
| 15700 | ITIPS | CMD_ITIPS_GET |
|
||||||
|
| 16100 | SHOOTING_SCHEDULE | CMD_SYNC_SHOOTING_SCHEDULE |
|
||||||
|
| 16101 | SHOOTING_SCHEDULE | CMD_CANCEL_SHOOTING_SCHEDULE |
|
||||||
|
| 16102 | SHOOTING_SCHEDULE | CMD_GET_ALL_SHOOTING_SCHEDULE |
|
||||||
|
| 16103 | SHOOTING_SCHEDULE | CMD_GET_SHOOTING_SCHEDULE_BY_ID |
|
||||||
|
| 16105 | SHOOTING_SCHEDULE | CMD_REPLACE_SHOOTING_SCHEDULE |
|
||||||
|
| 16106 | SHOOTING_SCHEDULE | CMD_UNLOCK_SHOOTING_SCHEDULE |
|
||||||
|
| 16107 | SHOOTING_SCHEDULE | CMD_LOCK_SHOOTING_SCHEDULE |
|
||||||
|
| 16108 | SHOOTING_SCHEDULE | CMD_DELETE_SHOOTING_SCHEDULE |
|
||||||
|
| 16400 | TASK_CENTER | CMD_GLOBAL_TASK_MANAGER_START_TASK |
|
||||||
|
| 16401 | TASK_CENTER | CMD_GLOBAL_TASK_MANAGER_STOP_TASK |
|
||||||
|
| 16402 | TASK_CENTER | CMD_GLOBAL_TASK_MANAGER_SWITCH_SHOOTING_MODE |
|
||||||
|
| 16403 | TASK_CENTER | CMD_GLOBAL_TASK_MANAGER_SWITCH_SHOOTING_TECH |
|
||||||
|
| 16404 | TASK_CENTER | CMD_GLOBAL_TASK_MANAGER_ENTER_CAMERA |
|
||||||
|
| 16405 | TASK_CENTER | CMD_GLOBAL_TASK_GET_DEVICE_STATE_INFO |
|
||||||
|
| 16406 | TASK_CENTER | CMD_GLOBAL_VOICE_ASSISTANT_TASK |
|
||||||
|
| 16700 | PARAM | CMD_PARAM_SET_EXPOSURE |
|
||||||
|
| 16701 | PARAM | CMD_PARAM_SET_GAIN |
|
||||||
|
| 16702 | PARAM | CMD_PARAM_SET_WB |
|
||||||
|
| 16703 | PARAM | CMD_PARAM_SET_GENERAL_INT_PARAM |
|
||||||
|
| 16704 | PARAM | CMD_PARAM_SET_GENERAL_FLOAT_PARAM |
|
||||||
|
| 16705 | PARAM | CMD_PARAM_SET_GENERAL_BOOL_PARAM |
|
||||||
|
| 16706 | PARAM | CMD_PARAM_SET_AUTO_PARAMS |
|
||||||
|
| 16800 | VOICE_ASSISTANT | CMD_VOICE_ASSISTANT_TASK |
|
||||||
|
| 17000 | DEVICE | CMD_DEVICE_LENS_DEFOG |
|
||||||
|
| 17001 | DEVICE | CMD_DEVICE_AUTO_COOLING |
|
||||||
|
| 17002 | DEVICE | CMD_DEVICE_AUTO_SHUTDOWN |
|
||||||
502
analysis/UI_REFERENCE.md
Normal file
502
analysis/UI_REFERENCE.md
Normal file
@ -0,0 +1,502 @@
|
|||||||
|
# DWARFLAB App — UI / UX Reference (reverse-engineered)
|
||||||
|
|
||||||
|
Reverse-engineered from `DWARFLAB.apk` v3.4.0 (`com.convergence.dwarflab`). This
|
||||||
|
document describes the **user interface, screen hierarchy, navigation, and
|
||||||
|
interactions** so the app can be reimplemented in another language/framework.
|
||||||
|
|
||||||
|
Focus: **Splash → Home → Connection → Capture (main shooter) → Settings**.
|
||||||
|
(Atlas/Sky-Atlas and Album/Gallery screens are documented separately.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. App structure & navigation model
|
||||||
|
|
||||||
|
The app uses **Jetpack Navigation** (single-activity `MainActivity` + a
|
||||||
|
`NavHostFragment`) with a **`BottomNavigationView`** of 4 tabs, plus several
|
||||||
|
full-screen Activities launched outside the nav graph.
|
||||||
|
|
||||||
|
### 1.1 Entry / launch flow
|
||||||
|
```
|
||||||
|
SplashActivity (launcher, branding + init)
|
||||||
|
└─▶ MainActivity (NavHost + BottomNavigationView, 4 tabs)
|
||||||
|
├─ Tab 1: Home → HomeFragment
|
||||||
|
├─ Tab 2: Atlas → AtlasActivity (separate)
|
||||||
|
├─ Tab 3: Album → AlbumFragment / AlbumActivity
|
||||||
|
└─ Tab 4: Settings → SettingsFragment
|
||||||
|
```
|
||||||
|
- `mobile_navigation.xml` is the main nav graph; `startDestination =
|
||||||
|
navigation_device` (Home).
|
||||||
|
- `HeartbeatEntryActivity` is a transparent launcher alias used to keep a
|
||||||
|
foreground service alive (the BLE/Wi-Fi heartbeat to the scope).
|
||||||
|
- Tab labels (from `bottom_nav_menu.xml` + strings `home_3/4/5`, `camera_astro_69`):
|
||||||
|
| tab | id | label (en) | icon |
|
||||||
|
|-----|----|-----------|------|
|
||||||
|
| 1 | `navigation_device` | **Home** | `icon_function_tabbar_home` |
|
||||||
|
| 2 | `navigation_atlas` | **Atlas** | `icon_function_tabbar_atlas` |
|
||||||
|
| 3 | `navigation_album` | **Album** | `icon_function_tabbar_album` |
|
||||||
|
| 4 | `navigation_settings` | **Settings** | `icon_function_tabbar_settings` |
|
||||||
|
|
||||||
|
The bottom bar can be hidden (`MainActivity.isShowBottomNav`) when entering
|
||||||
|
full-screen sub-flows (device connect, OTA, capture).
|
||||||
|
|
||||||
|
### 1.2 Activities (beyond the nav graph)
|
||||||
|
| Activity | Purpose |
|
||||||
|
|----------|---------|
|
||||||
|
| `SplashActivity` | Cold-start splash, version checks, routing to connect vs. main |
|
||||||
|
| `MainActivity` | Hosts the 4 tabs + NavHost |
|
||||||
|
| `CaptureActivity` | **The shooting screen** (9199 lines — the heart of the app) |
|
||||||
|
| `AtlasActivity` | Sky atlas / star map / GoTo target selection |
|
||||||
|
| `AlbumActivity` | Gallery of captured photos/videos/FITS |
|
||||||
|
| `LocationActivity` | Map to set observing location |
|
||||||
|
| `CaliFrameActivity` | Calibration-frame capture/management |
|
||||||
|
| `HelperActivity` | In-app help / guide center |
|
||||||
|
| `WebActivity` / `NavActivity` | Embedded web views (privacy, OSS notice, help docs) |
|
||||||
|
| `NfcWriteActivity` | NFC tag update (device name change) |
|
||||||
|
| `MosaicGuideActivity`, `SkyLightTipActivity`, `StarSearchActivity` | Atlas sub-screens |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Splash & first-run
|
||||||
|
|
||||||
|
`SplashActivity` → decides between:
|
||||||
|
- **Not connected**: routes to `HomeFragment` which shows a *device-discovery /
|
||||||
|
connect* CTA when no scope is paired.
|
||||||
|
- **App upgrade available**: shows `AppUpdateDialog` (force-update path uses
|
||||||
|
`FirmwareForceUpdateDialog`).
|
||||||
|
- **System notice**: `AppNotice` banner.
|
||||||
|
|
||||||
|
`MainActivity` also handles: app-upgrade dialogs, product-activation dialog
|
||||||
|
(`ProductActivateDialog`), not-enough-storage dialog, and an activation-error
|
||||||
|
dialog. Activation is gated behind internet access (strings `settings_25`–`45`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Home tab (`HomeFragment`) — `fragment_home.xml`
|
||||||
|
|
||||||
|
The dashboard / device hub. Two visual states:
|
||||||
|
|
||||||
|
### 3.1 Disconnected state
|
||||||
|
- Title bar: device-name placeholder + a **"Guide"** button (`home_16`,
|
||||||
|
top-right, primary pill).
|
||||||
|
- Centered illustration + **"Connect"** call-to-action → navigates to
|
||||||
|
`DeviceSearchFragment` (BLE scan).
|
||||||
|
- `view_bg_home_disconnected` background shown.
|
||||||
|
|
||||||
|
### 3.2 Connected state
|
||||||
|
Top bar becomes a **device selector dropdown** (`tv_title` with
|
||||||
|
`drawableEnd icon_action_arrow_down`): tapping opens device switcher.
|
||||||
|
Below: device status card, then action entries.
|
||||||
|
|
||||||
|
Navigation actions declared on `navigation_device` (HomeFragment):
|
||||||
|
| Action | Destination | Meaning |
|
||||||
|
|--------|-------------|---------|
|
||||||
|
| `action_deviceFragment_to_deviceSearchFragment` | Device Search | Add/switch device |
|
||||||
|
| `action_homeFragment_to_locationFragment` | Location | Set GPS/observing site |
|
||||||
|
| `action_homeFragment_to_ScheduleFragment` | Schedule | Shooting plans list |
|
||||||
|
| `action_homeFragment_to_upgradeFragment` | OTA Upgrade | Firmware update |
|
||||||
|
| `action_homeFragment_to_scheduleDetailFragment` | Schedule Detail | Edit a plan |
|
||||||
|
| `action_homeFragment_to_helperFragment` | Helper | In-app guide |
|
||||||
|
| `action_homeFragment_to_webFragment` | Web | Embedded web content |
|
||||||
|
| `action_home_to_taskListFragment` | Task List | Task/creation jobs (`createType` arg) |
|
||||||
|
| `action_home_to_astroFitsFragment` | Astro FITS | View a FITS file (`filePath`) |
|
||||||
|
| `action_home_to_caliFrameListFragment` | Cali-Frame List | Manage calibration frames (`caliFrameType`, `cameraType`) |
|
||||||
|
|
||||||
|
So **Home is a launcher** into: connect, location, schedule, OTA, tasks,
|
||||||
|
cali-frames, help. The actual *shooting* is entered by tapping the connected
|
||||||
|
device card → launches `CaptureActivity`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Device connection flow
|
||||||
|
|
||||||
|
A multi-step wizard (mostly bottom-sheet dialogs) living under
|
||||||
|
`navigation_device_connect` and friends.
|
||||||
|
|
||||||
|
```
|
||||||
|
DeviceSearchFragment (BLE scan, lists nearby scopes)
|
||||||
|
├─▶ DeviceConnectFragment (dialog) — enter device password
|
||||||
|
│ ├─ success → DeviceConnectSuccessFragment
|
||||||
|
│ ├─ wrong pwd → DeviceConnectPwdErrorAgainFragment
|
||||||
|
│ └─ upgrade needed → UpgradeReminderFragment → OTAUpgradeFragment
|
||||||
|
├─▶ WiFiListFragment (STA mode: scan Wi-Fi for the scope)
|
||||||
|
│ └─▶ StaInfoFragment (enter Wi-Fi password) → DeviceConnectFragment
|
||||||
|
├─▶ DeviceConnectManualFragment (manual IP entry)
|
||||||
|
├─▶ DeviceStaPwdFragment / DeviceStaConnectFailedFragment
|
||||||
|
└─▶ DeviceResetTutorialFragment / DeviceConnectFailedFragment
|
||||||
|
```
|
||||||
|
|
||||||
|
Key strings reveal the model:
|
||||||
|
- **Connection modes** (`settings_connection_14–21`):
|
||||||
|
- **Auto (Recommended)** — auto-choose AP vs STA.
|
||||||
|
- **STA mode** — phone & scope join the same home Wi-Fi (scope gets internet).
|
||||||
|
- **AP mode** — connect directly to the DWARF hotspot (outdoor/no-Wi-Fi).
|
||||||
|
- **Wi-Fi Compatible Mode** + **Enable 2.4GHz** toggles for region/legacy fixes.
|
||||||
|
- **Region** setting (`settings_connection_10`) — country code for Wi-Fi regs.
|
||||||
|
- **Activate Wi-Fi at Startup** — auto-enable hotspot on boot.
|
||||||
|
- Device password screen distinguishes **default password** vs custom
|
||||||
|
(`isDefaultPwd` arg → `DevicePasswordFragment`).
|
||||||
|
|
||||||
|
`DeviceSearchFragment` args: `type` (0 = first connect, 1 = add another),
|
||||||
|
`deviceName` (nullable, for reconnect). Result carries a `DeviceInfo`
|
||||||
|
(`com.convergence.dwarflab.net.discovery.DeviceInfo`) containing BLE-resolved
|
||||||
|
IP/SSID/PSK (see API_REFERENCE §2.1 for the BLE `DwarfEcho` payload).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Capture screen (`CaptureActivity`) — the shooter
|
||||||
|
|
||||||
|
This is the most complex screen (~9200 lines). Landscape-oriented camera
|
||||||
|
viewfinder with overlaid controls. Layout: `activity_capture.xml`.
|
||||||
|
|
||||||
|
### 5.1 Layout regions
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
|
│ [ TechniqueBar (top-right) ] [ Sky-finder actions (top-right) ] │
|
||||||
|
│ │
|
||||||
|
│ ┌────────────────────────────┐ ┌──────────┐ │
|
||||||
|
│ │ │ │ Wide PIP │ ← wide-angle │
|
||||||
|
│ │ MAIN PREVIEW (RTSP) │ │ preview │ inset (top-L) │
|
||||||
|
│ │ Tele camera │ └──────────┘ │
|
||||||
|
│ │ (RtspPlayerView) │ │
|
||||||
|
│ │ + TrackBoxView overlay │ [ RGB container (right) ] │
|
||||||
|
│ │ + PreviewBorderView │ │
|
||||||
|
│ │ + ShootingProgressView │ │
|
||||||
|
│ └────────────────────────────┘ │
|
||||||
|
│ │
|
||||||
|
│ ┌─Left─┐ ┌─Joystick─┐ ┌──Right panel──┐ │
|
||||||
|
│ │panel │ │ (polar │ │ Focus │ │
|
||||||
|
│ │ │ │ D-pad) │ │ ┌───────────┐ │ │
|
||||||
|
│ │ ✕back│ │ │ │ │ CAPTURE │ │ │
|
||||||
|
│ │ PIP │ └──────────┘ │ │ BUTTON │ │ │
|
||||||
|
│ │ more │ │ └───────────┘ │ │
|
||||||
|
│ │ ? │ [ ParameterIndicatorBar ] │ Parameter │ │
|
||||||
|
│ │ album│ [ DeviceIndicatorBar ] └───────────────┘ │
|
||||||
|
│ │ clear│ │
|
||||||
|
│ └──────┘ [ GoTo composition pill ] [ ZoomLensPanel ] │
|
||||||
|
│ │
|
||||||
|
│ (overlays: FocusProgress, StopProgress, CaptureStatus, │
|
||||||
|
│ FullscreenProgress, CaliFrameProgress, PanoComposition) │
|
||||||
|
└──────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5.2 Left control panel (`view_capture_left_control_panel.xml`, 48dp wide)
|
||||||
|
Vertical icon stack, top→bottom:
|
||||||
|
| id | icon | action |
|
||||||
|
|----|------|--------|
|
||||||
|
| `iv_photography_cancel` | arrow-left | **Back** (exit capture) |
|
||||||
|
| `iv_photography_pip` | pip icon | **Toggle PIP** (picture-in-picture wide inset) |
|
||||||
|
| `iv_photography_more_feature_set` | (dynamic) | **More settings** (opens `CamMoreFeatureSetDialog`) |
|
||||||
|
| `iv_photography_guide` | question-circle | **Guide/help** (hidden by default) |
|
||||||
|
| `iv_open_album` | album icon | **Open Album** (jump to gallery) |
|
||||||
|
| `ivClearAll` | clear-all | **Clear** (reset selection/overlay) |
|
||||||
|
|
||||||
|
### 5.3 Right control panel (`view_capture_right_panel.xml`, 84dp wide)
|
||||||
|
Vertical stack:
|
||||||
|
| id | label | icon | action |
|
||||||
|
|----|-------|------|--------|
|
||||||
|
| `btn_focus_view_capture_right_panel` | **Focus** (`camera_general_2`) | `icon_function_main_focus` | Open focus controls (AF, manual, astro-AF) |
|
||||||
|
| `item_main_capture_button_view` | — (76dp circular) | dynamic | **Main shutter** (see §5.5) |
|
||||||
|
| `btn_parameter_view_capture_right_panel` | **Parameter** (`camera_astro_222`) | `icon_function_general_parameter` | Open `CamParameterSetDialog` (exposure/gain/WB/ISP) |
|
||||||
|
|
||||||
|
`ZoomLensPanel` sits just left of the right panel (zoom/crop-ratio control).
|
||||||
|
|
||||||
|
### 5.4 TechniqueBar (top-right) — mode selector
|
||||||
|
A pill that shows the current **ShootingModeType** + **ShootingTech** and a
|
||||||
|
right-side action (`RightActionType`). Tapping opens
|
||||||
|
`ShootingModeSelectDialog` to pick a mode.
|
||||||
|
|
||||||
|
**`ShootingModeType`** (the "scene"/target class) — `ShootingModeType.java`:
|
||||||
|
| value | name | notes |
|
||||||
|
|-------|------|-------|
|
||||||
|
| 1 | `NORMAL` | generic |
|
||||||
|
| 2 | `DSO` | deep-sky object (needs calibration + EQ) |
|
||||||
|
| 3 | `SUN_MOON` | solar/lunar |
|
||||||
|
| 4 | `MILKY_WAY` | Milky Way wide-field |
|
||||||
|
| 5 | `STAR_TRAIL` | star-trail time accumulation |
|
||||||
|
| 6 | `AUTO_TRACKING` | generic object tracking |
|
||||||
|
| 7 | `PANORAMA` | panorama/grid capture |
|
||||||
|
| 8 | `SUN` | sun (ND filter warning!) |
|
||||||
|
| 9 | `MOON` | moon |
|
||||||
|
| 10 | `PLANET` | planetary |
|
||||||
|
| 0 | `UNKNOWN` | default |
|
||||||
|
|
||||||
|
Each mode carries flags: `isWidePreviewOnly`, `isWidePreviewSuggested`,
|
||||||
|
`isPipWindowBtnEnable`, `isHidePip`, `isViewRectangleVisible`,
|
||||||
|
`isAddQuickSet`, `cameraType` (Tele/Wide), `shootingTech`,
|
||||||
|
`isAstroFocus`, `isShowAutoFocusSwitch`, `isSunOrMoon`, `isLongTouchStop`,
|
||||||
|
`isSolarSystem`, `isShowZoomLens`, `isEnterAtlasVisible`, `isEnableCurves`,
|
||||||
|
`isAreaFocusEnable`. These drive which UI controls are visible.
|
||||||
|
|
||||||
|
**`ShootingTech`** (the capture technique) — `ShootingTech.java`:
|
||||||
|
| value | name | UI ring style |
|
||||||
|
|-------|------|---------------|
|
||||||
|
| 0 | `UNKNOWN` | — |
|
||||||
|
| 1 | `SINGLE_SHOT` | single photo |
|
||||||
|
| 2 | `STACKING` | live-stacking (astro) |
|
||||||
|
| 3 | `BURST` | burst |
|
||||||
|
| 4 | `VIDEO` | video record |
|
||||||
|
| 5 | `TIMELAPSE` | timelapse |
|
||||||
|
| 6 | `PANORAMA` | panorama/grid |
|
||||||
|
|
||||||
|
**`RightActionType`** (what the TechniqueBar's right button does):
|
||||||
|
`NORMAL, FOCUS, PARAMETER, TECHNOLOGY, TECHNOLOGY_SETTING, MODE, LongPressStop`.
|
||||||
|
|
||||||
|
### 5.5 Main capture button (`MainCaptureButtonView`)
|
||||||
|
A 76dp circular shutter whose appearance is driven by **`CaptureState`**
|
||||||
|
(`CaptureState.java`) and the current `ShootingModeType`/`ShootingTech`.
|
||||||
|
States include:
|
||||||
|
`None, PreparingAstronomyDarkFrame, RawDarkTaking, RawDarkStopping,
|
||||||
|
RawDarkStopped, RawTaking, RawStopping, GoLive, AIEnhance, AIEnhanceStopping,
|
||||||
|
PanoramaTaking, PanoramaStopping, RecordTaking, RecordStopping, …`
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
- **Tap** → start capture (photo/burst/stack/record depending on tech).
|
||||||
|
- **Long-press** → stop (`isLongPressTriggered`; shows `item_long_press_stop`
|
||||||
|
pill "Long Press to Stop" / `camera_general_153`, then "Stopping…").
|
||||||
|
- Ring/teeth animations reflect exposure countdown (`ShootingProgressView`)
|
||||||
|
and long-exposure progress (`NotifyProto.LongExpPhotoProgress`).
|
||||||
|
|
||||||
|
### 5.6 Joystick (`PolarDpadJoystickView`, 258dp)
|
||||||
|
Bottom-left polar D-pad for manual slewing. Sends
|
||||||
|
`CMD_STEP_MOTOR_SERVICE_JOYSTICK` (14006) with `vector_angle`/`vector_length`.
|
||||||
|
Has low/high speed indicators and four directional triangle overlays.
|
||||||
|
|
||||||
|
### 5.7 Overlays (z-ordered by elevation)
|
||||||
|
| Widget | elevation | purpose |
|
||||||
|
|--------|-----------|---------|
|
||||||
|
| `TrackBoxView` (tele + wide) | 4dp | tracking bounding-box overlay |
|
||||||
|
| `PreviewBorderView` | — | PIP border / crop frame |
|
||||||
|
| `ShootingProgressView` (main + minor) | 1dp | exposure countdown ring/text |
|
||||||
|
| `FocusProgressLayout` | 3dp | autofocus sweep overlay |
|
||||||
|
| `StopProgressLayout` | 3dp | stop-in-progress overlay |
|
||||||
|
| `CaptureStatusLayout` | 3dp | status HUD (bottom-center) |
|
||||||
|
| `FullscreenProgressLayout` | 4dp | full-screen progress (calibration, GoTo) |
|
||||||
|
| `CaliFrameProgressLayout` | 4dp | calibration-frame progress |
|
||||||
|
| `PanoCompositionLayout` | 30dp (top) | panorama composition canvas |
|
||||||
|
| `ParameterIndicatorBar` / `DeviceIndicatorBar` | 1dp | bottom status chips |
|
||||||
|
|
||||||
|
### 5.8 Sky-finder / Milky-Way action rows (top-right & bottom-center)
|
||||||
|
- `item_action_sky_finder`: calibration icon, AR-toggle, exit — for the
|
||||||
|
Sky-Target-Finder / AR overlay mode (`CMD_ASTRO_START_SKY_TARGET_FINDER`).
|
||||||
|
- `item_action_milky_way`: "Locate Milky Way" (`camera_astro_419`) +
|
||||||
|
"Confirm" (`camera_astro_412`) pills — Milky Way composition helper.
|
||||||
|
- `flGoComposition`: "GoTo" composition pill (`camera_pano_52`) for panorama
|
||||||
|
framing.
|
||||||
|
|
||||||
|
### 5.9 Key dialogs launched from Capture
|
||||||
|
| Dialog | Trigger | Purpose |
|
||||||
|
|--------|---------|---------|
|
||||||
|
| `ShootingModeSelectDialog` | TechniqueBar tap | Pick ShootingModeType |
|
||||||
|
| `CamModeSelectDialog` | mode button | Pick ShootingTech (photo/video/stack/…) |
|
||||||
|
| `CamParameterSetDialog` / `CamParamSetVM` | Parameter button | Exposure/Gain/WB/ISP per camera |
|
||||||
|
| `CamMoreFeatureSetDialog` | left "more" icon | Extra feature toggles |
|
||||||
|
| `PenalSetDialog` | panel button | Side-panel config |
|
||||||
|
| `StatusHUDDialog` | indicator bar | Detailed status overlay |
|
||||||
|
| `DarkSceneShootingDialog` | dark-frame flow | Dark-frame capture wizard |
|
||||||
|
| `CaliFramePrepareDialog` | cali-frame flow | Calibration-frame prep |
|
||||||
|
| `AtlasGotoDialog` | GoTo action | Confirm GoTo target |
|
||||||
|
| `AiEnhanceProgressDialog` | AI enhance | AI post-process progress |
|
||||||
|
| `ReservationCurveDialog` | curves | Tone/exposure curves editor |
|
||||||
|
| `SkyFinderNodeTargetsDialog` | sky finder | Pick target from AR nodes |
|
||||||
|
| `TrackSunHintDialog` | sun tracking | Sun-tracking safety hint |
|
||||||
|
| `BottomTipDialog` / `TipDialog` / `MessageDialog` | various | Tips & confirmations |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Settings tab (`SettingsFragment`) — `fragment_settings.xml`
|
||||||
|
|
||||||
|
A single `RecyclerView` whose rows are built programmatically in
|
||||||
|
`SettingsFragment.java` (grouped sections). Title: "Settings" (`settings_1`).
|
||||||
|
|
||||||
|
### 6.1 Top-level rows (from nav actions on `navigation_settings`)
|
||||||
|
| Row (string) | Destination fragment |
|
||||||
|
|--------------|----------------------|
|
||||||
|
| Profile / Login-Register | `ProfileFragment` / `LoginRegisterFragment` |
|
||||||
|
| **My Device** (`settings_2`) | `MyDeviceFragment` |
|
||||||
|
| **Connection Settings** (`settings_3`) | `ConnectionSettingsFragment` |
|
||||||
|
| **Advanced Settings** (`settings_4`) | `AdvancedFragment` |
|
||||||
|
| **Location** (`settings_5`) | `LocationFragment` |
|
||||||
|
| **General** (`settings_6`) | `GeneralFragment` |
|
||||||
|
| **Voice Assistant** | `VoiceAssistantFragment` |
|
||||||
|
| **Support** (`settings_7`) | `SupportFragment` |
|
||||||
|
| **About** (`settings_9`) | `AboutFragment` |
|
||||||
|
| Clear Cache (`settings_8`) | (action, no nav) |
|
||||||
|
|
||||||
|
### 6.2 My Device (`MyDeviceFragment`) sub-tree
|
||||||
|
- Device name → `DeviceNameFragment` (edit name; also triggers NFC update).
|
||||||
|
- Device password → `DevicePasswordFragment` (change pwd; `isDefaultPwd` flag)
|
||||||
|
→ `DeviceResetFragment` (factory reset).
|
||||||
|
- **NFC Update** (`settings_64`) → `NfcWriteActivity` — hold phone near ring light.
|
||||||
|
- **Activation info** → `ActivateInfoFragment` (status, time, warranty).
|
||||||
|
- **Storage** → `StorageFragment` (total/available size args).
|
||||||
|
- Firmware/OTA — reuses `OTAUpgradeFragment`.
|
||||||
|
|
||||||
|
### 6.3 Connection Settings (`ConnectionSettingsFragment`)
|
||||||
|
Toggles + radio (strings `settings_connection_1–29`):
|
||||||
|
- **Connection mode**: Auto / STA / AP (radio).
|
||||||
|
- **Activate Wi-Fi at Startup** (switch).
|
||||||
|
- **Enable 2.4GHz**, **Wi-Fi Compatible Mode** (switches).
|
||||||
|
- **Region** → `RegionSettingsFragment` (country code).
|
||||||
|
- Configure STA network → `WiFiListFragment` → `StaInfoFragment`/`StaInfoSetFragment`.
|
||||||
|
|
||||||
|
### 6.4 General (`GeneralFragment`) sub-tree
|
||||||
|
- **Language** → `LanguageSettingsFragment`.
|
||||||
|
- **Temperature unit** → `TemperatureUnitFragment`.
|
||||||
|
- **Appearance / Dark mode** → `AppearanceFragment`.
|
||||||
|
- **Image correction** → `ImageCorrectionFragment` → list (`ImageCorrectionListFragment`) → item (`ImageCorrectionListItemFragment`) + helper.
|
||||||
|
- **Floating window** → `FloatingWindowFragment`.
|
||||||
|
- **Calendar** (dialog) → `CalendarFragment`.
|
||||||
|
- **Auto-stop duration** → `AutoStopDurationFragment`.
|
||||||
|
- **Emotion / voice** → `EmotionFragment`, `EmotionScaleFragment`, `SpeechRateFragment`, `VoiceTypeFragment`, `VoiceNavigationModeFragment`.
|
||||||
|
- **Upload log / Log type** → `UploadLogFragment`, `LogTypeFragment`.
|
||||||
|
|
||||||
|
### 6.5 Advanced (`AdvancedFragment`)
|
||||||
|
Device-level toggles: master lock, MTP mode, CPU mode, low-temp protection,
|
||||||
|
lens defog, auto-cooling, auto-shutdown (the `CMD_SYSTEM_*` / `CMD_DEVICE_*`
|
||||||
|
commands). Shows `layout_advanced_settings_unavailable.xml` when the connected
|
||||||
|
device/firmware doesn't support an option.
|
||||||
|
|
||||||
|
### 6.6 Support / About
|
||||||
|
- **Support** (`settings_7`): FAQ/web links, contact `support@dwarflab.com`,
|
||||||
|
log upload.
|
||||||
|
- **About** (`settings_9`): app version, OSS notice
|
||||||
|
(`site.dwarflabapp.com/app-about/open-source-software-android`), privacy &
|
||||||
|
terms (en/zh).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. OTA / firmware upgrade flow
|
||||||
|
|
||||||
|
```
|
||||||
|
UpgradeReminderFragment (dialog: "new firmware available")
|
||||||
|
└─▶ OTAUpgradeFragment (download + apply)
|
||||||
|
└─▶ WiFiConnectFragment (dialog, if scope needs Wi-Fi for download)
|
||||||
|
```
|
||||||
|
- Args: `ssid`, `psd`, `isStaMode` — the scope may need to join Wi-Fi to fetch
|
||||||
|
the firmware; the app drives this via BLE (`ReqSta`) then polls download
|
||||||
|
progress.
|
||||||
|
- Firmware download URL:
|
||||||
|
`https://dwarflab.com/pages/dwarflab-app-firmware-download`.
|
||||||
|
- `FirmwareForceUpdateDialog` blocks the app if firmware is too old for a
|
||||||
|
required feature (e.g. astrophotography — see `camera_astro_116`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Schedule / shooting-plan flow
|
||||||
|
|
||||||
|
```
|
||||||
|
HomeFragment
|
||||||
|
└─▶ ScheduleFragment (list of plans)
|
||||||
|
├─▶ ScheduleDetailFragment (edit one plan; add targets, set params)
|
||||||
|
│ └─▶ ScheduleErrorReasonFragment (if sync fails) [args: reason]
|
||||||
|
└─▶ (sync/lock/unlock/delete via ScheduleProto cmds 16100–16108)
|
||||||
|
```
|
||||||
|
- A plan = a timed shooting session with one or more targets, per-camera
|
||||||
|
params, and a date/time window (sunset→sunrise auto-calculated from Atlas).
|
||||||
|
- Plans can be **locked** (16107) so they reserve their time slot; unlocking
|
||||||
|
(16106) frees it.
|
||||||
|
- "Add to Schedule" (`camera_general_113`), "Date of Plan"
|
||||||
|
(`camera_general_114`), and the 12-hour-ahead sync limit
|
||||||
|
(`camera_general_118`) are key UX constraints.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Shared UI conventions & components
|
||||||
|
|
||||||
|
### 9.1 Custom widgets (`ui/widget/`)
|
||||||
|
| Widget | Path | Role |
|
||||||
|
|--------|------|------|
|
||||||
|
| `RtspPlayerView` | `media/` | RTSP preview (ijkplayer, TCP transport) |
|
||||||
|
| `PolarDpadJoystickView` | `widget/joystick/` | Polar slew D-pad |
|
||||||
|
| `TechniqueBar` | `widget/capture/` | Mode/tech selector pill |
|
||||||
|
| `MainCaptureButtonView` | `widget/capture/` | Circular shutter |
|
||||||
|
| `CaptureLeftControlPanel` / `CaptureRightControlPanel` | `widget/capture/` | Side control columns |
|
||||||
|
| `ZoomLensPanel` | `widget/capture/` | Zoom / crop-ratio |
|
||||||
|
| `ParameterIndicatorBar` / `DeviceIndicatorBar` | `widget/capture/` | Bottom status chips |
|
||||||
|
| `ShootingProgressView` | `widget/capture/` | Exposure countdown ring |
|
||||||
|
| `TrackBoxView` | `widget/camera/module/` | Tracking bbox overlay |
|
||||||
|
| `PreviewBorderView` | `widget/camera/module/` | PIP/crop border |
|
||||||
|
| `PanoPreviewGridLineView` | `widget/camera/module/` | Panorama grid |
|
||||||
|
| `TargetRectView` | `widget/camera/module/` | Target rectangle |
|
||||||
|
| `FocusProgressLayout` / `StopProgressLayout` | `widget/camera/module/` | Full-screen progress |
|
||||||
|
| `RGBContainerLayout` | `widget/camera/function/` | RGB ring-light control |
|
||||||
|
| `FullscreenProgressLayout` / `CaliFrameProgressLayout` / `PanoCompositionLayout` | `widget/capture/` | Full-screen overlays |
|
||||||
|
| `DWRangeSliderView` | `widget/atlas/` | Range slider (params) |
|
||||||
|
| `FitSystemView` | `widget/` | Status-bar inset helper |
|
||||||
|
|
||||||
|
### 9.2 Design tokens
|
||||||
|
- Material 3 color scheme: `dl_color_on_surface`, `dl_color_surface_container_low_dark`,
|
||||||
|
`dl_color_primary_dark`, `dl_color_mask_strong`, `dl_color_border_variant_dark`,
|
||||||
|
`dl_color_white_80`, `dl_color_transparent`…
|
||||||
|
- Spacing scale: `dl_gap_level_4/8/12/16/24/32` (4-pt grid), `dl_margin_level_3`,
|
||||||
|
`dl_padding_level_2`, `dl_radius_rounded`, `dl_radius_medium`.
|
||||||
|
- Typography styles: `title_large_emphasized`, `title_small_emphasized`,
|
||||||
|
`body_medium`, `body_medium_emphasized`, `body_small_emphasized`,
|
||||||
|
`label_medium`, `Photography_label_2`, `CamControlBtnStyle`.
|
||||||
|
- Transitions: `right_slide_enter/exit`, `left_slide_enter/exit` (push),
|
||||||
|
`dialog_bottom_enter/exit` (bottom-sheets).
|
||||||
|
|
||||||
|
### 9.3 Guide / onboarding overlays
|
||||||
|
`ui/guide/overlay/`: `BaseGuideDialogFragment`,
|
||||||
|
`GuideDialogFragment`, `ActivityGuideDialogFragment`,
|
||||||
|
`FullScreenOverlayDialogFragment` — coach-mark overlays with anchor points
|
||||||
|
(`ui/guide/anchor/`) used for first-run feature discovery.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Internationalization
|
||||||
|
|
||||||
|
- Default strings in `res/values/strings.xml`; localized variants exist
|
||||||
|
(Chinese `values-zh`, etc.). All user-visible text is keyed
|
||||||
|
(`camera_astro_N`, `camera_general_N`, `settings_N`, `home_N`,
|
||||||
|
`settings_connection_N`, `album_N`, `guide_N`…).
|
||||||
|
- Help docs link to language-specific URLs:
|
||||||
|
`https://help.dwarflab.com/en` vs `/zh`.
|
||||||
|
- Voice assistant has its own strings and supports emotion/speech-rate tuning.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Map: UI action → API command
|
||||||
|
|
||||||
|
| UI action | WS command(s) | Proto |
|
||||||
|
|-----------|---------------|-------|
|
||||||
|
| Tap shutter (photo) | 10002 / 12022 | `ReqPhotograph` |
|
||||||
|
| Burst start/stop | 10003 / 10004 | `…Burst` |
|
||||||
|
| Video record start/stop | 10005 / 10006 | `…Record` |
|
||||||
|
| Set exposure | 10009 / 12004 | `ReqSetExp` |
|
||||||
|
| Set gain | 10013 / 12006 | `ReqSetGain` |
|
||||||
|
| WB / brightness / contrast / saturation / hue / sharpness | 10015–10024 | `ReqSetWB…` |
|
||||||
|
| Open/close camera | 10000/10001 (tele), 12000/12001 (wide) | — |
|
||||||
|
| Joystick slew | 14006 | `ReqMotorServiceJoystick` |
|
||||||
|
| GoTo target | 11002/11003/11013/11014 | `ReqStartGotoDSO`/`…SolarSystem` |
|
||||||
|
| Calibrate | 11000 | `ReqStartCalibration` |
|
||||||
|
| Live stacking | 11005/11006 | `Req…LiveStacking` |
|
||||||
|
| Dark frames | 11007/11021 | `Req…RawDark…` |
|
||||||
|
| Auto-focus | 15000 | `ReqAutoFocus` |
|
||||||
|
| Start track | 14800 | `ReqStartTrack` |
|
||||||
|
| Panorama grid | 15500/15501 | `Req…Grid` |
|
||||||
|
| AI enhance | 11029/11030 | `Req…AiEnhance` |
|
||||||
|
| EQ solving | 11018/11019 | `Req…EqSolving` |
|
||||||
|
| Power / reboot / RGB | 13500–13505 | `RGB.proto` |
|
||||||
|
| Set time/location | 13000/13010 | `ReqSetTime`/`ReqSetLocation` |
|
||||||
|
| Sync schedule | 16100 | `Schedule.proto` |
|
||||||
|
|
||||||
|
Full command table: `CMD_TABLE.md`. Proto payloads: `analysis/protos/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Suggested reimplementation plan (cross-platform)
|
||||||
|
|
||||||
|
1. **Screens to build first** (MVP): Splash → Home (connect CTA) →
|
||||||
|
DeviceSearch (BLE) → DeviceConnect (password) → Capture (preview + shutter
|
||||||
|
+ params + joystick) → Settings (My Device + Connection).
|
||||||
|
2. **State model**: a single `DeviceStore` (connected? device_id, ip, cameras
|
||||||
|
on/off, current ShootingModeType/Tech, CaptureState, live params) fed by
|
||||||
|
the WebSocket NOTIFY stream (§API_REFERENCE §3.2). All UI reads from this.
|
||||||
|
3. **Capture screen** is the hard part — replicate the overlay z-order
|
||||||
|
(§5.7) and drive the capture button from `CaptureState`.
|
||||||
|
4. **Two preview surfaces** (Tele main + Wide PIP) each need an RTSP
|
||||||
|
consumer; toggle PIP via `CMD_SWITCH_MAIN_PREVIEW` (14809).
|
||||||
|
5. Keep the **mode-driven visibility** model: each `ShootingModeType` flag
|
||||||
|
(`isWidePreviewOnly`, `isAstroFocus`, `isShowZoomLens`…) controls which
|
||||||
|
controls render — don't hardcode per-screen logic.
|
||||||
150
analysis/extract_protos.py
Normal file
150
analysis/extract_protos.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Extract serialized FileDescriptorProto bytes from jadx-generated *Proto.java
|
||||||
|
files and regenerate clean .proto definitions using the real protobuf library.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from google.protobuf import descriptor_pb2
|
||||||
|
|
||||||
|
# proto3 -> no "optional" label; proto2 prints labels.
|
||||||
|
TYPE_MAP = {
|
||||||
|
1: 'double', 2: 'float', 3: 'int64', 4: 'uint64', 5: 'int32',
|
||||||
|
6: 'fixed64', 7: 'fixed32', 8: 'bool', 9: 'string', 11: 'message',
|
||||||
|
12: 'bytes', 13: 'uint32', 14: 'enum', 15: 'sfixed32', 16: 'sfixed64',
|
||||||
|
17: 'sint32', 18: 'sint64',
|
||||||
|
}
|
||||||
|
|
||||||
|
def field_type_str(f):
|
||||||
|
if f.type_name:
|
||||||
|
return f.type_name.lstrip('.')
|
||||||
|
return TYPE_MAP.get(f.type, f'scalar{f.type}')
|
||||||
|
|
||||||
|
def render_field(f, syntax):
|
||||||
|
ty = field_type_str(f)
|
||||||
|
label = ''
|
||||||
|
if f.label == descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED:
|
||||||
|
if f.options.packed:
|
||||||
|
label = 'packed repeated '
|
||||||
|
else:
|
||||||
|
label = 'repeated '
|
||||||
|
elif syntax == 'proto2' and f.label == descriptor_pb2.FieldDescriptorProto.LABEL_REQUIRED:
|
||||||
|
label = 'required '
|
||||||
|
elif syntax == 'proto2':
|
||||||
|
label = 'optional '
|
||||||
|
return f' {label}{ty} {f.name} = {f.number};'
|
||||||
|
|
||||||
|
def render_enum(e, indent):
|
||||||
|
lines = [f'{indent}enum {e.name} {{']
|
||||||
|
for v in e.value:
|
||||||
|
lines.append(f'{indent} {v.name} = {v.number};')
|
||||||
|
lines.append(f'{indent}}}')
|
||||||
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
def render_message(m, indent, syntax):
|
||||||
|
lines = [f'{indent}message {m.name} {{']
|
||||||
|
for oneof in m.oneof_decl:
|
||||||
|
lines.append(f'{indent} // oneof {oneof.name}')
|
||||||
|
for nested in m.enum_type:
|
||||||
|
lines.append(render_enum(nested, indent + ' '))
|
||||||
|
for nested in m.nested_type:
|
||||||
|
lines.append(render_message(nested, indent + ' ', syntax))
|
||||||
|
for f in m.field:
|
||||||
|
lines.append(render_field(f, syntax))
|
||||||
|
lines.append(f'{indent}}}')
|
||||||
|
return '\n'.join(lines)
|
||||||
|
|
||||||
|
def render_file(fd):
|
||||||
|
out = [f'// source: {fd.name}']
|
||||||
|
if fd.package:
|
||||||
|
out.append(f'package {fd.package};')
|
||||||
|
syntax = fd.syntax or 'proto3'
|
||||||
|
out.append(f'syntax = "{syntax}";')
|
||||||
|
if fd.dependency:
|
||||||
|
out.append('')
|
||||||
|
for dep in fd.dependency:
|
||||||
|
out.append(f'import "{dep}";')
|
||||||
|
out.append('')
|
||||||
|
for e in fd.enum_type:
|
||||||
|
out.append(render_enum(e, ''))
|
||||||
|
out.append('')
|
||||||
|
for m in fd.message_type:
|
||||||
|
out.append(render_message(m, '', syntax))
|
||||||
|
out.append('')
|
||||||
|
return '\n'.join(out)
|
||||||
|
|
||||||
|
DESC_RE = re.compile(
|
||||||
|
r'internalBuildGeneratedFileFrom\(new String\[\]\{(.*?)\}\s*,\s*new Descriptors',
|
||||||
|
re.DOTALL)
|
||||||
|
|
||||||
|
def decode_java_string_literal_body(lit):
|
||||||
|
"""Decode a Java string-literal body (between quotes) to raw bytes."""
|
||||||
|
out = bytearray()
|
||||||
|
i = 0; n = len(lit)
|
||||||
|
while i < n:
|
||||||
|
c = lit[i]
|
||||||
|
if c == '\\':
|
||||||
|
nxt = lit[i+1]
|
||||||
|
simple = {'n': 10, 'r': 13, 't': 9, '"': 34, "'": 39, '\\': 92, '0': 0, 'b': 8, 'f': 12}
|
||||||
|
if nxt in simple:
|
||||||
|
out.append(simple[nxt]); i += 2
|
||||||
|
elif nxt == 'u':
|
||||||
|
out += chr(int(lit[i+2:i+6], 16)).encode('latin-1', 'replace')
|
||||||
|
i += 6
|
||||||
|
else:
|
||||||
|
out.append(ord(nxt) & 0xff); i += 2
|
||||||
|
else:
|
||||||
|
out += c.encode('latin-1', 'replace'); i += 1
|
||||||
|
return bytes(out)
|
||||||
|
|
||||||
|
def extract_descriptor_bytes(java_path):
|
||||||
|
txt = open(java_path, encoding='utf-8', errors='replace').read()
|
||||||
|
m = DESC_RE.search(txt)
|
||||||
|
if not m:
|
||||||
|
return None
|
||||||
|
body = m.group(1)
|
||||||
|
lits = re.findall(r'"((?:[^"\\]|\\.)*)"', body)
|
||||||
|
# protobuf concatenates ALL adjacent string elements into ONE descriptor
|
||||||
|
combined = b''.join(decode_java_string_literal_body(l) for l in lits)
|
||||||
|
return combined if combined else None
|
||||||
|
|
||||||
|
def main():
|
||||||
|
proto_dir = sys.argv[1]
|
||||||
|
out_dir = sys.argv[2]
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
total_msgs = 0
|
||||||
|
for fn in sorted(os.listdir(proto_dir)):
|
||||||
|
if not fn.endswith('Proto.java'):
|
||||||
|
continue
|
||||||
|
path = os.path.join(proto_dir, fn)
|
||||||
|
raw = extract_descriptor_bytes(path)
|
||||||
|
base = fn[:-5].replace('Proto', '')
|
||||||
|
if not raw:
|
||||||
|
print(f' [WARN] no descriptor in {fn}')
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
fd_set = descriptor_pb2.FileDescriptorSet()
|
||||||
|
fd = fd_set.file.add()
|
||||||
|
fd.MergeFromString(raw)
|
||||||
|
except Exception as ex:
|
||||||
|
# may be a FileDescriptorSet directly, or multiple
|
||||||
|
try:
|
||||||
|
fd_set.ParseFromString(raw)
|
||||||
|
if not fd_set.file:
|
||||||
|
raise
|
||||||
|
except Exception as ex2:
|
||||||
|
print(f' [ERR ] {fn}: {ex2}')
|
||||||
|
continue
|
||||||
|
out_path = os.path.join(out_dir, base + '.proto')
|
||||||
|
chunks = []
|
||||||
|
for one_fd in fd_set.file:
|
||||||
|
chunks.append(render_file(one_fd))
|
||||||
|
total_msgs += len(one_fd.message_type)
|
||||||
|
with open(out_path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write('\n\n'.join(chunks) + '\n')
|
||||||
|
print(f' [OK] {fn} -> {base}.proto ({len(raw)} bytes, {len(fd_set.file)} file(s), {sum(len(x.message_type) for x in fd_set.file)} msgs)')
|
||||||
|
print(f'\nTotal messages recovered: {total_msgs}')
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
368
analysis/protos/Astro.proto
Normal file
368
analysis/protos/Astro.proto
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
// source: astro.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqStartCalibration {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCalibration {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGotoDSO {
|
||||||
|
double ra = 1;
|
||||||
|
double dec = 2;
|
||||||
|
string target_name = 3;
|
||||||
|
bool goto_only = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGotoSolarSystem {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
string target_name = 4;
|
||||||
|
bool force_start = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGotoSolarSystem {
|
||||||
|
int32 code = 1;
|
||||||
|
ReqGotoSolarSystem req = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopGoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureRawLiveStacking {
|
||||||
|
int32 ir_index = 1;
|
||||||
|
bool force_start = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqFastStopCaptureRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCheckDarkFrame {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCheckDarkFrame {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureDarkFrame {
|
||||||
|
int32 reshoot = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureDarkFrame {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureDarkFrameWithParam {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
int32 cap_size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureDarkFrameWithParam {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDarkFrameList {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDarkFrameInfo {
|
||||||
|
// oneof _temperature
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
string exp_name = 4;
|
||||||
|
string gain_name = 5;
|
||||||
|
string bin_name = 6;
|
||||||
|
int32 temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDarkFrameInfoList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated ResGetDarkFrameInfo results = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelDarkFrame {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
int32 temp_value = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelDarkFrameList {
|
||||||
|
repeated ReqDelDarkFrame dark_list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDelDarkFrameList {
|
||||||
|
int32 code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGoLive {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqTrackSpecialTarget {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTrackSpecialTarget {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickGotoDSO {
|
||||||
|
double ra = 1;
|
||||||
|
double dec = 2;
|
||||||
|
string target_name = 3;
|
||||||
|
double lon = 4;
|
||||||
|
double lat = 5;
|
||||||
|
int32 shooting_mode = 6;
|
||||||
|
bool goto_only = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResOneClickGoto {
|
||||||
|
int32 step = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
bool all_end = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickGotoSolarSystem {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
string target_name = 4;
|
||||||
|
int32 shooting_mode = 5;
|
||||||
|
bool force_start = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResOneClickGotoSolarSystem {
|
||||||
|
int32 step = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
bool all_end = 3;
|
||||||
|
ReqOneClickGotoSolarSystem req = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopOneClickGoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureWideRawLiveStacking {
|
||||||
|
bool force_start = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureWideRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqFastStopCaptureWideRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartEqSolving {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStartEqSolving {
|
||||||
|
double azi_err = 1;
|
||||||
|
double alt_err = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopEqSolving {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartAiEnhance {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopAiEnhance {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartMosaic {
|
||||||
|
int32 horizontal_scale = 1;
|
||||||
|
int32 vertical_scale = 2;
|
||||||
|
int32 rotation = 3;
|
||||||
|
int32 ir_index = 4;
|
||||||
|
bool force_start = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartMakeFitsThumb {
|
||||||
|
string src_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopMakeFitsThumb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMakeFitsThumb {
|
||||||
|
int32 code = 1;
|
||||||
|
string src_dir = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MakeFitsThumbTaskParam {
|
||||||
|
string src_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqIsImageStackable {
|
||||||
|
repeated string src_dirs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResIsImageStackable {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated ResGetDarkFrameInfo need_dark_frame_info = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartRepostprocess {
|
||||||
|
repeated string src_dirs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopRepostprocess {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResRepostprocess {
|
||||||
|
int32 code = 1;
|
||||||
|
string result_dir = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepostprocessTaskParam {
|
||||||
|
string result_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAstroShootingTime {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 horizontal_scale = 2;
|
||||||
|
int32 vertical_scale = 3;
|
||||||
|
int32 rotation = 4;
|
||||||
|
int32 cam_id = 5;
|
||||||
|
int32 shooting_mode = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAstroShootingTime {
|
||||||
|
enum AstroMode {
|
||||||
|
NORMAL = 0;
|
||||||
|
MOSAIC = 1;
|
||||||
|
}
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_time = 2;
|
||||||
|
int32 cam_id = 3;
|
||||||
|
ResGetAstroShootingTime.AstroMode astro_mode = 4;
|
||||||
|
int32 shooting_mode = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetCaliFrameList {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 cali_frame_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaliFrameInfo {
|
||||||
|
// oneof _filter_type
|
||||||
|
// oneof _info_id
|
||||||
|
// oneof _temp_value
|
||||||
|
string exp_name = 1;
|
||||||
|
int32 gain = 2;
|
||||||
|
int32 resolution = 3;
|
||||||
|
int32 camera_type = 4;
|
||||||
|
int32 progress = 5;
|
||||||
|
int32 cali_frame_type = 6;
|
||||||
|
int32 filter_type = 7;
|
||||||
|
int32 info_id = 8;
|
||||||
|
int32 temp_value = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetCaliFrameList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated CaliFrameInfo list = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
int32 cali_frame_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelCaliFrameList {
|
||||||
|
repeated int32 info_ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureCaliFrame {
|
||||||
|
// oneof _filter_type
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain = 2;
|
||||||
|
int32 resolution = 3;
|
||||||
|
int32 cap_size = 4;
|
||||||
|
int32 camera_type = 5;
|
||||||
|
int32 cali_frame_type = 6;
|
||||||
|
int32 filter_type = 7;
|
||||||
|
int32 scene_type = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureCaliFrame {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameTaskParam {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 cali_frame_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetQuickSetList {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message QuikSetInfo {
|
||||||
|
string exp_name = 1;
|
||||||
|
int32 exp_index = 2;
|
||||||
|
int32 gain = 3;
|
||||||
|
int32 resolution = 4;
|
||||||
|
int32 camera_type = 5;
|
||||||
|
string info_id = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetQuikSetList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated QuikSetInfo quick_set_list = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetQuickSet {
|
||||||
|
string info_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetQuickSet {
|
||||||
|
int32 code = 1;
|
||||||
|
string info_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickShooting {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResAstroShooting {
|
||||||
|
// oneof _exp_name
|
||||||
|
// oneof _gain
|
||||||
|
// oneof _resolution
|
||||||
|
// oneof _filter_type
|
||||||
|
// oneof _temp_threshold
|
||||||
|
int32 code = 1;
|
||||||
|
string exp_name = 2;
|
||||||
|
int32 gain = 3;
|
||||||
|
int32 resolution = 4;
|
||||||
|
int32 filter_type = 5;
|
||||||
|
int32 temp_threshold = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartSkyTargetFinder {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
bool force_restart = 3;
|
||||||
|
int32 scene_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStartSkyTargetFinder {
|
||||||
|
int32 code = 1;
|
||||||
|
double zenith_azi = 2;
|
||||||
|
double zenith_alt = 3;
|
||||||
|
double center_azi = 4;
|
||||||
|
double center_alt = 5;
|
||||||
|
double center_roll = 6;
|
||||||
|
int32 scene_type = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopSkyTargetFinder {
|
||||||
|
}
|
||||||
|
|
||||||
52
analysis/protos/Base.proto
Normal file
52
analysis/protos/Base.proto
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// source: base.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
enum WsMajorVersion {
|
||||||
|
WS_MAJOR_VERSION_UNKNOWN = 0;
|
||||||
|
WS_MAJOR_VERSION_NUMBER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WsMinorVersion {
|
||||||
|
WS_MINOR_VERSION_UNKNOWN = 0;
|
||||||
|
WS_MINOR_VERSION_NUMBER = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WsPacket {
|
||||||
|
uint32 major_version = 1;
|
||||||
|
uint32 minor_version = 2;
|
||||||
|
uint32 device_id = 3;
|
||||||
|
uint32 module_id = 4;
|
||||||
|
uint32 cmd = 5;
|
||||||
|
uint32 type = 6;
|
||||||
|
bytes data = 7;
|
||||||
|
string client_id = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResponse {
|
||||||
|
int32 code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithInt {
|
||||||
|
int32 value = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithDouble {
|
||||||
|
double value = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithString {
|
||||||
|
string str = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonParam {
|
||||||
|
bool hasAuto = 1;
|
||||||
|
int32 auto_mode = 2;
|
||||||
|
int32 id = 3;
|
||||||
|
int32 mode_index = 4;
|
||||||
|
int32 index = 5;
|
||||||
|
double continue_value = 6;
|
||||||
|
}
|
||||||
|
|
||||||
203
analysis/protos/Ble.proto
Normal file
203
analysis/protos/Ble.proto
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
// source: ble.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
enum VocalType {
|
||||||
|
VT_UNKNOWN = 0;
|
||||||
|
VT_PING = 1;
|
||||||
|
VT_ECHO = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetconfig {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string ble_psd = 2;
|
||||||
|
string client_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAp {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 wifi_type = 2;
|
||||||
|
int32 auto_start = 3;
|
||||||
|
int32 country_list = 4;
|
||||||
|
string country = 5;
|
||||||
|
string ble_psd = 6;
|
||||||
|
string client_id = 7;
|
||||||
|
bool force_restart = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSta {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 auto_start = 2;
|
||||||
|
string ble_psd = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string psd = 5;
|
||||||
|
string client_id = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetblewifi {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
string ble_psd = 3;
|
||||||
|
string value = 4;
|
||||||
|
string client_id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReset {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetwifilist {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetsysteminfo {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCheckFile {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string file_path = 2;
|
||||||
|
string md5 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCommon {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetconfig {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 state = 3;
|
||||||
|
int32 wifi_mode = 4;
|
||||||
|
int32 ap_mode = 5;
|
||||||
|
int32 auto_start = 6;
|
||||||
|
int32 ap_country_list = 7;
|
||||||
|
string ssid = 8;
|
||||||
|
string psd = 9;
|
||||||
|
string ip = 10;
|
||||||
|
string ap_country = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResAp {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 mode = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string psd = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSta {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
string ssid = 3;
|
||||||
|
string psd = 4;
|
||||||
|
string ip = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetblewifi {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 mode = 3;
|
||||||
|
string value = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReset {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WifiInfo {
|
||||||
|
int32 signal_level = 1;
|
||||||
|
string ssid = 2;
|
||||||
|
string security_capability = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResWifilist {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
repeated string ssid = 4;
|
||||||
|
repeated WifiInfo wifi_info_list = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetsysteminfo {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 protocol_version = 3;
|
||||||
|
string device = 4;
|
||||||
|
string mac_address = 5;
|
||||||
|
string dwarf_ota_version = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReceiveDataError {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCheckFile {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComDwarfMsg {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DwarfPing {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
uint64 timestamp = 2;
|
||||||
|
bytes magic = 3;
|
||||||
|
repeated bytes vocals = 4;
|
||||||
|
repeated bytes mutes = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StationModel {
|
||||||
|
uint32 family = 1;
|
||||||
|
uint32 revision = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NifAP {
|
||||||
|
// oneof _ipv6
|
||||||
|
string ifname = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
string country_code = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string sec = 5;
|
||||||
|
string psw = 6;
|
||||||
|
bytes ipv4 = 7;
|
||||||
|
bytes ipv6 = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NifSTA {
|
||||||
|
// oneof _ssid
|
||||||
|
// oneof _psw
|
||||||
|
// oneof _rssi
|
||||||
|
// oneof _ipv4
|
||||||
|
// oneof _ipv6
|
||||||
|
string ifname = 1;
|
||||||
|
string ssid = 2;
|
||||||
|
string psw = 3;
|
||||||
|
int32 rssi = 4;
|
||||||
|
bytes ipv4 = 5;
|
||||||
|
bytes ipv6 = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DwarfEcho {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
uint64 timestamp = 2;
|
||||||
|
bytes magic = 3;
|
||||||
|
uint64 ts_ping = 4;
|
||||||
|
bytes mac_address = 5;
|
||||||
|
StationModel model = 6;
|
||||||
|
string sn = 7;
|
||||||
|
string name = 8;
|
||||||
|
string psw = 9;
|
||||||
|
string fw_version = 10;
|
||||||
|
string ws_scheme = 11;
|
||||||
|
uint32 session = 12;
|
||||||
|
NifAP ap = 13;
|
||||||
|
NifSTA sta = 14;
|
||||||
|
}
|
||||||
|
|
||||||
217
analysis/protos/Camera.proto
Normal file
217
analysis/protos/Camera.proto
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
// source: camera.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
message ReqOpenCamera {
|
||||||
|
bool binning = 1;
|
||||||
|
int32 rtsp_encode_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCloseCamera {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPhoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqBurstPhoto {
|
||||||
|
int32 count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopBurstPhoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartRecord {
|
||||||
|
int32 encode_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopRecord {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetExpMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetExpMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetExp {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetExp {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGainMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetGainMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGain {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetGain {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetBrightness {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetBrightness {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetContrast {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetContrast {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetHue {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetHue {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetSaturation {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSaturation {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetSharpness {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSharpness {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBSence {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBSence {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBCT {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBCT {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetIrCut {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetIrcut {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTimeLapse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTimeLapse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetAllParams {
|
||||||
|
int32 exp_mode = 1;
|
||||||
|
int32 exp_index = 2;
|
||||||
|
int32 gain_mode = 3;
|
||||||
|
int32 gain_index = 4;
|
||||||
|
int32 ircut_value = 5;
|
||||||
|
int32 wb_mode = 6;
|
||||||
|
int32 wb_index_type = 7;
|
||||||
|
int32 wb_index = 8;
|
||||||
|
int32 brightness = 9;
|
||||||
|
int32 contrast = 10;
|
||||||
|
int32 hue = 11;
|
||||||
|
int32 saturation = 12;
|
||||||
|
int32 sharpness = 13;
|
||||||
|
int32 jpg_quality = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllParams {
|
||||||
|
repeated CommonParam all_params = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetFeatureParams {
|
||||||
|
CommonParam param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllFeatureParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllFeatureParams {
|
||||||
|
repeated CommonParam all_feature_params = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSystemWorkingState {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetJpgQuality {
|
||||||
|
int32 quality = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetJpgQuality {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPhotoRaw {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetRtspBitRateType {
|
||||||
|
int32 bitrate_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDisableAllIspProcessing {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqEnableAllIspProcessing {
|
||||||
|
}
|
||||||
|
|
||||||
|
message IspModuleState {
|
||||||
|
int32 module_id = 1;
|
||||||
|
bool state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetIspModuleState {
|
||||||
|
repeated IspModuleState module_states = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetIspModuleState {
|
||||||
|
repeated int32 module_ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchResolution {
|
||||||
|
int32 resolution_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchFrameRate {
|
||||||
|
int32 fps_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchCropRatio {
|
||||||
|
int32 crop_ratio = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetPreviewQuality {
|
||||||
|
uint32 level = 1;
|
||||||
|
uint32 quality = 2;
|
||||||
|
}
|
||||||
|
|
||||||
18
analysis/protos/Device.proto
Normal file
18
analysis/protos/Device.proto
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// source: device.proto
|
||||||
|
package device;
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
message ReqLensDefog {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAutoCooling {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAutoShutdown {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
39
analysis/protos/Focus.proto
Normal file
39
analysis/protos/Focus.proto
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// source: focus.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqManualSingleStepFocus {
|
||||||
|
uint32 direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqManualContinuFocus {
|
||||||
|
uint32 direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopManualContinuFocus {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqNormalAutoFocus {
|
||||||
|
uint32 mode = 1;
|
||||||
|
uint32 center_x = 2;
|
||||||
|
uint32 center_y = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAstroAutoFocus {
|
||||||
|
uint32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopAstroAutoFocus {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetUserInfinityPos {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetUserInfinityPos {
|
||||||
|
int32 pos = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResUserInfinityPos {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 pos = 2;
|
||||||
|
}
|
||||||
|
|
||||||
30
analysis/protos/ITips.proto
Normal file
30
analysis/protos/ITips.proto
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// source: itips.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqITipsGet {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResITipsGet {
|
||||||
|
int32 mode = 1;
|
||||||
|
string itips_code = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonITips {
|
||||||
|
int32 itips_status = 1;
|
||||||
|
string itips_code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonStepITips {
|
||||||
|
int32 step_id = 1;
|
||||||
|
int32 step_status = 2;
|
||||||
|
repeated CommonITips step_itips = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResITipsList {
|
||||||
|
repeated CommonStepITips itips_list = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
81
analysis/protos/MotorControl.proto
Normal file
81
analysis/protos/MotorControl.proto
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// source: motor_control.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqMotorServiceJoystick {
|
||||||
|
double vector_angle = 1;
|
||||||
|
double vector_length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorServiceJoystickFixedAngle {
|
||||||
|
double vector_angle = 1;
|
||||||
|
double vector_length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorServiceJoystickStop {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRun {
|
||||||
|
int32 id = 1;
|
||||||
|
double speed = 2;
|
||||||
|
bool direction = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution_level = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRunInPulse {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 frequency = 2;
|
||||||
|
bool direction = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution = 5;
|
||||||
|
int32 pulse = 6;
|
||||||
|
bool mode = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRunTo {
|
||||||
|
int32 id = 1;
|
||||||
|
double end_position = 2;
|
||||||
|
double speed = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution_level = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorGetPosition {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorStop {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorReset {
|
||||||
|
int32 id = 1;
|
||||||
|
bool direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorChangeSpeed {
|
||||||
|
int32 id = 1;
|
||||||
|
double speed = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorChangeDirection {
|
||||||
|
int32 id = 1;
|
||||||
|
bool direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMotor {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMotorPosition {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
double position = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDualCameraLinkage {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
}
|
||||||
|
|
||||||
518
analysis/protos/Notify.proto
Normal file
518
analysis/protos/Notify.proto
Normal file
@ -0,0 +1,518 @@
|
|||||||
|
// source: notify.proto
|
||||||
|
package notify;
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
enum OperationState {
|
||||||
|
OPERATION_STATE_IDLE = 0;
|
||||||
|
OPERATION_STATE_RUNNING = 1;
|
||||||
|
OPERATION_STATE_STOPPING = 2;
|
||||||
|
OPERATION_STATE_STOPPED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AstroState {
|
||||||
|
ASTRO_STATE_IDLE = 0;
|
||||||
|
ASTRO_STATE_RUNNING = 1;
|
||||||
|
ASTRO_STATE_STOPPING = 2;
|
||||||
|
ASTRO_STATE_STOPPED = 3;
|
||||||
|
ASTRO_STATE_PLATE_SOLVING = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SentryModeState {
|
||||||
|
SENTRY_MODE_STATE_IDLE = 0;
|
||||||
|
SENTRY_MODE_STATE_INIT = 1;
|
||||||
|
SENTRY_MODE_STATE_DETECT = 2;
|
||||||
|
SENTRY_MODE_STATE_TRACK = 3;
|
||||||
|
SENTRY_MODE_STATE_TRACK_FINISH = 4;
|
||||||
|
SENTRY_MODE_STATE_STOPPING = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SentryObjectType {
|
||||||
|
SENTRY_OBJECT_TYPE_UNKNOWN = 0;
|
||||||
|
SENTRY_OBJECT_TYPE_UFO = 1;
|
||||||
|
SENTRY_OBJECT_TYPE_BIRD = 2;
|
||||||
|
SENTRY_OBJECT_TYPE_PERSON = 3;
|
||||||
|
SENTRY_OBJECT_TYPE_ANIMAL = 4;
|
||||||
|
SENTRY_OBJECT_TYPE_VEHICLE = 5;
|
||||||
|
SENTRY_OBJECT_TYPE_FLYING = 6;
|
||||||
|
SENTRY_OBJECT_TYPE_BOAT = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PictureMatching {
|
||||||
|
uint32 x = 1;
|
||||||
|
uint32 y = 2;
|
||||||
|
uint32 width = 3;
|
||||||
|
uint32 height = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StorageInfo {
|
||||||
|
uint32 available_size = 1;
|
||||||
|
uint32 total_size = 2;
|
||||||
|
int32 storage_type = 3;
|
||||||
|
bool is_valid = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Temperature {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 temperature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CmosTemperature {
|
||||||
|
// oneof _temperature
|
||||||
|
int32 temperature = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RecordTime {
|
||||||
|
uint32 record_time = 1;
|
||||||
|
uint32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TimeLapseOutTime {
|
||||||
|
uint32 interval = 1;
|
||||||
|
uint32 out_time = 2;
|
||||||
|
uint32 total_time = 3;
|
||||||
|
uint32 camera_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OperationStateNotify {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroCalibrationState {
|
||||||
|
notify.AstroState state = 1;
|
||||||
|
int32 plate_solving_times = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroGotoState {
|
||||||
|
notify.AstroState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroTrackingState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureRawDark {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 remaining_time = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureRawLiveStacking {
|
||||||
|
// oneof _shooting_time
|
||||||
|
// oneof _stacked_time
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 update_type = 2;
|
||||||
|
int32 current_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 exp_index = 5;
|
||||||
|
int32 gain_index = 6;
|
||||||
|
string target_name = 7;
|
||||||
|
int32 camera_type = 8;
|
||||||
|
int32 shooting_time = 9;
|
||||||
|
int32 stacked_time = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Param {
|
||||||
|
repeated CommonParam param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BurstProgress {
|
||||||
|
uint32 total_count = 1;
|
||||||
|
uint32 completed_count = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaProgress {
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 completed_count = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RgbState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PowerIndState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChargingState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BatteryInfo {
|
||||||
|
int32 percentage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HostSlaveMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
bool lock = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MTPState {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackResult {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 w = 3;
|
||||||
|
int32 h = 4;
|
||||||
|
int32 id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CPUMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroTrackingSpecialState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
int32 index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PowerOff {
|
||||||
|
}
|
||||||
|
|
||||||
|
message AlbumUpdate {
|
||||||
|
int32 media_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SentryState {
|
||||||
|
notify.SentryModeState state = 1;
|
||||||
|
notify.SentryObjectType object_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OneClickGotoState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.AstroAutoFocusState astro_auto_focus_state = 1;
|
||||||
|
notify.AstroCalibrationState astro_calibration_state = 2;
|
||||||
|
notify.AstroGotoState astro_goto_state = 3;
|
||||||
|
notify.AstroTrackingState astro_tracking_state = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StreamType {
|
||||||
|
int32 stream_type = 1;
|
||||||
|
int32 cam_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiTrackResult {
|
||||||
|
repeated notify.TrackResult results = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EqSolvingState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LongExpPhotoProgress {
|
||||||
|
double total_time = 1;
|
||||||
|
double exposured_time = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingScheduleResultAndState {
|
||||||
|
string schedule_id = 1;
|
||||||
|
int32 result = 2;
|
||||||
|
int32 state = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingTaskState {
|
||||||
|
string schedule_task_id = 1;
|
||||||
|
int32 state = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SkySeacherState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressAiEnhance {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 total_time = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonProgress {
|
||||||
|
enum ProgressType {
|
||||||
|
PROGRESS_TYPE_INITING = 0;
|
||||||
|
PROGRESS_TYPE_MOSAIC_MOVING = 1;
|
||||||
|
}
|
||||||
|
int32 current = 1;
|
||||||
|
int32 total = 2;
|
||||||
|
notify.CommonProgress.ProgressType progress_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CalibrationResult {
|
||||||
|
double azi = 1;
|
||||||
|
double alt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FocusPosition {
|
||||||
|
int32 pos = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SentryAutoHand {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaStitchUploadComplete {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCompressionComplete {
|
||||||
|
int32 code = 1;
|
||||||
|
string panorama_name = 2;
|
||||||
|
string zip_file_path = 3;
|
||||||
|
string zip_file_md5 = 4;
|
||||||
|
uint64 zip_file_size = 5;
|
||||||
|
string stitch_param = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCompressionProgress {
|
||||||
|
string panorama_name = 1;
|
||||||
|
uint32 total_files_num = 2;
|
||||||
|
uint32 compressed_files_num = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadCompressionProgress {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint32 total_files_num = 5;
|
||||||
|
uint32 compressed_files_num = 6;
|
||||||
|
double speed = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadProgress {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint64 total_size = 5;
|
||||||
|
uint64 uploaded_size = 6;
|
||||||
|
double speed = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCurrentUploadState {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
uint32 total_files_num = 6;
|
||||||
|
uint32 compressed_files_num = 7;
|
||||||
|
uint64 total_size = 8;
|
||||||
|
uint64 uploaded_size = 9;
|
||||||
|
uint32 step = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LowTempProtectionMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StateSystemResourceOccupation {
|
||||||
|
enum TaskId {
|
||||||
|
IDLE = 0;
|
||||||
|
PANORAMA_UPLOAD = 1;
|
||||||
|
ASTRO_MULTI_STACK = 2;
|
||||||
|
}
|
||||||
|
notify.StateSystemResourceOccupation.TaskId task_id = 1;
|
||||||
|
notify.OperationState state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BodyStatus {
|
||||||
|
enum BodyStatusEnum {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
EQ_MODE = 1;
|
||||||
|
AZI_MODE = 2;
|
||||||
|
}
|
||||||
|
notify.BodyStatus.BodyStatusEnum body_status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureMosaic {
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 update_type = 2;
|
||||||
|
int32 current_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 exp_index = 5;
|
||||||
|
int32 gain_index = 6;
|
||||||
|
string target_name = 7;
|
||||||
|
int32 horizontal_scale = 8;
|
||||||
|
int32 vertical_scale = 9;
|
||||||
|
int32 rotation = 10;
|
||||||
|
int32 fov_id = 11;
|
||||||
|
int32 fov_total = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Wb {
|
||||||
|
uint64 mode = 1;
|
||||||
|
int32 ct = 2;
|
||||||
|
int32 scene = 3;
|
||||||
|
int32 camera_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralIntParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralFloatParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
float value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralBoolParams {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
bool value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchShootingMode {
|
||||||
|
int32 state = 1;
|
||||||
|
int32 source_mode = 2;
|
||||||
|
int32 dst_mode = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchCropRatioState {
|
||||||
|
int32 state = 1;
|
||||||
|
int32 crop_ratio = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResolutionParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 current_res_value = 2;
|
||||||
|
int32 current_fps_value = 3;
|
||||||
|
repeated int32 supported_fps_list = 4;
|
||||||
|
repeated int32 supported_resolution_list = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureRawState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PhotoState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BurstState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RecordState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TimeLapseState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureRawDarkState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroAutoFocusState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NormalAutoFocusState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroAutoFocusFastState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AreaAutoFocusState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DualCameraLinkageState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NormalTrackState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchResolutionFpsState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 cali_frame_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameProgress {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 cali_frame_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceAttitude {
|
||||||
|
double pitch = 1;
|
||||||
|
double yaw = 2;
|
||||||
|
double roll = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SkyTargetFinderState {
|
||||||
|
notify.OperationState state = 1;
|
||||||
|
int32 scene_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingThumbnailUpdateNotify {
|
||||||
|
bytes webp_data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingRectUpdateNotify {
|
||||||
|
double norm_x_tl = 1;
|
||||||
|
double norm_y_tl = 2;
|
||||||
|
double norm_x_br = 3;
|
||||||
|
double norm_y_br = 4;
|
||||||
|
double norm_limit_x_left = 5;
|
||||||
|
double norm_limit_y_top = 6;
|
||||||
|
double norm_limit_x_right = 7;
|
||||||
|
double norm_limit_y_bottom = 8;
|
||||||
|
double rect_hor_fov = 9;
|
||||||
|
double rect_ver_fov = 10;
|
||||||
|
int32 error_code = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingStateNotify {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AutoShutdown {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LensDefog {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AutoCooling {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
108
analysis/protos/Panorama.proto
Normal file
108
analysis/protos/Panorama.proto
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
// source: panorama.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqStartPanoramaByGrid {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaByEulerRange {
|
||||||
|
float yaw_range = 1;
|
||||||
|
float pitch_range = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaStitchUpload {
|
||||||
|
uint64 resource_id = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
int32 app_platform = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string ak = 5;
|
||||||
|
string sk = 6;
|
||||||
|
string token = 7;
|
||||||
|
string bucket = 8;
|
||||||
|
string bucket_prefix = 9;
|
||||||
|
string from = 10;
|
||||||
|
string env_type = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanorama {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaStitchUpload {
|
||||||
|
string user_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetPanoramaCurrentUploadState {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetPanoramaCurrentUploadState {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
uint32 total_files_num = 6;
|
||||||
|
uint32 compressed_files_num = 7;
|
||||||
|
uint64 total_size = 8;
|
||||||
|
uint64 uploaded_size = 9;
|
||||||
|
uint32 step = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetUploadPredict {
|
||||||
|
string panorama_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetUploadPredict {
|
||||||
|
int32 code = 1;
|
||||||
|
string panorama_name = 2;
|
||||||
|
uint32 file_nums = 3;
|
||||||
|
string resolution = 4;
|
||||||
|
uint64 cloud_data_size = 5;
|
||||||
|
uint64 zip_data_size = 6;
|
||||||
|
uint64 app_zip_data_size = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadParam {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint32 total_files_num = 5;
|
||||||
|
uint32 compressed_files_num = 6;
|
||||||
|
uint64 total_size = 7;
|
||||||
|
uint64 uploaded_size = 8;
|
||||||
|
uint32 step = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCompressPanorama {
|
||||||
|
string panorama_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCompressPanorama {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqResetPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaFramingAndStartGrid {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStopPanoramaFraming {
|
||||||
|
int32 code = 1;
|
||||||
|
double centerX_degree_offset = 2;
|
||||||
|
double centerY_degree_offset = 3;
|
||||||
|
uint32 framing_rows = 4;
|
||||||
|
uint32 framing_cols = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUpdatePanoramaFramingRect {
|
||||||
|
double norm_x_tl = 1;
|
||||||
|
double norm_y_tl = 2;
|
||||||
|
double norm_x_br = 3;
|
||||||
|
double norm_y_br = 4;
|
||||||
|
}
|
||||||
|
|
||||||
52
analysis/protos/Param.proto
Normal file
52
analysis/protos/Param.proto
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// source: param.proto
|
||||||
|
package param;
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqSetExposure {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGain {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWb {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralIntParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralFloatParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
float value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralBoolParams {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
bool value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetAutoParam {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 shooting_tech = 2;
|
||||||
|
bool is_auto = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetAutoParam {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 shooting_tech = 3;
|
||||||
|
bool is_auto = 4;
|
||||||
|
bool update_all = 5;
|
||||||
|
int32 code = 6;
|
||||||
|
}
|
||||||
|
|
||||||
21
analysis/protos/RGB.proto
Normal file
21
analysis/protos/RGB.proto
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// source: rgb.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqOpenRgb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCloseRgb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPowerDown {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOpenPowerInd {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqClosePowerInd {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReboot {
|
||||||
|
}
|
||||||
|
|
||||||
157
analysis/protos/Schedule.proto
Normal file
157
analysis/protos/Schedule.proto
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// source: shooting_schedule.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
enum ShootingScheduleState {
|
||||||
|
SHOOTING_SCHEDULE_STATE_INITIALIZED = 0;
|
||||||
|
SHOOTING_SCHEDULE_STATE_PENDING_SHOOT = 1;
|
||||||
|
SHOOTING_SCHEDULE_STATE_SHOOTING = 2;
|
||||||
|
SHOOTING_SCHEDULE_STATE_COMPLETED = 3;
|
||||||
|
SHOOTING_SCHEDULE_STATE_EXPIRED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleSyncState {
|
||||||
|
SHOOTING_SCHEDULE_SYNC_STATE_PENDING_SYNC = 0;
|
||||||
|
SHOOTING_SCHEDULE_SYNC_STATE_SYNCED = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleResult {
|
||||||
|
SHOOTING_SCHEDULE_RESULT_PENDING_START = 0;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_ALL_COMPLETED = 1;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_PARTIALLY_COMPLETED = 2;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_ALL_FAILED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingTaskState {
|
||||||
|
SHOOTING_TASK_STATUS_IDLE = 0;
|
||||||
|
SHOOTING_TASK_STATUS_SHOOTING = 1;
|
||||||
|
SHOOTING_TASK_STATUS_SUCCESS = 2;
|
||||||
|
SHOOTING_TASK_STATUS_FAILED = 3;
|
||||||
|
SHOOTING_TASK_STATUS_INTERRUPTED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleMode {
|
||||||
|
SHOOTING_SCHEDULE_MODE_ASTRO_DEEP_SKY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingTaskMsg {
|
||||||
|
string schedule_id = 1;
|
||||||
|
string params = 2;
|
||||||
|
ShootingTaskState state = 3;
|
||||||
|
int32 code = 4;
|
||||||
|
int64 created_time = 5;
|
||||||
|
int64 updated_time = 6;
|
||||||
|
string schedule_task_id = 7;
|
||||||
|
int32 param_mode = 8;
|
||||||
|
int32 param_version = 9;
|
||||||
|
int32 create_from = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingScheduleMsg {
|
||||||
|
string schedule_id = 1;
|
||||||
|
string schedule_name = 2;
|
||||||
|
int32 device_id = 3;
|
||||||
|
string mac_address = 4;
|
||||||
|
int64 start_time = 5;
|
||||||
|
int64 end_time = 6;
|
||||||
|
ShootingScheduleResult result = 7;
|
||||||
|
int64 created_time = 8;
|
||||||
|
int64 updated_time = 9;
|
||||||
|
ShootingScheduleState state = 10;
|
||||||
|
int32 lock = 11;
|
||||||
|
string password = 12;
|
||||||
|
repeated ShootingTaskMsg shooting_tasks = 13;
|
||||||
|
int32 param_mode = 14;
|
||||||
|
int32 param_version = 15;
|
||||||
|
string params = 16;
|
||||||
|
int64 schedule_time = 17;
|
||||||
|
ShootingScheduleSyncState sync_state = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSyncShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSyncShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
repeated string time_conflict_schedule_ids = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
bool can_replace = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCancelShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCancelShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllShootingSchedule {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllShootingSchedule {
|
||||||
|
repeated ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetShootingScheduleById {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetShootingScheduleById {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetShootingTaskById {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetShootingTaskById {
|
||||||
|
ShootingTaskMsg shooting_task = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReplaceShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReplaceShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
repeated ShootingScheduleMsg replaced_shooting_schedule = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUnlockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResUnlockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqLockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResLockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeleteShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeleteShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
72
analysis/protos/System.proto
Normal file
72
analysis/protos/System.proto
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// source: system.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqSetTime {
|
||||||
|
uint64 timestamp = 1;
|
||||||
|
double timezone_offset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetTimezone {
|
||||||
|
string timezone = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetMtpMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetCpuMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqsetMasterLock {
|
||||||
|
bool lock = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDeviceActivateInfo {
|
||||||
|
int32 issuer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateInfo {
|
||||||
|
int32 activate_state = 1;
|
||||||
|
int32 activate_process_state = 2;
|
||||||
|
string request_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeviceActivateWriteFile {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateWriteFile {
|
||||||
|
int32 code = 1;
|
||||||
|
string request_param = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeviceActivateSuccessfull {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateSuccessfull {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 activate_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDisableDeviceActivate {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDisableDeviceActivate {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 activate_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetLocation {
|
||||||
|
double latitude = 1;
|
||||||
|
double longitude = 2;
|
||||||
|
double altitude = 3;
|
||||||
|
string country_region = 4;
|
||||||
|
string province = 5;
|
||||||
|
string city = 6;
|
||||||
|
string district = 7;
|
||||||
|
bool enable = 8;
|
||||||
|
}
|
||||||
|
|
||||||
204
analysis/protos/TaskCenter.proto
Normal file
204
analysis/protos/TaskCenter.proto
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
// source: task_center.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "notify.proto";
|
||||||
|
import "panorama.proto";
|
||||||
|
import "astro.proto";
|
||||||
|
|
||||||
|
enum TaskId {
|
||||||
|
TASK_ID_IDLE = 0;
|
||||||
|
TASK_ID_PANORAMA_UPLOAD = 1;
|
||||||
|
TASK_ID_ASTRO_MULTI_STACK_THUMBNAIL_GENERATION = 2;
|
||||||
|
TASK_ID_ASTRO_MULTI_STACK = 3;
|
||||||
|
TASK_ID_CAPTURE_CALI_FRAME = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ExclusiveTaskType {
|
||||||
|
EXCLUSIVE_TYPE_NONE = 0;
|
||||||
|
EXCLUSIVE_TYPE_CAMERA = 1;
|
||||||
|
EXCLUSIVE_TYPE_MOTOR = 2;
|
||||||
|
EXCLUSIVE_TYPE_FOCUS_MOTOR = 4;
|
||||||
|
EXCLUSIVE_TYPE_SYSTEM_IO = 8;
|
||||||
|
EXCLUSIVE_TYPE_SYSTEM_WIFI = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskAttr {
|
||||||
|
int32 exclusive_mask = 1;
|
||||||
|
int32 priority = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskState {
|
||||||
|
// oneof extendedState
|
||||||
|
notify.OperationState base_state = 1;
|
||||||
|
notify.AstroState astro_extended_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskParam {
|
||||||
|
// oneof param
|
||||||
|
PanoramaUploadParam panorama_upload = 1;
|
||||||
|
MakeFitsThumbTaskParam make_fits_thumb_task_param = 2;
|
||||||
|
RepostprocessTaskParam repostprocess_task_param = 3;
|
||||||
|
CaptureCaliFrameTaskParam capture_cali_frame_task_param = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResNotifyTaskState {
|
||||||
|
TaskId task_id = 1;
|
||||||
|
TaskAttr task_attr = 2;
|
||||||
|
TaskState state = 3;
|
||||||
|
TaskParam param = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTask {
|
||||||
|
// oneof param
|
||||||
|
TaskId task_id = 1;
|
||||||
|
ReqStartMakeFitsThumb req_make_fits_thumb_param = 2;
|
||||||
|
ReqStartRepostprocess req_repostprocess_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTask {
|
||||||
|
TaskId task_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResTaskCenter {
|
||||||
|
int32 code = 1;
|
||||||
|
TaskId task_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientParams {
|
||||||
|
int32 encode_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqEnterCamera {
|
||||||
|
ClientParams client_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResEnterCamera {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_mode_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchShootingMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSwitchShootingMode {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_mode_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchShootingTech {
|
||||||
|
int32 tech = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSwitchShootingTech {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_tech_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDeviceStateInfo {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveCameraState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.CaptureRawState capture_raw_state = 1;
|
||||||
|
notify.PhotoState photo_state = 2;
|
||||||
|
notify.BurstState burst_state = 3;
|
||||||
|
notify.RecordState record_state = 4;
|
||||||
|
notify.TimeLapseState timelapse_state = 5;
|
||||||
|
notify.CaptureCaliFrameState capture_cali_frame_state = 6;
|
||||||
|
notify.PanoramaState panorama_state = 7;
|
||||||
|
notify.SentryState sentry_state = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TeleCameraStateInfo {
|
||||||
|
// oneof _cmos_temperature
|
||||||
|
ExclusiveCameraState exclusive_state = 1;
|
||||||
|
notify.StreamType stream_type = 2;
|
||||||
|
double h_fov = 3;
|
||||||
|
double v_fov = 4;
|
||||||
|
uint32 resolution_width = 5;
|
||||||
|
uint32 resolution_height = 6;
|
||||||
|
notify.CmosTemperature cmos_temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WideCameraStateInfo {
|
||||||
|
// oneof _cmos_temperature
|
||||||
|
ExclusiveCameraState exclusive_state = 1;
|
||||||
|
notify.StreamType stream_type = 2;
|
||||||
|
double h_fov = 3;
|
||||||
|
double v_fov = 4;
|
||||||
|
uint32 resolution_width = 5;
|
||||||
|
uint32 resolution_height = 6;
|
||||||
|
notify.CmosTemperature cmos_temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveFocusMotorState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.AstroAutoFocusState astro_auto_focus_state = 1;
|
||||||
|
notify.NormalAutoFocusState normal_auto_focus_state = 2;
|
||||||
|
notify.AstroAutoFocusFastState astro_auto_focus_fast_state = 3;
|
||||||
|
notify.AreaAutoFocusState area_auto_focus_state = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FocusMotorStateInfo {
|
||||||
|
// oneof _focus_position
|
||||||
|
ExclusiveFocusMotorState exclusive_state = 1;
|
||||||
|
notify.FocusPosition focus_position = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveMotionMotorState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.AstroCalibrationState astro_calibration_state = 1;
|
||||||
|
notify.AstroGotoState astro_goto_state = 2;
|
||||||
|
notify.AstroTrackingState astro_tracking_state = 3;
|
||||||
|
notify.NormalTrackState normal_track_state = 4;
|
||||||
|
notify.OneClickGotoState one_click_goto_state = 5;
|
||||||
|
notify.EqSolvingState eq_state = 6;
|
||||||
|
notify.SentryState sentry_state = 7;
|
||||||
|
notify.SkyTargetFinderState sky_target_finder_state = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MotionMotorStateInfo {
|
||||||
|
ExclusiveMotionMotorState exclusive_state = 1;
|
||||||
|
notify.SentryAutoHand sentry_auto_hand = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceStateInfo {
|
||||||
|
notify.RgbState rgb_state = 1;
|
||||||
|
notify.PowerIndState power_ind_state = 2;
|
||||||
|
notify.ChargingState charging_state = 3;
|
||||||
|
notify.StorageInfo storage_info = 4;
|
||||||
|
notify.MTPState mtp_state = 5;
|
||||||
|
notify.CPUMode cpu_mode = 6;
|
||||||
|
notify.Temperature temperature = 7;
|
||||||
|
notify.BodyStatus body_status = 8;
|
||||||
|
notify.BatteryInfo battery_info = 9;
|
||||||
|
notify.CalibrationResult calibration_result = 10;
|
||||||
|
notify.PictureMatching picture_matching = 11;
|
||||||
|
notify.AutoShutdown auto_shutdown = 12;
|
||||||
|
notify.LensDefog lens_defog = 13;
|
||||||
|
notify.AutoCooling auto_cooling = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConnectionStateInfo {
|
||||||
|
notify.HostSlaveMode host_slave_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingModeAndTech {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
int32 parent_shooting_mode = 2;
|
||||||
|
repeated int32 shooting_techs = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDeviceStateInfo {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
TeleCameraStateInfo tele_camera_state_info = 2;
|
||||||
|
WideCameraStateInfo wide_camera_state_info = 3;
|
||||||
|
FocusMotorStateInfo focus_motor_state_info = 4;
|
||||||
|
MotionMotorStateInfo motion_motor_state_info = 5;
|
||||||
|
DeviceStateInfo device_state_info = 6;
|
||||||
|
int32 code = 7;
|
||||||
|
ConnectionStateInfo connection_state_info = 8;
|
||||||
|
repeated ShootingModeAndTech shooting_mode_and_techs = 9;
|
||||||
|
}
|
||||||
|
|
||||||
41
analysis/protos/Track.proto
Normal file
41
analysis/protos/Track.proto
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// source: track.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message ReqStartTrack {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 w = 3;
|
||||||
|
int32 h = 4;
|
||||||
|
int32 cam_id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPauseTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqContinueTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartSentryMode {
|
||||||
|
int32 type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopSentryMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMOTTrackOne {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUFOAutoHandMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTrackClick {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 cam_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
140
analysis/protos/VoiceAssistant.proto
Normal file
140
analysis/protos/VoiceAssistant.proto
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// source: voice_assistant.proto
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
import "notify.proto";
|
||||||
|
import "task_center.proto";
|
||||||
|
|
||||||
|
enum VoiceCommandType {
|
||||||
|
VOICE_CMD_UNKNOWN = 0;
|
||||||
|
VOICE_CMD_GET_STATUS = 1;
|
||||||
|
VOICE_CMD_TAKE_PHOTO = 2;
|
||||||
|
VOICE_CMD_START_RECORD = 3;
|
||||||
|
VOICE_CMD_STOP_RECORD = 4;
|
||||||
|
VOICE_CMD_START_TIMELAPSE = 5;
|
||||||
|
VOICE_CMD_STOP_TIMELAPSE = 6;
|
||||||
|
VOICE_CMD_START_BURST = 7;
|
||||||
|
VOICE_CMD_STOP_BURST = 8;
|
||||||
|
VOICE_CMD_START_ASTRO = 9;
|
||||||
|
VOICE_CMD_STOP_ASTRO = 10;
|
||||||
|
VOICE_CMD_START_SENTRY = 11;
|
||||||
|
VOICE_CMD_STOP_SENTRY = 12;
|
||||||
|
VOICE_CMD_MOVE = 13;
|
||||||
|
VOICE_CMD_GOTO_TARGET = 14;
|
||||||
|
VOICE_CMD_CALIBRATION = 15;
|
||||||
|
VOICE_CMD_AUTO_FOCUS = 16;
|
||||||
|
VOICE_CMD_STOP_FOCUS = 17;
|
||||||
|
VOICE_CMD_STOP_ALL = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqVoiceCommand {
|
||||||
|
// oneof params
|
||||||
|
VoiceCommandType command_type = 1;
|
||||||
|
int32 shooting_mode = 2;
|
||||||
|
VoicePhotoParams photo_params = 10;
|
||||||
|
VoiceRecordParams record_params = 11;
|
||||||
|
VoiceTimelapseParams timelapse_params = 12;
|
||||||
|
VoiceBurstParams burst_params = 13;
|
||||||
|
VoiceAstroParams astro_params = 14;
|
||||||
|
VoiceSentryParams sentry_params = 15;
|
||||||
|
VoiceMoveParams move_params = 16;
|
||||||
|
VoiceGotoParams goto_params = 17;
|
||||||
|
VoiceCalibrationParams calibration_params = 18;
|
||||||
|
VoiceFocusParams focus_params = 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoicePhotoParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceRecordParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 duration_seconds = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceTimelapseParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 interval_seconds = 2;
|
||||||
|
int32 duration_seconds = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceBurstParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 count = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceAstroParams {
|
||||||
|
string target_name = 1;
|
||||||
|
double ra = 2;
|
||||||
|
double dec = 3;
|
||||||
|
int32 index = 4;
|
||||||
|
double lon = 5;
|
||||||
|
double lat = 6;
|
||||||
|
bool auto_goto = 7;
|
||||||
|
bool force_start = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceSentryParams {
|
||||||
|
int32 type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceMoveParams {
|
||||||
|
double azimuth_angle = 1;
|
||||||
|
double altitude_angle = 2;
|
||||||
|
int32 speed = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceGotoParams {
|
||||||
|
string target_name = 1;
|
||||||
|
double ra = 2;
|
||||||
|
double dec = 3;
|
||||||
|
int32 index = 4;
|
||||||
|
double lon = 5;
|
||||||
|
double lat = 6;
|
||||||
|
int32 shooting_mode = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceCalibrationParams {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceFocusParams {
|
||||||
|
bool is_infinity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResVoiceCommand {
|
||||||
|
// oneof result
|
||||||
|
int32 code = 1;
|
||||||
|
string message = 2;
|
||||||
|
VoiceCommandType command_type = 3;
|
||||||
|
VoiceStatusResult status_result = 10;
|
||||||
|
VoiceOperationResult operation_result = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroShootingProgress {
|
||||||
|
string target_name = 1;
|
||||||
|
int32 captured_count = 2;
|
||||||
|
int32 total_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 progress_percentage = 5;
|
||||||
|
int64 elapsed_time = 6;
|
||||||
|
int64 remaining_time = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceStatusResult {
|
||||||
|
ResGetDeviceStateInfo device_state_info = 1;
|
||||||
|
AstroShootingProgress astro_progress = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceOperationResult {
|
||||||
|
bool success = 1;
|
||||||
|
string detail_message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResNotifyVoiceAssistant {
|
||||||
|
VoiceCommandType command_type = 1;
|
||||||
|
notify.OperationState state = 2;
|
||||||
|
string message = 4;
|
||||||
|
}
|
||||||
|
|
||||||
25
dwarfctl/Makefile
Normal file
25
dwarfctl/Makefile
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
.PHONY: proto build clean test install
|
||||||
|
|
||||||
|
PROTOC ?= protoc
|
||||||
|
GO ?= go
|
||||||
|
BINARY = dwarfctl
|
||||||
|
|
||||||
|
build: ## Build the dwarfctl binary
|
||||||
|
$(GO) build -o $(BINARY) ./cmd/dwarfctl/
|
||||||
|
|
||||||
|
proto: ## Regenerate Go protobuf bindings from .proto files
|
||||||
|
$(PROTOC) --go_out=. --go_opt=paths=source_relative --proto_path=. dwarf.proto
|
||||||
|
|
||||||
|
install: build ## Install dwarfctl to $$GOBIN
|
||||||
|
$(GO) install ./cmd/dwarfctl/
|
||||||
|
|
||||||
|
test: ## Run tests
|
||||||
|
$(GO) test ./...
|
||||||
|
|
||||||
|
clean: ## Remove build artifacts
|
||||||
|
rm -f $(BINARY)
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-12s\033[0m %s\n",$$1,$$2}'
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := build
|
||||||
122
dwarfctl/README.md
Normal file
122
dwarfctl/README.md
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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/...)
|
||||||
|
└── 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
|
||||||
|
|
||||||
|
- [ ] BLE discovery + handshake (DwarfPing/DwarfEcho)
|
||||||
|
- [ ] RTSP preview viewer
|
||||||
|
- [ ] Interactive REPL mode
|
||||||
|
- [ ] Schedule plan management
|
||||||
|
- [ ] OTA firmware update
|
||||||
|
- [ ] Full Notify event parsing (typed)
|
||||||
161
dwarfctl/TEST_RESULTS.md
Normal file
161
dwarfctl/TEST_RESULTS.md
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
# Plan de test — dwarfctl sur télescope réel
|
||||||
|
|
||||||
|
## Conditions de test
|
||||||
|
- **Télescope** : DWARF II, firmware 2.1.6, mode AP (hotspot WiFi)
|
||||||
|
- **IP** : `192.168.88.1`
|
||||||
|
- **Réseau** : machine connectée au hotspot du télescope
|
||||||
|
- **Environnement** : intérieur, journée (pas d'accès au ciel/étoiles)
|
||||||
|
|
||||||
|
## Découvertes protocolaires importantes
|
||||||
|
|
||||||
|
### Modèle de réponse du télescope
|
||||||
|
|
||||||
|
Le télescope utilise **type=3 (REPLY)** pour les réponses directes, PAS type=1 (RESPONSE). De plus, certaines commandes ne reçoivent AUCUNE réponse directe — seulement des notifications (type=2).
|
||||||
|
|
||||||
|
| Pattern | Commandes | Comportement |
|
||||||
|
|---------|-----------|--------------|
|
||||||
|
| **Reply type=3 (même cmd)** | `photo` (10002), `focus auto` (15000), `focus step` (15001), `state` (16405) | Réponse directe avec le même cmd → request-response |
|
||||||
|
| **Notification uniquement** | `rgb-on/off` (13500/13501), `camera open/close` (10000/10001), `camera params` (10036) | Pas de reply → fire-and-forget + vérifier via `state` |
|
||||||
|
| **Fire-and-forget natif** | `motor slew` (14006), `motor stop` (14002) | Pas d'ack attendu |
|
||||||
|
|
||||||
|
### Implémentation dans dwarfctl
|
||||||
|
- `send()` : attend un type=3 reply (10s timeout) — pour photo, focus, state
|
||||||
|
- `sendNotify()` : fire-and-forget — pour RGB, camera open/close, motor slew
|
||||||
|
- Flag `--debug` / `-d` : loggue tout le trafic WebSocket (cmd, module, type, taille data)
|
||||||
|
|
||||||
|
## Tests par groupe
|
||||||
|
|
||||||
|
### ✅ 1. Connexion (PASS)
|
||||||
|
|
||||||
|
| Test | Commande | Résultat |
|
||||||
|
|------|----------|---------|
|
||||||
|
| Ping | `ping 192.168.88.1` | ✅ 36ms |
|
||||||
|
| Port 9900 (WebSocket) | `/dev/tcp/192.168.88.1/9900` | ✅ OPEN |
|
||||||
|
| Port 80 (RTSP) | `/dev/tcp/192.168.88.1/80` | ✅ OPEN |
|
||||||
|
| WebSocket handshake | `dwarfctl --ip 192.168.88.1 state` | ✅ connexion établie |
|
||||||
|
|
||||||
|
### ✅ 2. État du device (PASS)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dwarfctl --ip 192.168.88.1 state
|
||||||
|
```
|
||||||
|
Réponse complète : shooting_mode, cameras (résolution, FoV), focus position (594), batterie (100%), stockage (38/52 GB), température CMOS, modes disponibles.
|
||||||
|
|
||||||
|
### ✅ 3. Caméra Tele (PASS)
|
||||||
|
|
||||||
|
| Test | Commande | Debug | Statut |
|
||||||
|
|------|----------|-------|--------|
|
||||||
|
| Open camera | `camera open --cam tele` | fire-and-forget | ✅ |
|
||||||
|
| Photo | `camera photo --cam tele` | reply cmd=10002 type=3 data=11B | ✅ photo capturée |
|
||||||
|
| Focus step out | `focus step 1` | reply cmd=15001 type=3 data=0B | ✅ |
|
||||||
|
|
||||||
|
### ✅ 4. Moteurs / Slew (PASS)
|
||||||
|
|
||||||
|
Tests systématiques effectués — tous les mouvements confirmés visuellement sur le télescope.
|
||||||
|
|
||||||
|
#### 4.1 Directions cardinales (joystick cmd 14006)
|
||||||
|
|
||||||
|
| Direction | Angle | Length | Durée | Résultat |
|
||||||
|
|-----------|-------|--------|-------|----------|
|
||||||
|
| HAUT | 0° | 0.3 | 2s | ✅ mouvement observé |
|
||||||
|
| DROITE | 90° | 0.3 | 2s | ✅ mouvement observé |
|
||||||
|
| BAS | 180° | 0.3 | 2s | ✅ mouvement observé |
|
||||||
|
| GAUCHE | 270° | 0.3 | 2s | ✅ mouvement observé |
|
||||||
|
|
||||||
|
**Système de coordonnées joystick** : angle en degrés (polaire), 0°=haut, 90°=droite, 180°=bas, 270°=gauche. Length = vitesse normalisée (0.0 à 1.0).
|
||||||
|
|
||||||
|
#### 4.2 Vitesses variables
|
||||||
|
|
||||||
|
| Vitesse | Length | Résultat |
|
||||||
|
|---------|--------|----------|
|
||||||
|
| Lente | 0.1 | ✅ mouvement visible et lent |
|
||||||
|
| Moyenne | 0.5 | ✅ mouvement net |
|
||||||
|
| Rapide | 0.9 | ✅ mouvement rapide |
|
||||||
|
|
||||||
|
#### 4.3 Diagonales
|
||||||
|
|
||||||
|
| Direction | Angle | Résultat |
|
||||||
|
|-----------|-------|----------|
|
||||||
|
| HAUT-DROITE | 45° | ✅ mouvement diagonal |
|
||||||
|
| BAS-GAUCHE | 225° | ✅ mouvement diagonal |
|
||||||
|
|
||||||
|
Le joystick est bien polaire — 360° de liberté, pas seulement 4 directions.
|
||||||
|
|
||||||
|
#### 4.4 Arrêt d'urgence
|
||||||
|
|
||||||
|
| Test | Commande | Résultat |
|
||||||
|
|------|----------|----------|
|
||||||
|
| Stop pendant slew | `motor stop 0` (cmd 14002) | ✅ arrêt immédiat |
|
||||||
|
| Stop motor 1 | `motor stop 1` | ✅ |
|
||||||
|
|
||||||
|
Le `motor stop` interrompt un slew en cours instantanément.
|
||||||
|
|
||||||
|
#### 4.5 Motor run/goto (cmd 14000)
|
||||||
|
|
||||||
|
| Test | Commande | Résultat |
|
||||||
|
|------|----------|----------|
|
||||||
|
| Run to position | `motor goto 0 10 5` | ✅ fire-and-forget envoyé |
|
||||||
|
|
||||||
|
`ReqMotorRunTo` : moteur ID, position cible, vitesse. Fire-and-forget (pas de ack type=3).
|
||||||
|
|
||||||
|
#### 4.6 Observations sur la lecture de position
|
||||||
|
|
||||||
|
- **`focus_position`** (moteur de mise au point) : visible dans `state` → `focus_position:{pos:593}`, reste stable pendant les mouvements de pointage.
|
||||||
|
- **Position moteurs de pointage (RA/DEC)** : `motion_motor_state_info:{exclusive_state:{}}` reste vide — la position des moteurs alt-az n'est PAS exposée dans `GetDeviceState`.
|
||||||
|
- Les messages proto `ReqMotorGetPosition` et `ReqMotorReset` existent dans le proto mais ne sont **pas utilisés par l'app Android** (aucune classe de requête correspondante). La lecture de position se fait probablement via les notifications d'attitude (cmd 15295 `CMD_NOTIFY_DEVICE_ATTITUDE`).
|
||||||
|
|
||||||
|
### ✅ 5. RGB / Power (PASS après fix fire-and-forget)
|
||||||
|
|
||||||
|
| Test | Commande | Avant fix | Après fix |
|
||||||
|
|------|----------|-----------|-----------|
|
||||||
|
| RGB off | `power rgb-off` | ❌ timeout (cmd 13501) | ✅ fire-and-forget |
|
||||||
|
| RGB on | `power rgb-on` | ❌ timeout (cmd 13500) | ✅ fire-and-forget |
|
||||||
|
|
||||||
|
Vérification : `rgb_state:{}` (éteint) vs `rgb_state:{state:1}` (allumé) dans `state`.
|
||||||
|
|
||||||
|
### ✅ 6. Focus (PASS)
|
||||||
|
|
||||||
|
| Test | Commande | Debug | Statut |
|
||||||
|
|------|----------|-------|--------|
|
||||||
|
| Autofocus | `focus auto` | notifications + reply cmd=15000 type=3 | ✅ |
|
||||||
|
| Step out | `focus step 1` | reply cmd=15001 type=3 | ✅ |
|
||||||
|
|
||||||
|
### ✅ 7. System (NON TESTÉ — nécessite validation)
|
||||||
|
|
||||||
|
| Test | Commande | Notes |
|
||||||
|
|------|----------|-------|
|
||||||
|
| Sync time | `system sync-time` | À tester |
|
||||||
|
| Set location | `system set-location 48.86 2.35 35` | À tester |
|
||||||
|
|
||||||
|
### ❌ 8. Astrophotographie (NON TESTABLE — jour/intérieur)
|
||||||
|
|
||||||
|
Ces commandes nécessitent un ciel étoilé nocturne :
|
||||||
|
|
||||||
|
| Test | Raison |
|
||||||
|
|------|--------|
|
||||||
|
| `astro calibrate start` | Nécessite des étoiles visibles |
|
||||||
|
| `astro goto-dso` | Nécessite le ciel |
|
||||||
|
| `astro stack start` | Nécessite des étoiles |
|
||||||
|
| `astro eq-solve start` | Nécessite des étoiles |
|
||||||
|
| `track start` | Nécessite une cible mobile |
|
||||||
|
|
||||||
|
### ❌ 9. Camera params (KNOWN ISSUE)
|
||||||
|
|
||||||
|
`camera params --cam tele` (cmd 10036) : le télescope ne renvoie pas de reply.
|
||||||
|
Les paramètres sont toutefois visibles dans la réponse `state` (résolution, FoV).
|
||||||
|
Les paramètres ajustables (exposure, gain) nécessiteraient une commande GET qui ne répond pas en type=3.
|
||||||
|
|
||||||
|
## Bugs corrigés pendant les tests
|
||||||
|
|
||||||
|
1. **`readLoop` ne dispatchait pas type=3 correctement** → corrigé : tous les types sont dispatchés vers `dispatchResponse` + `dispatchNotification`
|
||||||
|
2. **Commandes RGB/camera open attendaient un reply inexistant** → converties en fire-and-forget (`sendNotify`)
|
||||||
|
3. **Motor stop/goto attendaient un reply** → convertis en fire-and-forget
|
||||||
|
4. **Pas de logging** → ajout du flag `--debug` / `-d`
|
||||||
|
|
||||||
|
## Tests unitaires
|
||||||
|
|
||||||
|
```
|
||||||
|
ok github.com/antitbone/dwarfctl/internal/transport 0.003s
|
||||||
|
ok github.com/antitbone/dwarfctl/internal/api 0.003s
|
||||||
|
```
|
||||||
|
57 tests, tous PASS.
|
||||||
596
dwarfctl/cmd/dwarfctl/main.go
Normal file
596
dwarfctl/cmd/dwarfctl/main.go
Normal file
@ -0,0 +1,596 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/antitbone/dwarfctl/internal/api"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
flagIP string
|
||||||
|
flagClientID string
|
||||||
|
flagDebug bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
rootCmd := &cobra.Command{
|
||||||
|
Use: "dwarfctl",
|
||||||
|
Short: "DWARF telescope control CLI",
|
||||||
|
Long: "Open-source client for DWARF II / DWARFLAB smart telescopes.\nControls cameras, motors, astrophotography, focus, tracking, and power\nvia the telescope's WebSocket API (port 9900).",
|
||||||
|
}
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&flagIP, "ip", "i", "", "telescope IP address (required)")
|
||||||
|
rootCmd.PersistentFlags().StringVar(&flagClientID, "client-id", "dwarfctl", "WebSocket client_id")
|
||||||
|
rootCmd.PersistentFlags().BoolVarP(&flagDebug, "debug", "d", false, "verbose WebSocket traffic log")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(
|
||||||
|
cmdState(),
|
||||||
|
cmdCamera(),
|
||||||
|
cmdMotor(),
|
||||||
|
cmdAstro(),
|
||||||
|
cmdFocus(),
|
||||||
|
cmdTrack(),
|
||||||
|
cmdSystem(),
|
||||||
|
cmdPower(),
|
||||||
|
cmdMonitor(),
|
||||||
|
)
|
||||||
|
|
||||||
|
rootCmd.MarkPersistentFlagRequired("ip")
|
||||||
|
if err := rootCmd.Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dial connects to the telescope and returns a ready Telescope + cleanup.
|
||||||
|
func dial() (*api.Telescope, func()) {
|
||||||
|
scope := api.New(flagClientID)
|
||||||
|
scope.SetDebug(flagDebug)
|
||||||
|
if err := scope.Connect(flagIP); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: connect to %s: %v\n", flagIP, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return scope, func() { scope.Close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
func mustCam(s string) api.Camera {
|
||||||
|
switch strings.ToLower(s) {
|
||||||
|
case "tele", "t", "0":
|
||||||
|
return api.CameraTele
|
||||||
|
case "wide", "w", "1":
|
||||||
|
return api.CameraWide
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: invalid camera '%s' (use: tele|wide)\n", s)
|
||||||
|
os.Exit(1)
|
||||||
|
return api.CameraTele
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- state ---
|
||||||
|
|
||||||
|
func cmdState() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "state",
|
||||||
|
Short: "Get device state info",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
state, err := scope.GetDeviceState()
|
||||||
|
if err != nil {
|
||||||
|
die("get state: %v", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Device State:\n")
|
||||||
|
printProto(state)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- camera ---
|
||||||
|
|
||||||
|
func cmdCamera() *cobra.Command {
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "camera",
|
||||||
|
Short: "Camera control (open/close/photo/params)",
|
||||||
|
}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "open [--cam tele|wide]",
|
||||||
|
Short: "Open camera",
|
||||||
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.OpenCamera(cam))
|
||||||
|
fmt.Println("camera opened")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "close [--cam tele|wide]",
|
||||||
|
Short: "Close camera",
|
||||||
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.CloseCamera(cam))
|
||||||
|
fmt.Println("camera closed")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "photo [--cam tele|wide] [--raw]",
|
||||||
|
Short: "Take a photo",
|
||||||
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
raw, _ := cmd.Flags().GetBool("raw")
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
if raw {
|
||||||
|
must(scope.TakeRawPhoto(cam))
|
||||||
|
} else {
|
||||||
|
must(scope.TakePhoto(cam))
|
||||||
|
}
|
||||||
|
fmt.Println("photo captured")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "burst [--cam tele|wide] [start|stop]",
|
||||||
|
Short: "Start or stop burst capture",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartBurst(cam))
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopBurst(cam))
|
||||||
|
default:
|
||||||
|
die("usage: camera burst [start|stop]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "record [--cam tele|wide] [start|stop]",
|
||||||
|
Short: "Start or stop video recording",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartRecord(cam))
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopRecord(cam))
|
||||||
|
default:
|
||||||
|
die("usage: camera record [start|stop]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "exp [--cam tele|wide] <index>",
|
||||||
|
Short: "Set exposure index (0=1/10000s, see params_range.json)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
idx := parseInt32(args[0])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.SetExposure(cam, idx))
|
||||||
|
fmt.Printf("exposure set to %d\n", idx)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "gain [--cam tele|wide] <index>",
|
||||||
|
Short: "Set gain index (0-200+)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
idx := parseInt32(args[0])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.SetGain(cam, idx))
|
||||||
|
fmt.Printf("gain set to %d\n", idx)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "params [--cam tele|wide]",
|
||||||
|
Short: "Get all camera parameters",
|
||||||
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
|
cam := mustCam(flagCam(cmd))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
params, err := scope.GetAllParams(cam)
|
||||||
|
must(err)
|
||||||
|
printProto(params)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// Add --cam to all subcommands
|
||||||
|
for _, sub := range c.Commands() {
|
||||||
|
sub.Flags().String("cam", "tele", "camera: tele|wide")
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- motor ---
|
||||||
|
|
||||||
|
func cmdMotor() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "motor", Short: "Motor control (slew/joystick)"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "slew <angle-deg> <length>",
|
||||||
|
Short: "Slew via joystick vector (angle 0-360, length 0-1)",
|
||||||
|
Args: cobra.ExactArgs(2),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
angle := parseFloat(args[0])
|
||||||
|
length := parseFloat(args[1])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.SlewJoystick(angle, length))
|
||||||
|
fmt.Printf("slew: angle=%.1f length=%.2f\n", angle, length)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "stop [motor-id]",
|
||||||
|
Short: "Stop motors (id 0=RA, 1=DEC, default=both)",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
id := int32(0)
|
||||||
|
if len(args) > 0 {
|
||||||
|
id = parseInt32(args[0])
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.MotorStop(id))
|
||||||
|
fmt.Println("motor stopped")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "goto <motor-id> <position> <speed>",
|
||||||
|
Short: "Move motor to position at speed",
|
||||||
|
Args: cobra.ExactArgs(3),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
id := parseInt32(args[0])
|
||||||
|
pos := parseFloat(args[1])
|
||||||
|
speed := parseFloat(args[2])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.MotorRunTo(id, pos, speed))
|
||||||
|
fmt.Printf("motor %d -> pos %.2f @ speed %.2f\n", id, pos, speed)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "reset <motor-id> [direction]",
|
||||||
|
Short: "Reset motor to home (0=back, 1=forward)",
|
||||||
|
Args: cobra.RangeArgs(1, 2),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
id := parseInt32(args[0])
|
||||||
|
dir := false
|
||||||
|
if len(args) > 1 && args[1] == "1" {
|
||||||
|
dir = true
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.MotorReset(id, dir))
|
||||||
|
fmt.Printf("motor %d reset (dir=%v)\n", id, dir)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "position <motor-id>",
|
||||||
|
Short: "Get motor position (experimental cmd 14001)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
id := parseInt32(args[0])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
pos, err := scope.MotorGetPosition(id)
|
||||||
|
must(err)
|
||||||
|
fmt.Printf("motor %d: id=%d code=%d position=%.2f\n", id, pos.GetId(), pos.GetCode(), pos.GetPosition())
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- astro ---
|
||||||
|
|
||||||
|
func cmdAstro() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "astro", Short: "Astrophotography (calibrate/goto/stack)"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "calibrate [start|stop]",
|
||||||
|
Short: "Start or stop star calibration",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartCalibration())
|
||||||
|
fmt.Println("calibration started")
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopCalibration())
|
||||||
|
fmt.Println("calibration stopped")
|
||||||
|
default:
|
||||||
|
die("usage: astro calibrate [start|stop]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "goto-dso <ra-deg> <dec-deg> [name]",
|
||||||
|
Short: "GoTo a deep-sky object by RA/Dec (degrees)",
|
||||||
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
ra := parseFloat(args[0])
|
||||||
|
dec := parseFloat(args[1])
|
||||||
|
name := ""
|
||||||
|
if len(args) > 2 {
|
||||||
|
name = strings.Join(args[2:], " ")
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.GotoDSO(ra, dec, name))
|
||||||
|
fmt.Printf("GoTo DSO: RA=%.4f° Dec=%.4f° (%s)\n", ra, dec, name)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "goto-solar <index>",
|
||||||
|
Short: "GoTo solar system object (1=Mercury..7=Neptune, see planet table)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
idx := parseInt32(args[0])
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.GotoSolar(idx))
|
||||||
|
fmt.Printf("GoTo solar system object %d\n", idx)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "goto-stop",
|
||||||
|
Short: "Abort GoTo",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.StopGoto())
|
||||||
|
fmt.Println("GoTo stopped")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "stack [start|stop]",
|
||||||
|
Short: "Start or stop live stacking",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartLiveStacking())
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopLiveStacking())
|
||||||
|
default:
|
||||||
|
die("usage: astro stack [start|stop]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "eq-solve [start|stop]",
|
||||||
|
Short: "Start or stop EQ solving (polar alignment)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartEqSolving())
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopEqSolving())
|
||||||
|
default:
|
||||||
|
die("usage: astro eq-solve [start|stop]")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- focus ---
|
||||||
|
|
||||||
|
func cmdFocus() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "focus", Short: "Focus control"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "auto",
|
||||||
|
Short: "Trigger autofocus",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.AutoFocus())
|
||||||
|
fmt.Println("autofocus triggered")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "step <0|1>",
|
||||||
|
Short: "Manual single-step focus (0=in, 1=out)",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
dir := uint32(parseInt32(args[0]))
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.ManualSingleStepFocus(dir))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "astro-af [start|stop]",
|
||||||
|
Short: "Start or stop astro autofocus",
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
switch args[0] {
|
||||||
|
case "start":
|
||||||
|
must(scope.StartAstroAutoFocus())
|
||||||
|
case "stop":
|
||||||
|
must(scope.StopAstroAutoFocus())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- track ---
|
||||||
|
|
||||||
|
func cmdTrack() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "track", Short: "Tracking control"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "start <x> <y> <w> <h> [cam-id]",
|
||||||
|
Short: "Start tracking an object in a region",
|
||||||
|
Args: cobra.MinimumNArgs(4),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
x, y, w, h := parseInt32(args[0]), parseInt32(args[1]), parseInt32(args[2]), parseInt32(args[3])
|
||||||
|
cam := int32(0)
|
||||||
|
if len(args) > 4 {
|
||||||
|
cam = parseInt32(args[4])
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.StartTracking(x, y, w, h, cam))
|
||||||
|
fmt.Printf("tracking started: bbox(%d,%d,%d,%d) cam=%d\n", x, y, w, h, cam)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "stop",
|
||||||
|
Short: "Stop tracking",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.StopTracking())
|
||||||
|
fmt.Println("tracking stopped")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- system ---
|
||||||
|
|
||||||
|
func cmdSystem() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "system", Short: "System commands (time/location)"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "sync-time",
|
||||||
|
Short: "Sync telescope clock to this machine",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
_, tz := time.Now().Zone()
|
||||||
|
must(scope.SetTime(uint64(time.Now().Unix()), float64(tz)))
|
||||||
|
fmt.Println("time synced")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&cobra.Command{
|
||||||
|
Use: "set-location <lat> <lon> [alt]",
|
||||||
|
Short: "Set observing location",
|
||||||
|
Args: cobra.MinimumNArgs(2),
|
||||||
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
lat := parseFloat(args[0])
|
||||||
|
lon := parseFloat(args[1])
|
||||||
|
alt := 0.0
|
||||||
|
if len(args) > 2 {
|
||||||
|
alt = parseFloat(args[2])
|
||||||
|
}
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
must(scope.SetLocation(lat, lon, alt))
|
||||||
|
fmt.Printf("location set: %.4f, %.4f, %.0fm\n", lat, lon, alt)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- power ---
|
||||||
|
|
||||||
|
func cmdPower() *cobra.Command {
|
||||||
|
c := &cobra.Command{Use: "power", Short: "Power & RGB control"}
|
||||||
|
c.AddCommand(
|
||||||
|
&cobra.Command{Use: "rgb-on", Short: "Turn on RGB ring light", Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial(); defer cleanup(); must(scope.RGBOn()); fmt.Println("RGB on")
|
||||||
|
}},
|
||||||
|
&cobra.Command{Use: "rgb-off", Short: "Turn off RGB ring light", Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial(); defer cleanup(); must(scope.RGBOff()); fmt.Println("RGB off")
|
||||||
|
}},
|
||||||
|
&cobra.Command{Use: "off", Short: "Power down telescope", Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial(); defer cleanup(); must(scope.PowerDown()); fmt.Println("powering down")
|
||||||
|
}},
|
||||||
|
&cobra.Command{Use: "reboot", Short: "Reboot telescope", Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial(); defer cleanup(); must(scope.Reboot()); fmt.Println("rebooting")
|
||||||
|
}},
|
||||||
|
)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- monitor ---
|
||||||
|
|
||||||
|
func cmdMonitor() *cobra.Command {
|
||||||
|
return &cobra.Command{
|
||||||
|
Use: "monitor",
|
||||||
|
Short: "Listen for telescope notifications (Ctrl-C to stop)",
|
||||||
|
Run: func(_ *cobra.Command, _ []string) {
|
||||||
|
scope, cleanup := dial()
|
||||||
|
defer cleanup()
|
||||||
|
ch := scope.Notifications()
|
||||||
|
fmt.Println("Monitoring notifications (Ctrl-C to stop)...")
|
||||||
|
for pkt := range ch {
|
||||||
|
fmt.Printf("[NOTIFY] cmd=%d module=%d type=%d data_len=%d\n",
|
||||||
|
pkt.GetCmd(), pkt.GetModuleId(), pkt.GetType(), len(pkt.GetData()))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- helpers ---
|
||||||
|
|
||||||
|
func flagCam(cmd *cobra.Command) string {
|
||||||
|
s, _ := cmd.Flags().GetString("cam")
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInt32(s string) int32 {
|
||||||
|
v, err := strconv.ParseInt(s, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
die("invalid number '%s': %v", s, err)
|
||||||
|
}
|
||||||
|
return int32(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFloat(s string) float64 {
|
||||||
|
v, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
die("invalid float '%s': %v", s, err)
|
||||||
|
}
|
||||||
|
if math.IsNaN(v) || math.IsInf(v, 0) {
|
||||||
|
die("invalid float '%s'", s)
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func die(format string, args ...any) {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error: "+format+"\n", args...)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func must(err error) {
|
||||||
|
if err != nil {
|
||||||
|
die("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printProto(v any) {
|
||||||
|
fmt.Printf(" %+v\n", v)
|
||||||
|
}
|
||||||
14
dwarfctl/go.mod
Normal file
14
dwarfctl/go.mod
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
module github.com/antitbone/dwarfctl
|
||||||
|
|
||||||
|
go 1.25.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gorilla/websocket v1.5.3
|
||||||
|
github.com/spf13/cobra v1.9.1
|
||||||
|
google.golang.org/protobuf v1.36.11
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
|
)
|
||||||
16
dwarfctl/go.sum
Normal file
16
dwarfctl/go.sum
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||||
|
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||||
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
395
dwarfctl/internal/api/client.go
Normal file
395
dwarfctl/internal/api/client.go
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/antitbone/dwarfctl/internal/transport"
|
||||||
|
pb "github.com/antitbone/dwarfctl/proto"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Telescope wraps the WebSocket transport with typed telescope commands.
|
||||||
|
type Telescope struct {
|
||||||
|
t *transport.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a Telescope API client.
|
||||||
|
func New(clientID string) *Telescope {
|
||||||
|
return &Telescope{t: transport.NewClient(clientID, 1)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDebug enables verbose WebSocket traffic logging.
|
||||||
|
func (t *Telescope) SetDebug(on bool) {
|
||||||
|
t.t.Debug = on
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect opens a WebSocket connection to the telescope.
|
||||||
|
func (t *Telescope) Connect(ip string) error {
|
||||||
|
return t.t.Connect(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close disconnects from the telescope.
|
||||||
|
func (t *Telescope) Close() error {
|
||||||
|
return t.t.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notifications returns a channel for receiving NOTIFY packets.
|
||||||
|
func (t *Telescope) Notifications() chan *pb.WsPacket {
|
||||||
|
return t.t.SubscribeNotifications()
|
||||||
|
}
|
||||||
|
|
||||||
|
// send marshals an inner proto message, sends it, and returns the raw response.
|
||||||
|
func (t *Telescope) send(cmd uint32, msg proto.Message) (*pb.WsPacket, error) {
|
||||||
|
data, err := proto.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("marshal: %w", err)
|
||||||
|
}
|
||||||
|
return t.t.Send(ModuleIDForCmd(cmd), cmd, data, 10*time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendEmpty sends a command with no payload (empty data field).
|
||||||
|
func (t *Telescope) sendEmpty(cmd uint32) (*pb.WsPacket, error) {
|
||||||
|
return t.t.Send(ModuleIDForCmd(cmd), cmd, nil, 10*time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
// sendNotify marshals and sends without waiting for a response.
|
||||||
|
func (t *Telescope) sendNotify(cmd uint32, msg proto.Message) error {
|
||||||
|
data, err := proto.Marshal(msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return t.t.SendNotify(ModuleIDForCmd(cmd), cmd, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// decodeResponse parses the WsPacket data field into the given message type.
|
||||||
|
func decodeResponse(pkt *pb.WsPacket, msg proto.Message) error {
|
||||||
|
if len(pkt.GetData()) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return proto.Unmarshal(pkt.GetData(), msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Camera commands ---
|
||||||
|
|
||||||
|
// Camera identifies which camera to address.
|
||||||
|
type Camera int
|
||||||
|
|
||||||
|
const (
|
||||||
|
CameraTele Camera = 0
|
||||||
|
CameraWide Camera = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
func cameraCmd(tele, wide uint32, cam Camera) uint32 {
|
||||||
|
if cam == CameraWide {
|
||||||
|
return wide
|
||||||
|
}
|
||||||
|
return tele
|
||||||
|
}
|
||||||
|
|
||||||
|
// OpenCamera opens the specified camera.
|
||||||
|
// Some firmwares don't send a type=3 reply; fire-and-forget is safe.
|
||||||
|
func (t *Telescope) OpenCamera(cam Camera) error {
|
||||||
|
return t.sendNotify(cameraCmd(CmdTeleOpenCamera, CmdWideOpenCamera, cam), &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseCamera closes the specified camera.
|
||||||
|
func (t *Telescope) CloseCamera(cam Camera) error {
|
||||||
|
return t.sendNotify(cameraCmd(CmdTeleCloseCamera, CmdWideCloseCamera, cam), &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TakePhoto captures a single photograph.
|
||||||
|
func (t *Telescope) TakePhoto(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTelePhotograph, CmdWidePhotograph, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TakeRawPhoto captures a RAW photo.
|
||||||
|
func (t *Telescope) TakeRawPhoto(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTelePhotoRaw, CmdWidePhotoRaw, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartBurst starts burst capture.
|
||||||
|
func (t *Telescope) StartBurst(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTeleBurst, CmdWideBurst, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopBurst stops burst capture.
|
||||||
|
func (t *Telescope) StopBurst(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTeleStopBurst, CmdWideStopBurst, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartRecord starts video recording.
|
||||||
|
func (t *Telescope) StartRecord(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTeleStartRecord, CmdWideStartRecord, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopRecord stops video recording.
|
||||||
|
func (t *Telescope) StopRecord(cam Camera) error {
|
||||||
|
_, err := t.sendEmpty(cameraCmd(CmdTeleStopRecord, CmdWideStopRecord, cam))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExposure sets the exposure index on the camera.
|
||||||
|
func (t *Telescope) SetExposure(cam Camera, index int32) error {
|
||||||
|
_, err := t.send(cameraCmd(CmdTeleSetExp, CmdWideSetExp, cam), &pb.ReqSetExp{Index: index})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGain sets the gain index on the camera.
|
||||||
|
func (t *Telescope) SetGain(cam Camera, index int32) error {
|
||||||
|
_, err := t.send(cameraCmd(CmdTeleSetGain, CmdWideSetGain, cam), &pb.ReqSetGain{Index: index})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllParams retrieves all camera parameters.
|
||||||
|
// NOTE: this command may not receive a type=3 reply on some firmwares.
|
||||||
|
// The params are also embedded in the GetDeviceState response.
|
||||||
|
func (t *Telescope) GetAllParams(cam Camera) (*pb.ResGetAllParams, error) {
|
||||||
|
pkt, err := t.sendEmpty(cameraCmd(CmdTeleGetAllParams, CmdWideGetAllParams, cam))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp := &pb.ResGetAllParams{}
|
||||||
|
return resp, decodeResponse(pkt, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Motor commands ---
|
||||||
|
|
||||||
|
// SlewJoystick sends a joystick vector for manual slewing (fire-and-forget).
|
||||||
|
func (t *Telescope) SlewJoystick(angle, length float64) error {
|
||||||
|
return t.sendNotify(CmdMotorJoystick, &pb.ReqMotorServiceJoystick{
|
||||||
|
VectorAngle: angle,
|
||||||
|
VectorLength: length,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SlewJoystickFixedAngle sends a fixed-angle joystick vector.
|
||||||
|
func (t *Telescope) SlewJoystickFixedAngle(angle, length float64) error {
|
||||||
|
return t.sendNotify(CmdMotorJoystickFixedAngle, &pb.ReqMotorServiceJoystickFixedAngle{
|
||||||
|
VectorAngle: angle,
|
||||||
|
VectorLength: length,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotorStop stops a motor by ID (0=RA/az, 1=DEC/alt). Fire-and-forget —
|
||||||
|
// the telescope does not ack motor commands with a same-cmd response.
|
||||||
|
func (t *Telescope) MotorStop(motorID int32) error {
|
||||||
|
return t.sendNotify(CmdMotorStop, &pb.ReqMotorStop{Id: motorID})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotorJoystickStop stops joystick movement. Fire-and-forget.
|
||||||
|
func (t *Telescope) MotorJoystickStop() error {
|
||||||
|
return t.sendNotify(CmdMotorJoystickStop, &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotorRunTo moves a motor to a target position at a given speed.
|
||||||
|
// Fire-and-forget — verify via GetDeviceState after sending.
|
||||||
|
func (t *Telescope) MotorRunTo(id int32, endPos, speed float64) error {
|
||||||
|
return t.sendNotify(CmdMotorRun, &pb.ReqMotorRunTo{
|
||||||
|
Id: id,
|
||||||
|
EndPosition: endPos,
|
||||||
|
Speed: speed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotorReset resets a motor (finds home via limit switch).
|
||||||
|
// cmd 14003 is inferred (not in WsCmd enum). direction: false=back, true=forward.
|
||||||
|
func (t *Telescope) MotorReset(id int32, direction bool) error {
|
||||||
|
return t.sendNotify(CmdMotorReset, &pb.ReqMotorReset{Id: id, Direction: direction})
|
||||||
|
}
|
||||||
|
|
||||||
|
// MotorGetPosition queries a motor's current position.
|
||||||
|
// cmd 14001 is inferred. May timeout if firmware doesn't support it.
|
||||||
|
func (t *Telescope) MotorGetPosition(id int32) (*pb.ResMotorPosition, error) {
|
||||||
|
pkt, err := t.send(CmdMotorGetPosition, &pb.ReqMotorGetPosition{Id: id})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp := &pb.ResMotorPosition{}
|
||||||
|
return resp, decodeResponse(pkt, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFocusInfinityPos retrieves the user-defined infinity focus position.
|
||||||
|
func (t *Telescope) GetFocusInfinityPos() (int32, error) {
|
||||||
|
pkt, err := t.sendEmpty(CmdFocusGetUserInfinity)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
resp := &pb.ReqSetUserInfinityPos{}
|
||||||
|
if err := decodeResponse(pkt, resp); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return resp.GetPos(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFocusInfinityPos saves the current focus position as user infinity.
|
||||||
|
func (t *Telescope) SetFocusInfinityPos(pos int32) error {
|
||||||
|
_, err := t.send(CmdFocusSetUserInfinity, &pb.ReqSetUserInfinityPos{Pos: pos})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Astro commands ---
|
||||||
|
|
||||||
|
// StartCalibration begins star calibration.
|
||||||
|
func (t *Telescope) StartCalibration() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStartCalibration)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopCalibration cancels calibration.
|
||||||
|
func (t *Telescope) StopCalibration() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStopCalibration)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GotoDSO slews to a deep-sky object by RA/Dec coordinates.
|
||||||
|
func (t *Telescope) GotoDSO(ra, dec float64, name string) error {
|
||||||
|
_, err := t.send(CmdAstroStartGotoDSO, &pb.ReqGotoDSO{Ra: ra, Dec: dec, TargetName: name})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GotoSolar slews to a solar system object by index.
|
||||||
|
func (t *Telescope) GotoSolar(index int32) error {
|
||||||
|
_, err := t.send(CmdAstroStartGotoSolar, &pb.ReqGotoSolarSystem{Index: index})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopGoto aborts a GoTo operation.
|
||||||
|
func (t *Telescope) StopGoto() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStopGoto)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartLiveStacking begins live-stacking capture.
|
||||||
|
func (t *Telescope) StartLiveStacking() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStartLiveStacking)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopLiveStacking stops live-stacking.
|
||||||
|
func (t *Telescope) StopLiveStacking() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStopLiveStacking)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartEqSolving begins equatorial solving (polar alignment).
|
||||||
|
func (t *Telescope) StartEqSolving() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStartEqSolving)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopEqSolving stops equatorial solving.
|
||||||
|
func (t *Telescope) StopEqSolving() error {
|
||||||
|
_, err := t.sendEmpty(CmdAstroStopEqSolving)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Focus commands ---
|
||||||
|
|
||||||
|
// AutoFocus triggers autofocus.
|
||||||
|
func (t *Telescope) AutoFocus() error {
|
||||||
|
_, err := t.sendEmpty(CmdFocusAutoFocus)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManualSingleStepFocus moves the focuser a single step (direction 0=in, 1=out).
|
||||||
|
func (t *Telescope) ManualSingleStepFocus(direction uint32) error {
|
||||||
|
_, err := t.send(CmdFocusManualSingle, &pb.ReqManualSingleStepFocus{Direction: direction})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartAstroAutoFocus starts astro autofocus.
|
||||||
|
func (t *Telescope) StartAstroAutoFocus() error {
|
||||||
|
_, err := t.sendEmpty(CmdFocusStartAstroAF)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopAstroAutoFocus stops astro autofocus.
|
||||||
|
func (t *Telescope) StopAstroAutoFocus() error {
|
||||||
|
_, err := t.sendEmpty(CmdFocusStopAstroAF)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Track commands ---
|
||||||
|
|
||||||
|
// StartTracking starts tracking an object at the given coordinates.
|
||||||
|
func (t *Telescope) StartTracking(x, y, w, h, camID int32) error {
|
||||||
|
_, err := t.send(CmdTrackStart, &pb.ReqStartTrack{
|
||||||
|
X: x, Y: y, W: w, H: h, CamId: camID,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopTracking stops tracking.
|
||||||
|
func (t *Telescope) StopTracking() error {
|
||||||
|
_, err := t.sendEmpty(CmdTrackStop)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- System commands ---
|
||||||
|
|
||||||
|
// SetTime syncs the telescope clock.
|
||||||
|
func (t *Telescope) SetTime(unixSec uint64, tzOffset float64) error {
|
||||||
|
_, err := t.send(CmdSystemSetTime, &pb.ReqSetTime{
|
||||||
|
Timestamp: unixSec,
|
||||||
|
TimezoneOffset: tzOffset,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLocation sets the observing location.
|
||||||
|
func (t *Telescope) SetLocation(lat, lng, alt float64) error {
|
||||||
|
_, err := t.send(CmdSystemSetLocation, &pb.ReqSetLocation{
|
||||||
|
Latitude: lat,
|
||||||
|
Longitude: lng,
|
||||||
|
Altitude: alt,
|
||||||
|
Enable: true,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Power / RGB commands ---
|
||||||
|
|
||||||
|
// RGBOn turns on the RGB ring light. Fire-and-forget — no type=3 reply.
|
||||||
|
// Verify via GetDeviceState().DeviceStateInfo.RgbState.
|
||||||
|
func (t *Telescope) RGBOn() error {
|
||||||
|
return t.sendNotify(CmdRGBOn, &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGBOff turns off the RGB ring light. Fire-and-forget.
|
||||||
|
func (t *Telescope) RGBOff() error {
|
||||||
|
return t.sendNotify(CmdRGBOff, &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// PowerDown powers off the telescope. Fire-and-forget.
|
||||||
|
func (t *Telescope) PowerDown() error {
|
||||||
|
return t.sendNotify(CmdPowerDown, &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reboot reboots the telescope. Fire-and-forget.
|
||||||
|
func (t *Telescope) Reboot() error {
|
||||||
|
return t.sendNotify(CmdReboot, &pb.ReqMotorServiceJoystickStop{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Task Center ---
|
||||||
|
|
||||||
|
// GetDeviceState queries the current device state.
|
||||||
|
func (t *Telescope) GetDeviceState() (*pb.ResGetDeviceStateInfo, error) {
|
||||||
|
pkt, err := t.sendEmpty(CmdTaskGetDeviceState)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp := &pb.ResGetDeviceStateInfo{}
|
||||||
|
return resp, decodeResponse(pkt, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchShootingMode switches the active shooting mode.
|
||||||
|
func (t *Telescope) SwitchShootingMode(modeID int32) error {
|
||||||
|
_, err := t.send(CmdTaskSwitchMode, &pb.ReqSwitchShootingMode{Mode: modeID})
|
||||||
|
return err
|
||||||
|
}
|
||||||
231
dwarfctl/internal/api/client_test.go
Normal file
231
dwarfctl/internal/api/client_test.go
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
pb "github.com/antitbone/dwarfctl/proto"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestModuleIDForCmd verifies that every command range maps to the correct
|
||||||
|
// module_id, matching WsCmd.getModuleId() from the original APK.
|
||||||
|
func TestModuleIDForCmd(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
cmd uint32
|
||||||
|
wantMod uint32
|
||||||
|
}{
|
||||||
|
// Camera Tele (10000–10499)
|
||||||
|
{"tele open camera", CmdTeleOpenCamera, ModuleCameraTele},
|
||||||
|
{"tele photo", CmdTelePhotograph, ModuleCameraTele},
|
||||||
|
{"tele get all params", CmdTeleGetAllParams, ModuleCameraTele},
|
||||||
|
{"tele boundary low", 10000, ModuleCameraTele},
|
||||||
|
{"tele boundary high-1", 10499, ModuleCameraTele},
|
||||||
|
|
||||||
|
// Astro (11000–11499)
|
||||||
|
{"astro calibrate", CmdAstroStartCalibration, ModuleAstro},
|
||||||
|
{"astro goto dso", CmdAstroStartGotoDSO, ModuleAstro},
|
||||||
|
{"astro boundary low", 11000, ModuleAstro},
|
||||||
|
{"astro boundary high-1", 11499, ModuleAstro},
|
||||||
|
|
||||||
|
// Camera Wide (12000–12499)
|
||||||
|
{"wide open camera", CmdWideOpenCamera, ModuleCameraWide},
|
||||||
|
{"wide photo", CmdWidePhotograph, ModuleCameraWide},
|
||||||
|
{"wide boundary low", 12000, ModuleCameraWide},
|
||||||
|
{"wide boundary high-1", 12499, ModuleCameraWide},
|
||||||
|
|
||||||
|
// System (13000–13299)
|
||||||
|
{"system set time", CmdSystemSetTime, ModuleSystem},
|
||||||
|
{"system set location", CmdSystemSetLocation, ModuleSystem},
|
||||||
|
{"system boundary low", 13000, ModuleSystem},
|
||||||
|
{"system boundary high-1", 13299, ModuleSystem},
|
||||||
|
|
||||||
|
// RGB Power (13500–13799)
|
||||||
|
{"rgb on", CmdRGBOn, ModuleRGBPower},
|
||||||
|
{"reboot", CmdReboot, ModuleRGBPower},
|
||||||
|
{"rgb boundary low", 13500, ModuleRGBPower},
|
||||||
|
{"rgb boundary high-1", 13799, ModuleRGBPower},
|
||||||
|
|
||||||
|
// Motor (14000–14499)
|
||||||
|
{"motor run", CmdMotorRun, ModuleMotor},
|
||||||
|
{"motor joystick", CmdMotorJoystick, ModuleMotor},
|
||||||
|
{"motor boundary low", 14000, ModuleMotor},
|
||||||
|
{"motor boundary high-1", 14499, ModuleMotor},
|
||||||
|
|
||||||
|
// Track (14800–14899)
|
||||||
|
{"track start", CmdTrackStart, ModuleTrack},
|
||||||
|
{"switch preview", CmdSwitchMainPreview, ModuleTrack},
|
||||||
|
{"track boundary low", 14800, ModuleTrack},
|
||||||
|
{"track boundary high-1", 14899, ModuleTrack},
|
||||||
|
|
||||||
|
// Focus (15000–15199)
|
||||||
|
{"focus auto", CmdFocusAutoFocus, ModuleFocus},
|
||||||
|
{"focus boundary low", 15000, ModuleFocus},
|
||||||
|
{"focus boundary high-1", 15199, ModuleFocus},
|
||||||
|
|
||||||
|
// Notify (15200–15499)
|
||||||
|
{"notify track result", NotifyTrackResult, ModuleNotify},
|
||||||
|
{"notify boundary low", 15200, ModuleNotify},
|
||||||
|
{"notify boundary high-1", 15499, ModuleNotify},
|
||||||
|
|
||||||
|
// Panorama (15500–15599)
|
||||||
|
{"pano start grid", CmdPanoStartGrid, ModulePanorama},
|
||||||
|
{"pano boundary low", 15500, ModulePanorama},
|
||||||
|
{"pano boundary high-1", 15599, ModulePanorama},
|
||||||
|
|
||||||
|
// ITips (15700–15799)
|
||||||
|
{"itips boundary low", 15700, ModuleITips},
|
||||||
|
|
||||||
|
// Shooting Schedule (16100–16399)
|
||||||
|
{"schedule boundary low", 16100, ModuleShootingSchedule},
|
||||||
|
{"schedule boundary high-1", 16399, ModuleShootingSchedule},
|
||||||
|
|
||||||
|
// Task Center (16400–16599)
|
||||||
|
{"task get state", CmdTaskGetDeviceState, ModuleTaskCenter},
|
||||||
|
{"task boundary low", 16400, ModuleTaskCenter},
|
||||||
|
{"task boundary high-1", 16599, ModuleTaskCenter},
|
||||||
|
|
||||||
|
// Param (16700–16799)
|
||||||
|
{"param boundary low", 16700, ModuleParam},
|
||||||
|
|
||||||
|
// Voice Assistant (16800–16899)
|
||||||
|
{"voice boundary low", 16800, ModuleVoiceAssistant},
|
||||||
|
|
||||||
|
// Device (17000–17099)
|
||||||
|
{"device boundary low", 17000, ModuleDevice},
|
||||||
|
{"device boundary high-1", 17099, ModuleDevice},
|
||||||
|
|
||||||
|
// Out of range
|
||||||
|
{"unknown cmd 9999", 9999, ModuleNone},
|
||||||
|
{"unknown cmd 99999", 99999, ModuleNone},
|
||||||
|
{"cmd 0", 0, ModuleNone},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got := ModuleIDForCmd(tc.cmd)
|
||||||
|
if got != tc.wantMod {
|
||||||
|
t.Errorf("ModuleIDForCmd(%d) = %d, want %d", tc.cmd, got, tc.wantMod)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCameraCmdHelper verifies that cameraCmd dispatches correctly between
|
||||||
|
// Tele and Wide command IDs.
|
||||||
|
func TestCameraCmdHelper(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
tele, wide uint32
|
||||||
|
cam Camera
|
||||||
|
want uint32
|
||||||
|
}{
|
||||||
|
{CmdTeleOpenCamera, CmdWideOpenCamera, CameraTele, CmdTeleOpenCamera},
|
||||||
|
{CmdTeleOpenCamera, CmdWideOpenCamera, CameraWide, CmdWideOpenCamera},
|
||||||
|
{10002, 12022, CameraTele, 10002},
|
||||||
|
{10002, 12022, CameraWide, 12022},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
got := cameraCmd(tc.tele, tc.wide, tc.cam)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("cameraCmd(%d,%d,%d) = %d, want %d",
|
||||||
|
tc.tele, tc.wide, tc.cam, got, tc.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDecodeResponseEmpty verifies that decoding an empty Data field does
|
||||||
|
// not error and leaves the message at its zero value.
|
||||||
|
func TestDecodeResponseEmpty(t *testing.T) {
|
||||||
|
pkt := &pb.WsPacket{Cmd: 10000, Data: nil}
|
||||||
|
msg := &pb.ResGetAllParams{}
|
||||||
|
if err := decodeResponse(pkt, msg); err != nil {
|
||||||
|
t.Errorf("decodeResponse with empty data should not error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDecodeResponseWithPayload verifies that a response payload decodes
|
||||||
|
// correctly.
|
||||||
|
func TestDecodeResponseWithPayload(t *testing.T) {
|
||||||
|
// Build a ComResponse{code: 0} as the inner payload
|
||||||
|
inner := &pb.ComResponse{Code: 0}
|
||||||
|
data, err := proto.Marshal(inner)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal ComResponse: %v", err)
|
||||||
|
}
|
||||||
|
pkt := &pb.WsPacket{Cmd: 10002, Data: data}
|
||||||
|
|
||||||
|
msg := &pb.ComResponse{}
|
||||||
|
if err := decodeResponse(pkt, msg); err != nil {
|
||||||
|
t.Fatalf("decodeResponse: %v", err)
|
||||||
|
}
|
||||||
|
if msg.GetCode() != 0 {
|
||||||
|
t.Errorf("code: got %d, want 0", msg.GetCode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestDecodeResponseBadData verifies that corrupt data returns an error.
|
||||||
|
func TestDecodeResponseBadData(t *testing.T) {
|
||||||
|
pkt := &pb.WsPacket{Data: []byte{0xff, 0xff, 0xff, 0xff}}
|
||||||
|
msg := &pb.ComResponse{}
|
||||||
|
// Invalid wire format should error (may or may not depending on content,
|
||||||
|
// but definitely garbled). We just ensure it doesn't panic.
|
||||||
|
_ = decodeResponse(pkt, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCommandIDUniqueness verifies that command IDs are unique across all
|
||||||
|
// modules (no accidental collisions).
|
||||||
|
func TestCommandIDUniqueness(t *testing.T) {
|
||||||
|
allCmds := []uint32{
|
||||||
|
CmdTeleOpenCamera, CmdTeleCloseCamera, CmdTelePhotograph, CmdTeleBurst,
|
||||||
|
CmdTeleStopBurst, CmdTeleStartRecord, CmdTeleStopRecord,
|
||||||
|
CmdTeleSetExp, CmdTeleGetExp, CmdTeleSetGain, CmdTeleGetGain,
|
||||||
|
CmdAstroStartCalibration, CmdAstroStopCalibration,
|
||||||
|
CmdAstroStartGotoDSO, CmdAstroStartGotoSolar, CmdAstroStopGoto,
|
||||||
|
CmdWideOpenCamera, CmdWideCloseCamera, CmdWidePhotograph,
|
||||||
|
CmdSystemSetTime, CmdSystemSetLocation,
|
||||||
|
CmdRGBOn, CmdRGBOff, CmdPowerDown, CmdReboot,
|
||||||
|
CmdMotorRun, CmdMotorStop, CmdMotorJoystick,
|
||||||
|
CmdTrackStart, CmdTrackStop, CmdSwitchMainPreview,
|
||||||
|
CmdFocusAutoFocus, CmdFocusManualSingle,
|
||||||
|
CmdPanoStartGrid, CmdPanoStop,
|
||||||
|
CmdTaskStartTask, CmdTaskStopTask, CmdTaskGetDeviceState,
|
||||||
|
}
|
||||||
|
seen := make(map[uint32]string)
|
||||||
|
for _, cmd := range allCmds {
|
||||||
|
if prev, ok := seen[cmd]; ok {
|
||||||
|
t.Errorf("command ID %d is duplicated (%s vs %s)", cmd, prev, "current")
|
||||||
|
}
|
||||||
|
seen[cmd] = "seen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNewTelescope verifies that New() returns a usable Telescope instance.
|
||||||
|
func TestNewTelescope(t *testing.T) {
|
||||||
|
scope := New("test-client")
|
||||||
|
if scope == nil {
|
||||||
|
t.Fatal("New() returned nil")
|
||||||
|
}
|
||||||
|
if scope.t == nil {
|
||||||
|
t.Fatal("telescope transport is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestModuleConstants verify module IDs are non-zero and distinct.
|
||||||
|
func TestModuleConstants(t *testing.T) {
|
||||||
|
modules := []uint32{
|
||||||
|
ModuleCameraTele, ModuleCameraWide, ModuleAstro, ModuleSystem,
|
||||||
|
ModuleRGBPower, ModuleMotor, ModuleTrack, ModuleFocus, ModuleNotify,
|
||||||
|
ModulePanorama, ModuleITips, ModuleShootingSchedule, ModuleTaskCenter,
|
||||||
|
ModuleParam, ModuleVoiceAssistant, ModuleDevice,
|
||||||
|
}
|
||||||
|
seen := make(map[uint32]bool)
|
||||||
|
for _, m := range modules {
|
||||||
|
if m == 0 {
|
||||||
|
t.Errorf("module constant is 0 (ModuleNone)")
|
||||||
|
}
|
||||||
|
if seen[m] {
|
||||||
|
t.Errorf("module constant %d is duplicated", m)
|
||||||
|
}
|
||||||
|
seen[m] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
243
dwarfctl/internal/api/commands.go
Normal file
243
dwarfctl/internal/api/commands.go
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
// Module IDs (WsModuleId enum ordinals, derived from WsCmd.getModuleId ranges).
|
||||||
|
const (
|
||||||
|
ModuleNone = 0
|
||||||
|
ModuleCameraTele = 1
|
||||||
|
ModuleCameraWide = 2
|
||||||
|
ModuleAstro = 3
|
||||||
|
ModuleSystem = 4
|
||||||
|
ModuleRGBPower = 5
|
||||||
|
ModuleMotor = 6
|
||||||
|
ModuleTrack = 7
|
||||||
|
ModuleFocus = 8
|
||||||
|
ModuleNotify = 9
|
||||||
|
ModulePanorama = 10
|
||||||
|
ModuleITips = 11
|
||||||
|
ModuleShootingSchedule = 13
|
||||||
|
ModuleTaskCenter = 14
|
||||||
|
ModuleParam = 15
|
||||||
|
ModuleVoiceAssistant = 16
|
||||||
|
ModuleCameraGuide = 17
|
||||||
|
ModuleDevice = 18
|
||||||
|
)
|
||||||
|
|
||||||
|
// ModuleIDForCmd derives the module_id from a command ID using the same
|
||||||
|
// range logic as WsCmd.getModuleId() in the original APK.
|
||||||
|
func ModuleIDForCmd(cmd uint32) uint32 {
|
||||||
|
switch {
|
||||||
|
case cmd >= 10000 && cmd < 10500:
|
||||||
|
return ModuleCameraTele
|
||||||
|
case cmd >= 11000 && cmd < 11500:
|
||||||
|
return ModuleAstro
|
||||||
|
case cmd >= 12000 && cmd < 12500:
|
||||||
|
return ModuleCameraWide
|
||||||
|
case cmd >= 13000 && cmd < 13300:
|
||||||
|
return ModuleSystem
|
||||||
|
case cmd >= 13500 && cmd < 13800:
|
||||||
|
return ModuleRGBPower
|
||||||
|
case cmd >= 14000 && cmd < 14500:
|
||||||
|
return ModuleMotor
|
||||||
|
case cmd >= 14800 && cmd < 14900:
|
||||||
|
return ModuleTrack
|
||||||
|
case cmd >= 15000 && cmd < 15200:
|
||||||
|
return ModuleFocus
|
||||||
|
case cmd >= 15200 && cmd < 15500:
|
||||||
|
return ModuleNotify
|
||||||
|
case cmd >= 15500 && cmd < 15600:
|
||||||
|
return ModulePanorama
|
||||||
|
case cmd >= 15700 && cmd < 15800:
|
||||||
|
return ModuleITips
|
||||||
|
case cmd >= 16100 && cmd < 16400:
|
||||||
|
return ModuleShootingSchedule
|
||||||
|
case cmd >= 16400 && cmd < 16600:
|
||||||
|
return ModuleTaskCenter
|
||||||
|
case cmd >= 16700 && cmd < 16800:
|
||||||
|
return ModuleParam
|
||||||
|
case cmd >= 16800 && cmd < 16900:
|
||||||
|
return ModuleVoiceAssistant
|
||||||
|
case cmd >= 17000 && cmd < 17100:
|
||||||
|
return ModuleDevice
|
||||||
|
default:
|
||||||
|
return ModuleNone
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Command IDs — Camera Tele (MODULE_CAMERA_TELE, 10000–10499).
|
||||||
|
const (
|
||||||
|
CmdTeleOpenCamera = 10000
|
||||||
|
CmdTeleCloseCamera = 10001
|
||||||
|
CmdTelePhotograph = 10002
|
||||||
|
CmdTeleBurst = 10003
|
||||||
|
CmdTeleStopBurst = 10004
|
||||||
|
CmdTeleStartRecord = 10005
|
||||||
|
CmdTeleStopRecord = 10006
|
||||||
|
CmdTeleSetExpMode = 10007
|
||||||
|
CmdTeleGetExpMode = 10008
|
||||||
|
CmdTeleSetExp = 10009
|
||||||
|
CmdTeleGetExp = 10010
|
||||||
|
CmdTeleSetGainMode = 10011
|
||||||
|
CmdTeleGetGainMode = 10012
|
||||||
|
CmdTeleSetGain = 10013
|
||||||
|
CmdTeleGetGain = 10014
|
||||||
|
CmdTeleSetBrightness = 10015
|
||||||
|
CmdTeleGetBrightness = 10016
|
||||||
|
CmdTeleSetContrast = 10017
|
||||||
|
CmdTeleGetContrast = 10018
|
||||||
|
CmdTeleSetSaturation = 10019
|
||||||
|
CmdTeleGetSaturation = 10020
|
||||||
|
CmdTeleSetHue = 10021
|
||||||
|
CmdTeleGetHue = 10022
|
||||||
|
CmdTeleSetSharpness = 10023
|
||||||
|
CmdTeleGetSharpness = 10024
|
||||||
|
CmdTeleSetWBMode = 10025
|
||||||
|
CmdTeleGetWBMode = 10026
|
||||||
|
CmdTeleSetWBScene = 10027
|
||||||
|
CmdTeleGetWBScene = 10028
|
||||||
|
CmdTeleSetWBCT = 10029
|
||||||
|
CmdTeleGetWBCT = 10030
|
||||||
|
CmdTeleSetIRCut = 10031
|
||||||
|
CmdTeleGetIRCut = 10032
|
||||||
|
CmdTeleStartTimelapse = 10033
|
||||||
|
CmdTeleStopTimelapse = 10034
|
||||||
|
CmdTeleSetAllParams = 10035
|
||||||
|
CmdTeleGetAllParams = 10036
|
||||||
|
CmdTeleSetFeatureParam = 10037
|
||||||
|
CmdTeleGetAllFeatureParams = 10038
|
||||||
|
CmdTeleGetWorkingState = 10039
|
||||||
|
CmdTeleSetJpgQuality = 10040
|
||||||
|
CmdTelePhotoRaw = 10041
|
||||||
|
CmdTeleSetRtspBitrate = 10042
|
||||||
|
CmdTeleSwitchResolution = 10047
|
||||||
|
CmdTeleSwitchFramerate = 10048
|
||||||
|
CmdTeleSwitchCropRatio = 10049
|
||||||
|
CmdTeleSetPreviewQuality = 10050
|
||||||
|
)
|
||||||
|
|
||||||
|
// Camera Wide (MODULE_CAMERA_WIDE, 12000–12499).
|
||||||
|
const (
|
||||||
|
CmdWideOpenCamera = 12000
|
||||||
|
CmdWideCloseCamera = 12001
|
||||||
|
CmdWideSetExpMode = 12002
|
||||||
|
CmdWideGetExpMode = 12003
|
||||||
|
CmdWideSetExp = 12004
|
||||||
|
CmdWideGetExp = 12005
|
||||||
|
CmdWideSetGain = 12006
|
||||||
|
CmdWideGetGain = 12007
|
||||||
|
CmdWidePhotograph = 12022
|
||||||
|
CmdWideBurst = 12023
|
||||||
|
CmdWideStopBurst = 12024
|
||||||
|
CmdWidePhotoRaw = 12029
|
||||||
|
CmdWideStartRecord = 12030
|
||||||
|
CmdWideStopRecord = 12031
|
||||||
|
CmdWideGetAllParams = 12027
|
||||||
|
CmdWideSetAllParams = 12028
|
||||||
|
)
|
||||||
|
|
||||||
|
// Astro (MODULE_ASTRO, 11000–11499).
|
||||||
|
const (
|
||||||
|
CmdAstroStartCalibration = 11000
|
||||||
|
CmdAstroStopCalibration = 11001
|
||||||
|
CmdAstroStartGotoDSO = 11002
|
||||||
|
CmdAstroStartGotoSolar = 11003
|
||||||
|
CmdAstroStopGoto = 11004
|
||||||
|
CmdAstroStartLiveStacking = 11005
|
||||||
|
CmdAstroStopLiveStacking = 11006
|
||||||
|
CmdAstroStartRawDark = 11007
|
||||||
|
CmdAstroStopRawDark = 11008
|
||||||
|
CmdAstroGoLive = 11010
|
||||||
|
CmdAstroStartOneClickGoto = 11013
|
||||||
|
CmdAstroStopOneClickGoto = 11015
|
||||||
|
CmdAstroStartEqSolving = 11018
|
||||||
|
CmdAstroStopEqSolving = 11019
|
||||||
|
CmdAstroStartAiEnhance = 11029
|
||||||
|
CmdAstroStopAiEnhance = 11030
|
||||||
|
CmdAstroStartMosaic = 11031
|
||||||
|
CmdAstroStartSkyFinder = 11047
|
||||||
|
CmdAstroStopSkyFinder = 11048
|
||||||
|
)
|
||||||
|
|
||||||
|
// System (MODULE_SYSTEM, 13000–13299).
|
||||||
|
const (
|
||||||
|
CmdSystemSetTime = 13000
|
||||||
|
CmdSystemSetTimeZone = 13001
|
||||||
|
CmdSystemSetMtpMode = 13002
|
||||||
|
CmdSystemSetCpuMode = 13003
|
||||||
|
CmdSystemSetMasterLock = 13004
|
||||||
|
CmdSystemSetLocation = 13010
|
||||||
|
)
|
||||||
|
|
||||||
|
// RGB Power (MODULE_RGB_POWER, 13500–13799).
|
||||||
|
const (
|
||||||
|
CmdRGBOn = 13500
|
||||||
|
CmdRGBOff = 13501
|
||||||
|
CmdPowerDown = 13502
|
||||||
|
CmdReboot = 13505
|
||||||
|
)
|
||||||
|
|
||||||
|
// Motor constants — extended (14001-14005 are inferred from gaps)
|
||||||
|
const (
|
||||||
|
CmdMotorRun = 14000
|
||||||
|
CmdMotorGetPosition = 14001 // inferred: missing ID between RUN and STOP
|
||||||
|
CmdMotorStop = 14002
|
||||||
|
CmdMotorReset = 14003 // inferred: missing ID after STOP
|
||||||
|
CmdMotorChangeSpeed = 14004 // inferred
|
||||||
|
CmdMotorChangeDirection = 14005 // inferred
|
||||||
|
CmdMotorJoystick = 14006
|
||||||
|
CmdMotorJoystickFixedAngle = 14007
|
||||||
|
CmdMotorJoystickStop = 14008
|
||||||
|
CmdMotorDualCameraLinkage = 14009
|
||||||
|
)
|
||||||
|
|
||||||
|
// Track (MODULE_TRACK, 14800–14899).
|
||||||
|
const (
|
||||||
|
CmdTrackStart = 14800
|
||||||
|
CmdTrackStop = 14801
|
||||||
|
CmdSentryStart = 14802
|
||||||
|
CmdSentryStop = 14803
|
||||||
|
CmdSwitchMainPreview = 14809
|
||||||
|
)
|
||||||
|
|
||||||
|
// Focus (MODULE_FOCUS, 15000–15199).
|
||||||
|
const (
|
||||||
|
CmdFocusAutoFocus = 15000
|
||||||
|
CmdFocusManualSingle = 15001
|
||||||
|
CmdFocusStartManualCont = 15002
|
||||||
|
CmdFocusStopManualCont = 15003
|
||||||
|
CmdFocusStartAstroAF = 15004
|
||||||
|
CmdFocusStopAstroAF = 15005
|
||||||
|
CmdFocusGetUserInfinity = 15011
|
||||||
|
CmdFocusSetUserInfinity = 15012
|
||||||
|
)
|
||||||
|
|
||||||
|
// Panorama (MODULE_PANORAMA, 15500–15599).
|
||||||
|
const (
|
||||||
|
CmdPanoStartGrid = 15500
|
||||||
|
CmdPanoStop = 15501
|
||||||
|
CmdPanoStartStitch = 15503
|
||||||
|
CmdPanoStopStitch = 15504
|
||||||
|
CmdPanoStartFraming = 15509
|
||||||
|
CmdPanoStopFraming = 15510
|
||||||
|
CmdPanoResetFraming = 15511
|
||||||
|
CmdPanoUpdateFramingRect = 15512
|
||||||
|
)
|
||||||
|
|
||||||
|
// Task Center (MODULE_TASK_CENTER, 16400–16599).
|
||||||
|
const (
|
||||||
|
CmdTaskStartTask = 16400
|
||||||
|
CmdTaskStopTask = 16401
|
||||||
|
CmdTaskSwitchMode = 16402
|
||||||
|
CmdTaskSwitchTech = 16403
|
||||||
|
CmdTaskGetDeviceState = 16405
|
||||||
|
)
|
||||||
|
|
||||||
|
// Notify (MODULE_NOTIFY, 15200–15399) — server-pushed, not requestable.
|
||||||
|
const (
|
||||||
|
NotifyTrackResult = 15225
|
||||||
|
NotifyStateCaptureRawDark = 15206
|
||||||
|
NotifyCalibrationResult = 15256
|
||||||
|
NotifyStateAstroGoto = 15211
|
||||||
|
NotifyTemperature = 15243
|
||||||
|
NotifySDCardInfo = 15203
|
||||||
|
NotifyPowerOff = 15229
|
||||||
|
)
|
||||||
219
dwarfctl/internal/transport/client.go
Normal file
219
dwarfctl/internal/transport/client.go
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
pb "github.com/antitbone/dwarfctl/proto"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
WsMajorVersion = 2
|
||||||
|
WsMinorVersion = 3
|
||||||
|
WsPort = 9900
|
||||||
|
)
|
||||||
|
|
||||||
|
// MsgType mirrors WsMessageType: request=0, response=1, notification=2, reply=3.
|
||||||
|
type MsgType uint32
|
||||||
|
|
||||||
|
const (
|
||||||
|
MsgRequest MsgType = 0
|
||||||
|
MsgResponse MsgType = 1
|
||||||
|
MsgNotification MsgType = 2
|
||||||
|
MsgReply MsgType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Client is a WebSocket client for the DWARF telescope control plane.
|
||||||
|
type Client struct {
|
||||||
|
conn *websocket.Conn
|
||||||
|
clientID string
|
||||||
|
deviceID uint32
|
||||||
|
mu sync.Mutex
|
||||||
|
pending map[uint32]chan *pb.WsPacket
|
||||||
|
notifyChs []chan *pb.WsPacket
|
||||||
|
done chan struct{}
|
||||||
|
Debug bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewClient creates a client with the given client_id and device_id.
|
||||||
|
func NewClient(clientID string, deviceID uint32) *Client {
|
||||||
|
return &Client{
|
||||||
|
clientID: clientID,
|
||||||
|
deviceID: deviceID,
|
||||||
|
pending: make(map[uint32]chan *pb.WsPacket),
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect opens the WebSocket to the telescope.
|
||||||
|
func (c *Client) Connect(ip string) error {
|
||||||
|
url := fmt.Sprintf("ws://%s:%d/?client_id=%s", ip, WsPort, c.clientID)
|
||||||
|
dialer := websocket.Dialer{
|
||||||
|
HandshakeTimeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
conn, _, err := dialer.Dial(url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ws dial %s: %w", url, err)
|
||||||
|
}
|
||||||
|
c.conn = conn
|
||||||
|
go c.readLoop()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close shuts down the connection.
|
||||||
|
func (c *Client) Close() error {
|
||||||
|
close(c.done)
|
||||||
|
if c.conn != nil {
|
||||||
|
return c.conn.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsConnected returns true if the WebSocket is open.
|
||||||
|
func (c *Client) IsConnected() bool {
|
||||||
|
return c.conn != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readLoop continuously reads WsPacket frames and dispatches them.
|
||||||
|
func (c *Client) readLoop() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-c.done:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
_, data, err := c.conn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
if c.Debug {
|
||||||
|
log.Printf("[WS] read error: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pkt := &pb.WsPacket{}
|
||||||
|
if err := proto.Unmarshal(data, pkt); err != nil {
|
||||||
|
if c.Debug {
|
||||||
|
log.Printf("[WS] unmarshal error: %v (raw %d bytes)", err, len(data))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c.Debug {
|
||||||
|
log.Printf("[WS] recv cmd=%d module=%d type=%d data=%d bytes",
|
||||||
|
pkt.GetCmd(), pkt.GetModuleId(), pkt.GetType(), len(pkt.GetData()))
|
||||||
|
}
|
||||||
|
// Dispatch based on type. Many telescopes send responses with
|
||||||
|
// type=0 (default proto3 value) instead of type=1. So we try
|
||||||
|
// response dispatch for type 0, 1, and 3.
|
||||||
|
switch MsgType(pkt.GetType()) {
|
||||||
|
case MsgNotification:
|
||||||
|
c.dispatchNotification(pkt)
|
||||||
|
// Also try response dispatch — some notifications double as acks
|
||||||
|
c.dispatchResponse(pkt)
|
||||||
|
default:
|
||||||
|
// Covers type=0 (unset), type=1 (response), type=3 (reply)
|
||||||
|
c.dispatchResponse(pkt)
|
||||||
|
c.dispatchNotification(pkt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatchResponse delivers a response to the pending request waiter.
|
||||||
|
func (c *Client) dispatchResponse(pkt *pb.WsPacket) {
|
||||||
|
c.mu.Lock()
|
||||||
|
ch, ok := c.pending[pkt.GetCmd()]
|
||||||
|
if ok {
|
||||||
|
delete(c.pending, pkt.GetCmd())
|
||||||
|
}
|
||||||
|
c.mu.Unlock()
|
||||||
|
if ok {
|
||||||
|
ch <- pkt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatchNotification fans out to all subscribers.
|
||||||
|
func (c *Client) dispatchNotification(pkt *pb.WsPacket) {
|
||||||
|
c.mu.Lock()
|
||||||
|
chs := make([]chan *pb.WsPacket, len(c.notifyChs))
|
||||||
|
copy(chs, c.notifyChs)
|
||||||
|
c.mu.Unlock()
|
||||||
|
for _, ch := range chs {
|
||||||
|
select {
|
||||||
|
case ch <- pkt:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubscribeNotifications returns a channel for receiving NOTIFY packets.
|
||||||
|
func (c *Client) SubscribeNotifications() chan *pb.WsPacket {
|
||||||
|
ch := make(chan *pb.WsPacket, 64)
|
||||||
|
c.mu.Lock()
|
||||||
|
c.notifyChs = append(c.notifyChs, ch)
|
||||||
|
c.mu.Unlock()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send sends a raw command with the given module_id and cmd, carrying
|
||||||
|
// the serialized inner proto message as data. It returns the response packet.
|
||||||
|
func (c *Client) Send(moduleID uint32, cmd uint32, data []byte, timeout time.Duration) (*pb.WsPacket, error) {
|
||||||
|
pkt := &pb.WsPacket{
|
||||||
|
MajorVersion: WsMajorVersion,
|
||||||
|
MinorVersion: WsMinorVersion,
|
||||||
|
DeviceId: c.deviceID,
|
||||||
|
ModuleId: moduleID,
|
||||||
|
Cmd: cmd,
|
||||||
|
Type: uint32(MsgRequest),
|
||||||
|
Data: data,
|
||||||
|
ClientId: c.clientID,
|
||||||
|
}
|
||||||
|
raw, err := proto.Marshal(pkt)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("marshal WsPacket: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
respCh := make(chan *pb.WsPacket, 1)
|
||||||
|
c.mu.Lock()
|
||||||
|
c.pending[cmd] = respCh
|
||||||
|
c.mu.Unlock()
|
||||||
|
|
||||||
|
if err := c.conn.WriteMessage(websocket.BinaryMessage, raw); err != nil {
|
||||||
|
c.mu.Lock()
|
||||||
|
delete(c.pending, cmd)
|
||||||
|
c.mu.Unlock()
|
||||||
|
return nil, fmt.Errorf("ws write: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case resp := <-respCh:
|
||||||
|
return resp, nil
|
||||||
|
case <-time.After(timeout):
|
||||||
|
c.mu.Lock()
|
||||||
|
delete(c.pending, cmd)
|
||||||
|
c.mu.Unlock()
|
||||||
|
return nil, fmt.Errorf("timeout waiting for response to cmd %d", cmd)
|
||||||
|
case <-c.done:
|
||||||
|
return nil, fmt.Errorf("connection closed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendNotify sends a command without waiting for a response (fire-and-forget).
|
||||||
|
func (c *Client) SendNotify(moduleID uint32, cmd uint32, data []byte) error {
|
||||||
|
pkt := &pb.WsPacket{
|
||||||
|
MajorVersion: WsMajorVersion,
|
||||||
|
MinorVersion: WsMinorVersion,
|
||||||
|
DeviceId: c.deviceID,
|
||||||
|
ModuleId: moduleID,
|
||||||
|
Cmd: cmd,
|
||||||
|
Type: uint32(MsgRequest),
|
||||||
|
Data: data,
|
||||||
|
ClientId: c.clientID,
|
||||||
|
}
|
||||||
|
raw, err := proto.Marshal(pkt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.conn.WriteMessage(websocket.BinaryMessage, raw)
|
||||||
|
}
|
||||||
223
dwarfctl/internal/transport/client_test.go
Normal file
223
dwarfctl/internal/transport/client_test.go
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
pb "github.com/antitbone/dwarfctl/proto"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestEnvelopeRoundTrip verifies that a WsPacket envelope survives a
|
||||||
|
// marshal → unmarshal round-trip with all fields intact. This is the core
|
||||||
|
// guarantee for every command sent to the telescope.
|
||||||
|
func TestEnvelopeRoundTrip(t *testing.T) {
|
||||||
|
original := &pb.WsPacket{
|
||||||
|
MajorVersion: WsMajorVersion,
|
||||||
|
MinorVersion: WsMinorVersion,
|
||||||
|
DeviceId: 1,
|
||||||
|
ModuleId: 6, // MODULE_MOTOR
|
||||||
|
Cmd: 14006,
|
||||||
|
Type: uint32(MsgRequest),
|
||||||
|
Data: []byte{0x08, 0x2a}, // some inner proto bytes
|
||||||
|
ClientId: "test-client-007",
|
||||||
|
}
|
||||||
|
|
||||||
|
raw, err := proto.Marshal(original)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal WsPacket: %v", err)
|
||||||
|
}
|
||||||
|
if len(raw) == 0 {
|
||||||
|
t.Fatal("marshaled envelope is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded := &pb.WsPacket{}
|
||||||
|
if err := proto.Unmarshal(raw, decoded); err != nil {
|
||||||
|
t.Fatalf("unmarshal WsPacket: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if decoded.GetMajorVersion() != original.GetMajorVersion() {
|
||||||
|
t.Errorf("major_version: got %d, want %d", decoded.GetMajorVersion(), original.GetMajorVersion())
|
||||||
|
}
|
||||||
|
if decoded.GetMinorVersion() != original.GetMinorVersion() {
|
||||||
|
t.Errorf("minor_version: got %d, want %d", decoded.GetMinorVersion(), original.GetMinorVersion())
|
||||||
|
}
|
||||||
|
if decoded.GetDeviceId() != original.GetDeviceId() {
|
||||||
|
t.Errorf("device_id: got %d, want %d", decoded.GetDeviceId(), original.GetDeviceId())
|
||||||
|
}
|
||||||
|
if decoded.GetModuleId() != original.GetModuleId() {
|
||||||
|
t.Errorf("module_id: got %d, want %d", decoded.GetModuleId(), original.GetModuleId())
|
||||||
|
}
|
||||||
|
if decoded.GetCmd() != original.GetCmd() {
|
||||||
|
t.Errorf("cmd: got %d, want %d", decoded.GetCmd(), original.GetCmd())
|
||||||
|
}
|
||||||
|
if decoded.GetType() != original.GetType() {
|
||||||
|
t.Errorf("type: got %d, want %d", decoded.GetType(), original.GetType())
|
||||||
|
}
|
||||||
|
if decoded.GetClientId() != original.GetClientId() {
|
||||||
|
t.Errorf("client_id: got %q, want %q", decoded.GetClientId(), original.GetClientId())
|
||||||
|
}
|
||||||
|
if string(decoded.GetData()) != string(original.GetData()) {
|
||||||
|
t.Errorf("data: got %x, want %x", decoded.GetData(), original.GetData())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestEnvelopeWithInnerProto verifies that inner proto messages (the Data
|
||||||
|
// field) encode and decode correctly within the envelope.
|
||||||
|
func TestEnvelopeWithInnerProto(t *testing.T) {
|
||||||
|
inner := &pb.ReqMotorServiceJoystick{
|
||||||
|
VectorAngle: 90.5,
|
||||||
|
VectorLength: 0.75,
|
||||||
|
}
|
||||||
|
innerBytes, err := proto.Marshal(inner)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal inner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
envelope := &pb.WsPacket{
|
||||||
|
MajorVersion: WsMajorVersion,
|
||||||
|
MinorVersion: WsMinorVersion,
|
||||||
|
DeviceId: 1,
|
||||||
|
ModuleId: 6,
|
||||||
|
Cmd: 14006,
|
||||||
|
Type: uint32(MsgRequest),
|
||||||
|
Data: innerBytes,
|
||||||
|
ClientId: "dwarfctl-test",
|
||||||
|
}
|
||||||
|
raw, err := proto.Marshal(envelope)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal envelope: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded := &pb.WsPacket{}
|
||||||
|
if err := proto.Unmarshal(raw, decoded); err != nil {
|
||||||
|
t.Fatalf("unmarshal envelope: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the inner message
|
||||||
|
innerDecoded := &pb.ReqMotorServiceJoystick{}
|
||||||
|
if err := proto.Unmarshal(decoded.GetData(), innerDecoded); err != nil {
|
||||||
|
t.Fatalf("unmarshal inner: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if innerDecoded.GetVectorAngle() != 90.5 {
|
||||||
|
t.Errorf("vector_angle: got %f, want 90.5", innerDecoded.GetVectorAngle())
|
||||||
|
}
|
||||||
|
if innerDecoded.GetVectorLength() != 0.75 {
|
||||||
|
t.Errorf("vector_length: got %f, want 0.75", innerDecoded.GetVectorLength())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestNewClientDefaults verifies that NewClient stores the client_id and
|
||||||
|
// device_id and initializes the pending map.
|
||||||
|
func TestNewClientDefaults(t *testing.T) {
|
||||||
|
c := NewClient("my-client", 2)
|
||||||
|
if c.clientID != "my-client" {
|
||||||
|
t.Errorf("clientID: got %q, want %q", c.clientID, "my-client")
|
||||||
|
}
|
||||||
|
if c.deviceID != 2 {
|
||||||
|
t.Errorf("deviceID: got %d, want 2", c.deviceID)
|
||||||
|
}
|
||||||
|
if c.pending == nil {
|
||||||
|
t.Error("pending map is nil")
|
||||||
|
}
|
||||||
|
if c.done == nil {
|
||||||
|
t.Error("done channel is nil")
|
||||||
|
}
|
||||||
|
if c.IsConnected() {
|
||||||
|
t.Error("should not be connected before Connect()")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMsgTypeConstants verifies the wire-format type values match the
|
||||||
|
// original enum (request=0, response=1, notification=2, reply=3).
|
||||||
|
func TestMsgTypeConstants(t *testing.T) {
|
||||||
|
cases := map[MsgType]uint32{
|
||||||
|
MsgRequest: 0,
|
||||||
|
MsgResponse: 1,
|
||||||
|
MsgNotification: 2,
|
||||||
|
MsgReply: 3,
|
||||||
|
}
|
||||||
|
for mt, expected := range cases {
|
||||||
|
if uint32(mt) != expected {
|
||||||
|
t.Errorf("MsgType %d: got value %d, want %d", mt, uint32(mt), expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSubscribeNotifications verifies the notification fan-out works:
|
||||||
|
// multiple subscribers all receive the same packet.
|
||||||
|
func TestSubscribeNotifications(t *testing.T) {
|
||||||
|
c := NewClient("test", 1)
|
||||||
|
ch1 := c.SubscribeNotifications()
|
||||||
|
ch2 := c.SubscribeNotifications()
|
||||||
|
|
||||||
|
pkt := &pb.WsPacket{Cmd: 15243, Type: uint32(MsgNotification)}
|
||||||
|
c.dispatchNotification(pkt)
|
||||||
|
|
||||||
|
// Both channels should receive a copy
|
||||||
|
select {
|
||||||
|
case got := <-ch1:
|
||||||
|
if got.GetCmd() != 15243 {
|
||||||
|
t.Errorf("ch1 cmd: got %d, want 15243", got.GetCmd())
|
||||||
|
}
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
t.Fatal("ch1 did not receive notification")
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case got := <-ch2:
|
||||||
|
if got.GetCmd() != 15243 {
|
||||||
|
t.Errorf("ch2 cmd: got %d, want 15243", got.GetCmd())
|
||||||
|
}
|
||||||
|
case <-time.After(100 * time.Millisecond):
|
||||||
|
t.Fatal("ch2 did not receive notification")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestEmptyDataEnvelope verifies that commands with no payload (empty Data)
|
||||||
|
// survive a round-trip.
|
||||||
|
func TestEmptyDataEnvelope(t *testing.T) {
|
||||||
|
original := &pb.WsPacket{
|
||||||
|
MajorVersion: WsMajorVersion,
|
||||||
|
MinorVersion: WsMinorVersion,
|
||||||
|
DeviceId: 1,
|
||||||
|
ModuleId: 3, // MODULE_ASTRO
|
||||||
|
Cmd: 11000,
|
||||||
|
Type: uint32(MsgRequest),
|
||||||
|
Data: nil,
|
||||||
|
ClientId: "dwarfctl",
|
||||||
|
}
|
||||||
|
raw, err := proto.Marshal(original)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("marshal: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded := &pb.WsPacket{}
|
||||||
|
if err := proto.Unmarshal(raw, decoded); err != nil {
|
||||||
|
t.Fatalf("unmarshal: %v", err)
|
||||||
|
}
|
||||||
|
if decoded.GetCmd() != 11000 {
|
||||||
|
t.Errorf("cmd: got %d, want 11000", decoded.GetCmd())
|
||||||
|
}
|
||||||
|
if len(decoded.GetData()) != 0 {
|
||||||
|
t.Errorf("data should be empty, got %d bytes", len(decoded.GetData()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestWsPort verifies the port constant matches the reverse-engineered value.
|
||||||
|
func TestWsPort(t *testing.T) {
|
||||||
|
if WsPort != 9900 {
|
||||||
|
t.Errorf("WsPort: got %d, want 9900", WsPort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestVersionConstants verifies the protocol version constants.
|
||||||
|
func TestVersionConstants(t *testing.T) {
|
||||||
|
if WsMajorVersion != 2 {
|
||||||
|
t.Errorf("WsMajorVersion: got %d, want 2", WsMajorVersion)
|
||||||
|
}
|
||||||
|
if WsMinorVersion != 3 {
|
||||||
|
t.Errorf("WsMinorVersion: got %d, want 3", WsMinorVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
367
dwarfctl/proto/astro.proto
Normal file
367
dwarfctl/proto/astro.proto
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqStartCalibration {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCalibration {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGotoDSO {
|
||||||
|
double ra = 1;
|
||||||
|
double dec = 2;
|
||||||
|
string target_name = 3;
|
||||||
|
bool goto_only = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGotoSolarSystem {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
string target_name = 4;
|
||||||
|
bool force_start = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGotoSolarSystem {
|
||||||
|
int32 code = 1;
|
||||||
|
ReqGotoSolarSystem req = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopGoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureRawLiveStacking {
|
||||||
|
int32 ir_index = 1;
|
||||||
|
bool force_start = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqFastStopCaptureRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCheckDarkFrame {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCheckDarkFrame {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureDarkFrame {
|
||||||
|
int32 reshoot = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureDarkFrame {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureDarkFrameWithParam {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
int32 cap_size = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureDarkFrameWithParam {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDarkFrameList {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDarkFrameInfo {
|
||||||
|
// oneof _temperature
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
string exp_name = 4;
|
||||||
|
string gain_name = 5;
|
||||||
|
string bin_name = 6;
|
||||||
|
int32 temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDarkFrameInfoList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated ResGetDarkFrameInfo results = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelDarkFrame {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain_index = 2;
|
||||||
|
int32 bin_index = 3;
|
||||||
|
int32 temp_value = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelDarkFrameList {
|
||||||
|
repeated ReqDelDarkFrame dark_list = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDelDarkFrameList {
|
||||||
|
int32 code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGoLive {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqTrackSpecialTarget {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTrackSpecialTarget {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickGotoDSO {
|
||||||
|
double ra = 1;
|
||||||
|
double dec = 2;
|
||||||
|
string target_name = 3;
|
||||||
|
double lon = 4;
|
||||||
|
double lat = 5;
|
||||||
|
int32 shooting_mode = 6;
|
||||||
|
bool goto_only = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResOneClickGoto {
|
||||||
|
int32 step = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
bool all_end = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickGotoSolarSystem {
|
||||||
|
int32 index = 1;
|
||||||
|
double lon = 2;
|
||||||
|
double lat = 3;
|
||||||
|
string target_name = 4;
|
||||||
|
int32 shooting_mode = 5;
|
||||||
|
bool force_start = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResOneClickGotoSolarSystem {
|
||||||
|
int32 step = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
bool all_end = 3;
|
||||||
|
ReqOneClickGotoSolarSystem req = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopOneClickGoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureWideRawLiveStacking {
|
||||||
|
bool force_start = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureWideRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqFastStopCaptureWideRawLiveStacking {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartEqSolving {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStartEqSolving {
|
||||||
|
double azi_err = 1;
|
||||||
|
double alt_err = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopEqSolving {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartAiEnhance {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopAiEnhance {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartMosaic {
|
||||||
|
int32 horizontal_scale = 1;
|
||||||
|
int32 vertical_scale = 2;
|
||||||
|
int32 rotation = 3;
|
||||||
|
int32 ir_index = 4;
|
||||||
|
bool force_start = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartMakeFitsThumb {
|
||||||
|
string src_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopMakeFitsThumb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMakeFitsThumb {
|
||||||
|
int32 code = 1;
|
||||||
|
string src_dir = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MakeFitsThumbTaskParam {
|
||||||
|
string src_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqIsImageStackable {
|
||||||
|
repeated string src_dirs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResIsImageStackable {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated ResGetDarkFrameInfo need_dark_frame_info = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartRepostprocess {
|
||||||
|
repeated string src_dirs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopRepostprocess {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResRepostprocess {
|
||||||
|
int32 code = 1;
|
||||||
|
string result_dir = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RepostprocessTaskParam {
|
||||||
|
string result_dir = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAstroShootingTime {
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 horizontal_scale = 2;
|
||||||
|
int32 vertical_scale = 3;
|
||||||
|
int32 rotation = 4;
|
||||||
|
int32 cam_id = 5;
|
||||||
|
int32 shooting_mode = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAstroShootingTime {
|
||||||
|
enum AstroMode {
|
||||||
|
NORMAL = 0;
|
||||||
|
MOSAIC = 1;
|
||||||
|
}
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_time = 2;
|
||||||
|
int32 cam_id = 3;
|
||||||
|
ResGetAstroShootingTime.AstroMode astro_mode = 4;
|
||||||
|
int32 shooting_mode = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetCaliFrameList {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 cali_frame_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaliFrameInfo {
|
||||||
|
// oneof _filter_type
|
||||||
|
// oneof _info_id
|
||||||
|
// oneof _temp_value
|
||||||
|
string exp_name = 1;
|
||||||
|
int32 gain = 2;
|
||||||
|
int32 resolution = 3;
|
||||||
|
int32 camera_type = 4;
|
||||||
|
int32 progress = 5;
|
||||||
|
int32 cali_frame_type = 6;
|
||||||
|
int32 filter_type = 7;
|
||||||
|
int32 info_id = 8;
|
||||||
|
int32 temp_value = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetCaliFrameList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated CaliFrameInfo list = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
int32 cali_frame_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDelCaliFrameList {
|
||||||
|
repeated int32 info_ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCaptureCaliFrame {
|
||||||
|
// oneof _filter_type
|
||||||
|
int32 exp_index = 1;
|
||||||
|
int32 gain = 2;
|
||||||
|
int32 resolution = 3;
|
||||||
|
int32 cap_size = 4;
|
||||||
|
int32 camera_type = 5;
|
||||||
|
int32 cali_frame_type = 6;
|
||||||
|
int32 filter_type = 7;
|
||||||
|
int32 scene_type = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCaptureCaliFrame {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameTaskParam {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 cali_frame_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetQuickSetList {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message QuikSetInfo {
|
||||||
|
string exp_name = 1;
|
||||||
|
int32 exp_index = 2;
|
||||||
|
int32 gain = 3;
|
||||||
|
int32 resolution = 4;
|
||||||
|
int32 camera_type = 5;
|
||||||
|
string info_id = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetQuikSetList {
|
||||||
|
int32 code = 1;
|
||||||
|
repeated QuikSetInfo quick_set_list = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetQuickSet {
|
||||||
|
string info_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetQuickSet {
|
||||||
|
int32 code = 1;
|
||||||
|
string info_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOneClickShooting {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResAstroShooting {
|
||||||
|
// oneof _exp_name
|
||||||
|
// oneof _gain
|
||||||
|
// oneof _resolution
|
||||||
|
// oneof _filter_type
|
||||||
|
// oneof _temp_threshold
|
||||||
|
int32 code = 1;
|
||||||
|
string exp_name = 2;
|
||||||
|
int32 gain = 3;
|
||||||
|
int32 resolution = 4;
|
||||||
|
int32 filter_type = 5;
|
||||||
|
int32 temp_threshold = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartSkyTargetFinder {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
bool force_restart = 3;
|
||||||
|
int32 scene_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStartSkyTargetFinder {
|
||||||
|
int32 code = 1;
|
||||||
|
double zenith_azi = 2;
|
||||||
|
double zenith_alt = 3;
|
||||||
|
double center_azi = 4;
|
||||||
|
double center_alt = 5;
|
||||||
|
double center_roll = 6;
|
||||||
|
int32 scene_type = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopSkyTargetFinder {
|
||||||
|
}
|
||||||
|
|
||||||
51
dwarfctl/proto/base.proto
Normal file
51
dwarfctl/proto/base.proto
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
enum WsMajorVersion {
|
||||||
|
WS_MAJOR_VERSION_UNKNOWN = 0;
|
||||||
|
WS_MAJOR_VERSION_NUMBER = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum WsMinorVersion {
|
||||||
|
WS_MINOR_VERSION_UNKNOWN = 0;
|
||||||
|
WS_MINOR_VERSION_NUMBER = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WsPacket {
|
||||||
|
uint32 major_version = 1;
|
||||||
|
uint32 minor_version = 2;
|
||||||
|
uint32 device_id = 3;
|
||||||
|
uint32 module_id = 4;
|
||||||
|
uint32 cmd = 5;
|
||||||
|
uint32 type = 6;
|
||||||
|
bytes data = 7;
|
||||||
|
string client_id = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResponse {
|
||||||
|
int32 code = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithInt {
|
||||||
|
int32 value = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithDouble {
|
||||||
|
double value = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComResWithString {
|
||||||
|
string str = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonParam {
|
||||||
|
bool hasAuto = 1;
|
||||||
|
int32 auto_mode = 2;
|
||||||
|
int32 id = 3;
|
||||||
|
int32 mode_index = 4;
|
||||||
|
int32 index = 5;
|
||||||
|
double continue_value = 6;
|
||||||
|
}
|
||||||
|
|
||||||
202
dwarfctl/proto/ble.proto
Normal file
202
dwarfctl/proto/ble.proto
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
enum VocalType {
|
||||||
|
VT_UNKNOWN = 0;
|
||||||
|
VT_PING = 1;
|
||||||
|
VT_ECHO = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetconfig {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string ble_psd = 2;
|
||||||
|
string client_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAp {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 wifi_type = 2;
|
||||||
|
int32 auto_start = 3;
|
||||||
|
int32 country_list = 4;
|
||||||
|
string country = 5;
|
||||||
|
string ble_psd = 6;
|
||||||
|
string client_id = 7;
|
||||||
|
bool force_restart = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSta {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 auto_start = 2;
|
||||||
|
string ble_psd = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string psd = 5;
|
||||||
|
string client_id = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetblewifi {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
string ble_psd = 3;
|
||||||
|
string value = 4;
|
||||||
|
string client_id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReset {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetwifilist {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetsysteminfo {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCheckFile {
|
||||||
|
int32 cmd = 1;
|
||||||
|
string file_path = 2;
|
||||||
|
string md5 = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCommon {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetconfig {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 state = 3;
|
||||||
|
int32 wifi_mode = 4;
|
||||||
|
int32 ap_mode = 5;
|
||||||
|
int32 auto_start = 6;
|
||||||
|
int32 ap_country_list = 7;
|
||||||
|
string ssid = 8;
|
||||||
|
string psd = 9;
|
||||||
|
string ip = 10;
|
||||||
|
string ap_country = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResAp {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 mode = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string psd = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSta {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
string ssid = 3;
|
||||||
|
string psd = 4;
|
||||||
|
string ip = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetblewifi {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 mode = 3;
|
||||||
|
string value = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReset {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WifiInfo {
|
||||||
|
int32 signal_level = 1;
|
||||||
|
string ssid = 2;
|
||||||
|
string security_capability = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResWifilist {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
repeated string ssid = 4;
|
||||||
|
repeated WifiInfo wifi_info_list = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetsysteminfo {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
int32 protocol_version = 3;
|
||||||
|
string device = 4;
|
||||||
|
string mac_address = 5;
|
||||||
|
string dwarf_ota_version = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReceiveDataError {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCheckFile {
|
||||||
|
int32 cmd = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ComDwarfMsg {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DwarfPing {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
uint64 timestamp = 2;
|
||||||
|
bytes magic = 3;
|
||||||
|
repeated bytes vocals = 4;
|
||||||
|
repeated bytes mutes = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StationModel {
|
||||||
|
uint32 family = 1;
|
||||||
|
uint32 revision = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NifAP {
|
||||||
|
// oneof _ipv6
|
||||||
|
string ifname = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
string country_code = 3;
|
||||||
|
string ssid = 4;
|
||||||
|
string sec = 5;
|
||||||
|
string psw = 6;
|
||||||
|
bytes ipv4 = 7;
|
||||||
|
bytes ipv6 = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NifSTA {
|
||||||
|
// oneof _ssid
|
||||||
|
// oneof _psw
|
||||||
|
// oneof _rssi
|
||||||
|
// oneof _ipv4
|
||||||
|
// oneof _ipv6
|
||||||
|
string ifname = 1;
|
||||||
|
string ssid = 2;
|
||||||
|
string psw = 3;
|
||||||
|
int32 rssi = 4;
|
||||||
|
bytes ipv4 = 5;
|
||||||
|
bytes ipv6 = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DwarfEcho {
|
||||||
|
VocalType vocaltype = 1;
|
||||||
|
uint64 timestamp = 2;
|
||||||
|
bytes magic = 3;
|
||||||
|
uint64 ts_ping = 4;
|
||||||
|
bytes mac_address = 5;
|
||||||
|
StationModel model = 6;
|
||||||
|
string sn = 7;
|
||||||
|
string name = 8;
|
||||||
|
string psw = 9;
|
||||||
|
string fw_version = 10;
|
||||||
|
string ws_scheme = 11;
|
||||||
|
uint32 session = 12;
|
||||||
|
NifAP ap = 13;
|
||||||
|
NifSTA sta = 14;
|
||||||
|
}
|
||||||
|
|
||||||
216
dwarfctl/proto/camera.proto
Normal file
216
dwarfctl/proto/camera.proto
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
message ReqOpenCamera {
|
||||||
|
bool binning = 1;
|
||||||
|
int32 rtsp_encode_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCloseCamera {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPhoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqBurstPhoto {
|
||||||
|
int32 count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopBurstPhoto {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartRecord {
|
||||||
|
int32 encode_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopRecord {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetExpMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetExpMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetExp {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetExp {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGainMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetGainMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGain {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetGain {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetBrightness {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetBrightness {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetContrast {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetContrast {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetHue {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetHue {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetSaturation {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSaturation {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetSharpness {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSharpness {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBSence {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBSence {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWBCT {
|
||||||
|
int32 index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetWBCT {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetIrCut {
|
||||||
|
int32 value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetIrcut {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTimeLapse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTimeLapse {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetAllParams {
|
||||||
|
int32 exp_mode = 1;
|
||||||
|
int32 exp_index = 2;
|
||||||
|
int32 gain_mode = 3;
|
||||||
|
int32 gain_index = 4;
|
||||||
|
int32 ircut_value = 5;
|
||||||
|
int32 wb_mode = 6;
|
||||||
|
int32 wb_index_type = 7;
|
||||||
|
int32 wb_index = 8;
|
||||||
|
int32 brightness = 9;
|
||||||
|
int32 contrast = 10;
|
||||||
|
int32 hue = 11;
|
||||||
|
int32 saturation = 12;
|
||||||
|
int32 sharpness = 13;
|
||||||
|
int32 jpg_quality = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllParams {
|
||||||
|
repeated CommonParam all_params = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetFeatureParams {
|
||||||
|
CommonParam param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllFeatureParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllFeatureParams {
|
||||||
|
repeated CommonParam all_feature_params = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetSystemWorkingState {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetJpgQuality {
|
||||||
|
int32 quality = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetJpgQuality {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPhotoRaw {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetRtspBitRateType {
|
||||||
|
int32 bitrate_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDisableAllIspProcessing {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqEnableAllIspProcessing {
|
||||||
|
}
|
||||||
|
|
||||||
|
message IspModuleState {
|
||||||
|
int32 module_id = 1;
|
||||||
|
bool state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetIspModuleState {
|
||||||
|
repeated IspModuleState module_states = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetIspModuleState {
|
||||||
|
repeated int32 module_ids = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchResolution {
|
||||||
|
int32 resolution_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchFrameRate {
|
||||||
|
int32 fps_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchCropRatio {
|
||||||
|
int32 crop_ratio = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetPreviewQuality {
|
||||||
|
uint32 level = 1;
|
||||||
|
uint32 quality = 2;
|
||||||
|
}
|
||||||
|
|
||||||
17
dwarfctl/proto/device.proto
Normal file
17
dwarfctl/proto/device.proto
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
message ReqLensDefog {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAutoCooling {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAutoShutdown {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
24948
dwarfctl/proto/dwarf.pb.go
Normal file
24948
dwarfctl/proto/dwarf.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
2653
dwarfctl/proto/dwarf.proto
Normal file
2653
dwarfctl/proto/dwarf.proto
Normal file
File diff suppressed because it is too large
Load Diff
38
dwarfctl/proto/focus.proto
Normal file
38
dwarfctl/proto/focus.proto
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqManualSingleStepFocus {
|
||||||
|
uint32 direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqManualContinuFocus {
|
||||||
|
uint32 direction = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopManualContinuFocus {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqNormalAutoFocus {
|
||||||
|
uint32 mode = 1;
|
||||||
|
uint32 center_x = 2;
|
||||||
|
uint32 center_y = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqAstroAutoFocus {
|
||||||
|
uint32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopAstroAutoFocus {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetUserInfinityPos {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetUserInfinityPos {
|
||||||
|
int32 pos = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResUserInfinityPos {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 pos = 2;
|
||||||
|
}
|
||||||
|
|
||||||
29
dwarfctl/proto/itips.proto
Normal file
29
dwarfctl/proto/itips.proto
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqITipsGet {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResITipsGet {
|
||||||
|
int32 mode = 1;
|
||||||
|
string itips_code = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonITips {
|
||||||
|
int32 itips_status = 1;
|
||||||
|
string itips_code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonStepITips {
|
||||||
|
int32 step_id = 1;
|
||||||
|
int32 step_status = 2;
|
||||||
|
repeated CommonITips step_itips = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResITipsList {
|
||||||
|
repeated CommonStepITips itips_list = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
63
dwarfctl/proto/merge.py
Normal file
63
dwarfctl/proto/merge.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Merge all extracted .proto files into a single unified proto3 file,
|
||||||
|
resolving duplicate names by prefixing with the source module."""
|
||||||
|
import os, re, sys
|
||||||
|
|
||||||
|
PROTO_DIR = sys.argv[1]
|
||||||
|
OUT = sys.argv[2]
|
||||||
|
|
||||||
|
# Collect all message/enum blocks
|
||||||
|
all_blocks = [] # (kind, name, lines, source_file)
|
||||||
|
seen_names = {}
|
||||||
|
duplicates = set()
|
||||||
|
|
||||||
|
for fn in sorted(os.listdir(PROTO_DIR)):
|
||||||
|
if not fn.endswith('.proto'):
|
||||||
|
continue
|
||||||
|
module = fn.replace('.proto','')
|
||||||
|
txt = open(os.path.join(PROTO_DIR, fn)).read()
|
||||||
|
lines = txt.split('\n')
|
||||||
|
i = 0
|
||||||
|
while i < len(lines):
|
||||||
|
line = lines[i]
|
||||||
|
# Skip syntax/package/import/option lines
|
||||||
|
if re.match(r'^(syntax|package|import|option)\s', line):
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
# Find message or enum blocks
|
||||||
|
m = re.match(r'^(message|enum)\s+(\w+)\s*\{', line)
|
||||||
|
if m:
|
||||||
|
kind = m.group(1)
|
||||||
|
name = m.group(2)
|
||||||
|
depth = 1
|
||||||
|
block_lines = [line]
|
||||||
|
i += 1
|
||||||
|
while i < len(lines) and depth > 0:
|
||||||
|
depth += lines[i].count('{') - lines[i].count('}')
|
||||||
|
block_lines.append(lines[i])
|
||||||
|
i += 1
|
||||||
|
# Handle duplicate names
|
||||||
|
final_name = name
|
||||||
|
if name in seen_names:
|
||||||
|
final_name = module.capitalize() + name
|
||||||
|
duplicates.add(name)
|
||||||
|
seen_names[final_name] = True
|
||||||
|
all_blocks.append((kind, final_name, block_lines, module))
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
# Write unified proto
|
||||||
|
with open(OUT, 'w') as f:
|
||||||
|
f.write('syntax = "proto3";\n')
|
||||||
|
f.write('option go_package = "github.com/antitbone/dwarfctl/proto;pb";\n\n')
|
||||||
|
for kind, name, block_lines, module in all_blocks:
|
||||||
|
f.write(f'// source: {module}\n')
|
||||||
|
# Replace the first line's name if it was renamed
|
||||||
|
block_lines[0] = re.sub(
|
||||||
|
rf'^({kind})\s+\w+\s*\{{',
|
||||||
|
rf'\1 {name} {{',
|
||||||
|
block_lines[0])
|
||||||
|
f.write('\n'.join(block_lines) + '\n\n')
|
||||||
|
|
||||||
|
print(f'Merged {len(all_blocks)} blocks into {OUT}')
|
||||||
|
print(f'Renamed duplicates: {duplicates}')
|
||||||
80
dwarfctl/proto/motor_control.proto
Normal file
80
dwarfctl/proto/motor_control.proto
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqMotorServiceJoystick {
|
||||||
|
double vector_angle = 1;
|
||||||
|
double vector_length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorServiceJoystickFixedAngle {
|
||||||
|
double vector_angle = 1;
|
||||||
|
double vector_length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorServiceJoystickStop {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRun {
|
||||||
|
int32 id = 1;
|
||||||
|
double speed = 2;
|
||||||
|
bool direction = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution_level = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRunInPulse {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 frequency = 2;
|
||||||
|
bool direction = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution = 5;
|
||||||
|
int32 pulse = 6;
|
||||||
|
bool mode = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorRunTo {
|
||||||
|
int32 id = 1;
|
||||||
|
double end_position = 2;
|
||||||
|
double speed = 3;
|
||||||
|
int32 speed_ramping = 4;
|
||||||
|
int32 resolution_level = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorGetPosition {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorStop {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorReset {
|
||||||
|
int32 id = 1;
|
||||||
|
bool direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorChangeSpeed {
|
||||||
|
int32 id = 1;
|
||||||
|
double speed = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMotorChangeDirection {
|
||||||
|
int32 id = 1;
|
||||||
|
bool direction = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMotor {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResMotorPosition {
|
||||||
|
int32 id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
double position = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDualCameraLinkage {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
}
|
||||||
|
|
||||||
517
dwarfctl/proto/notify.proto
Normal file
517
dwarfctl/proto/notify.proto
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
|
||||||
|
import "base.proto";
|
||||||
|
|
||||||
|
enum OperationState {
|
||||||
|
OPERATION_STATE_IDLE = 0;
|
||||||
|
OPERATION_STATE_RUNNING = 1;
|
||||||
|
OPERATION_STATE_STOPPING = 2;
|
||||||
|
OPERATION_STATE_STOPPED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AstroState {
|
||||||
|
ASTRO_STATE_IDLE = 0;
|
||||||
|
ASTRO_STATE_RUNNING = 1;
|
||||||
|
ASTRO_STATE_STOPPING = 2;
|
||||||
|
ASTRO_STATE_STOPPED = 3;
|
||||||
|
ASTRO_STATE_PLATE_SOLVING = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SentryModeState {
|
||||||
|
SENTRY_MODE_STATE_IDLE = 0;
|
||||||
|
SENTRY_MODE_STATE_INIT = 1;
|
||||||
|
SENTRY_MODE_STATE_DETECT = 2;
|
||||||
|
SENTRY_MODE_STATE_TRACK = 3;
|
||||||
|
SENTRY_MODE_STATE_TRACK_FINISH = 4;
|
||||||
|
SENTRY_MODE_STATE_STOPPING = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SentryObjectType {
|
||||||
|
SENTRY_OBJECT_TYPE_UNKNOWN = 0;
|
||||||
|
SENTRY_OBJECT_TYPE_UFO = 1;
|
||||||
|
SENTRY_OBJECT_TYPE_BIRD = 2;
|
||||||
|
SENTRY_OBJECT_TYPE_PERSON = 3;
|
||||||
|
SENTRY_OBJECT_TYPE_ANIMAL = 4;
|
||||||
|
SENTRY_OBJECT_TYPE_VEHICLE = 5;
|
||||||
|
SENTRY_OBJECT_TYPE_FLYING = 6;
|
||||||
|
SENTRY_OBJECT_TYPE_BOAT = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PictureMatching {
|
||||||
|
uint32 x = 1;
|
||||||
|
uint32 y = 2;
|
||||||
|
uint32 width = 3;
|
||||||
|
uint32 height = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StorageInfo {
|
||||||
|
uint32 available_size = 1;
|
||||||
|
uint32 total_size = 2;
|
||||||
|
int32 storage_type = 3;
|
||||||
|
bool is_valid = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Temperature {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 temperature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CmosTemperature {
|
||||||
|
// oneof _temperature
|
||||||
|
int32 temperature = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RecordTime {
|
||||||
|
uint32 record_time = 1;
|
||||||
|
uint32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TimeLapseOutTime {
|
||||||
|
uint32 interval = 1;
|
||||||
|
uint32 out_time = 2;
|
||||||
|
uint32 total_time = 3;
|
||||||
|
uint32 camera_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OperationStateNotify {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroCalibrationState {
|
||||||
|
AstroState state = 1;
|
||||||
|
int32 plate_solving_times = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroGotoState {
|
||||||
|
AstroState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroTrackingState {
|
||||||
|
OperationState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureRawDark {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 remaining_time = 2;
|
||||||
|
int32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureRawLiveStacking {
|
||||||
|
// oneof _shooting_time
|
||||||
|
// oneof _stacked_time
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 update_type = 2;
|
||||||
|
int32 current_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 exp_index = 5;
|
||||||
|
int32 gain_index = 6;
|
||||||
|
string target_name = 7;
|
||||||
|
int32 camera_type = 8;
|
||||||
|
int32 shooting_time = 9;
|
||||||
|
int32 stacked_time = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Param {
|
||||||
|
repeated CommonParam param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BurstProgress {
|
||||||
|
uint32 total_count = 1;
|
||||||
|
uint32 completed_count = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaProgress {
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 completed_count = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RgbState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PowerIndState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChargingState {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BatteryInfo {
|
||||||
|
int32 percentage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HostSlaveMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
bool lock = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MTPState {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrackResult {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 w = 3;
|
||||||
|
int32 h = 4;
|
||||||
|
int32 id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CPUMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroTrackingSpecialState {
|
||||||
|
OperationState state = 1;
|
||||||
|
string target_name = 2;
|
||||||
|
int32 index = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PowerOff {
|
||||||
|
}
|
||||||
|
|
||||||
|
message AlbumUpdate {
|
||||||
|
int32 media_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SentryState {
|
||||||
|
SentryModeState state = 1;
|
||||||
|
SentryObjectType object_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OneClickGotoState {
|
||||||
|
// oneof current_state
|
||||||
|
AstroAutoFocusState astro_auto_focus_state = 1;
|
||||||
|
AstroCalibrationState astro_calibration_state = 2;
|
||||||
|
AstroGotoState astro_goto_state = 3;
|
||||||
|
AstroTrackingState astro_tracking_state = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StreamType {
|
||||||
|
int32 stream_type = 1;
|
||||||
|
int32 cam_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MultiTrackResult {
|
||||||
|
repeated TrackResult results = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EqSolvingState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LongExpPhotoProgress {
|
||||||
|
double total_time = 1;
|
||||||
|
double exposured_time = 2;
|
||||||
|
uint32 camera_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingScheduleResultAndState {
|
||||||
|
string schedule_id = 1;
|
||||||
|
int32 result = 2;
|
||||||
|
int32 state = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingTaskState {
|
||||||
|
string schedule_task_id = 1;
|
||||||
|
int32 state = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SkySeacherState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressAiEnhance {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 total_time = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CommonProgress {
|
||||||
|
enum ProgressType {
|
||||||
|
PROGRESS_TYPE_INITING = 0;
|
||||||
|
PROGRESS_TYPE_MOSAIC_MOVING = 1;
|
||||||
|
}
|
||||||
|
int32 current = 1;
|
||||||
|
int32 total = 2;
|
||||||
|
CommonProgress.ProgressType progress_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CalibrationResult {
|
||||||
|
double azi = 1;
|
||||||
|
double alt = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FocusPosition {
|
||||||
|
int32 pos = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SentryAutoHand {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaStitchUploadComplete {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCompressionComplete {
|
||||||
|
int32 code = 1;
|
||||||
|
string panorama_name = 2;
|
||||||
|
string zip_file_path = 3;
|
||||||
|
string zip_file_md5 = 4;
|
||||||
|
uint64 zip_file_size = 5;
|
||||||
|
string stitch_param = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCompressionProgress {
|
||||||
|
string panorama_name = 1;
|
||||||
|
uint32 total_files_num = 2;
|
||||||
|
uint32 compressed_files_num = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadCompressionProgress {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint32 total_files_num = 5;
|
||||||
|
uint32 compressed_files_num = 6;
|
||||||
|
double speed = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadProgress {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint64 total_size = 5;
|
||||||
|
uint64 uploaded_size = 6;
|
||||||
|
double speed = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaCurrentUploadState {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
uint32 total_files_num = 6;
|
||||||
|
uint32 compressed_files_num = 7;
|
||||||
|
uint64 total_size = 8;
|
||||||
|
uint64 uploaded_size = 9;
|
||||||
|
uint32 step = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LowTempProtectionMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message StateSystemResourceOccupation {
|
||||||
|
enum TaskId {
|
||||||
|
IDLE = 0;
|
||||||
|
PANORAMA_UPLOAD = 1;
|
||||||
|
ASTRO_MULTI_STACK = 2;
|
||||||
|
}
|
||||||
|
StateSystemResourceOccupation.TaskId task_id = 1;
|
||||||
|
OperationState state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BodyStatus {
|
||||||
|
enum BodyStatusEnum {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
EQ_MODE = 1;
|
||||||
|
AZI_MODE = 2;
|
||||||
|
}
|
||||||
|
BodyStatus.BodyStatusEnum body_status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProgressCaptureMosaic {
|
||||||
|
int32 total_count = 1;
|
||||||
|
int32 update_type = 2;
|
||||||
|
int32 current_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 exp_index = 5;
|
||||||
|
int32 gain_index = 6;
|
||||||
|
string target_name = 7;
|
||||||
|
int32 horizontal_scale = 8;
|
||||||
|
int32 vertical_scale = 9;
|
||||||
|
int32 rotation = 10;
|
||||||
|
int32 fov_id = 11;
|
||||||
|
int32 fov_total = 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Wb {
|
||||||
|
uint64 mode = 1;
|
||||||
|
int32 ct = 2;
|
||||||
|
int32 scene = 3;
|
||||||
|
int32 camera_type = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralIntParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralFloatParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
float value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeneralBoolParams {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
bool value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchShootingMode {
|
||||||
|
int32 state = 1;
|
||||||
|
int32 source_mode = 2;
|
||||||
|
int32 dst_mode = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchCropRatioState {
|
||||||
|
int32 state = 1;
|
||||||
|
int32 crop_ratio = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResolutionParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 current_res_value = 2;
|
||||||
|
int32 current_fps_value = 3;
|
||||||
|
repeated int32 supported_fps_list = 4;
|
||||||
|
repeated int32 supported_resolution_list = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureRawState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PhotoState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message BurstState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RecordState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TimeLapseState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureRawDarkState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroAutoFocusState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NormalAutoFocusState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroAutoFocusFastState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AreaAutoFocusState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DualCameraLinkageState {
|
||||||
|
OperationState state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NormalTrackState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SwitchResolutionFpsState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 cali_frame_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CaptureCaliFrameProgress {
|
||||||
|
int32 progress = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 cali_frame_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceAttitude {
|
||||||
|
double pitch = 1;
|
||||||
|
double yaw = 2;
|
||||||
|
double roll = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SkyTargetFinderState {
|
||||||
|
OperationState state = 1;
|
||||||
|
int32 scene_type = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingThumbnailUpdateNotify {
|
||||||
|
bytes webp_data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingRectUpdateNotify {
|
||||||
|
double norm_x_tl = 1;
|
||||||
|
double norm_y_tl = 2;
|
||||||
|
double norm_x_br = 3;
|
||||||
|
double norm_y_br = 4;
|
||||||
|
double norm_limit_x_left = 5;
|
||||||
|
double norm_limit_y_top = 6;
|
||||||
|
double norm_limit_x_right = 7;
|
||||||
|
double norm_limit_y_bottom = 8;
|
||||||
|
double rect_hor_fov = 9;
|
||||||
|
double rect_ver_fov = 10;
|
||||||
|
int32 error_code = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoFramingStateNotify {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AutoShutdown {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message LensDefog {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AutoCooling {
|
||||||
|
int32 state = 1;
|
||||||
|
}
|
||||||
|
|
||||||
107
dwarfctl/proto/panorama.proto
Normal file
107
dwarfctl/proto/panorama.proto
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqStartPanoramaByGrid {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaByEulerRange {
|
||||||
|
float yaw_range = 1;
|
||||||
|
float pitch_range = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaStitchUpload {
|
||||||
|
uint64 resource_id = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
int32 app_platform = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string ak = 5;
|
||||||
|
string sk = 6;
|
||||||
|
string token = 7;
|
||||||
|
string bucket = 8;
|
||||||
|
string bucket_prefix = 9;
|
||||||
|
string from = 10;
|
||||||
|
string env_type = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanorama {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaStitchUpload {
|
||||||
|
string user_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetPanoramaCurrentUploadState {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetPanoramaCurrentUploadState {
|
||||||
|
int32 code = 1;
|
||||||
|
string user_id = 2;
|
||||||
|
string busi_no = 3;
|
||||||
|
string panorama_name = 4;
|
||||||
|
string mac = 5;
|
||||||
|
uint32 total_files_num = 6;
|
||||||
|
uint32 compressed_files_num = 7;
|
||||||
|
uint64 total_size = 8;
|
||||||
|
uint64 uploaded_size = 9;
|
||||||
|
uint32 step = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetUploadPredict {
|
||||||
|
string panorama_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetUploadPredict {
|
||||||
|
int32 code = 1;
|
||||||
|
string panorama_name = 2;
|
||||||
|
uint32 file_nums = 3;
|
||||||
|
string resolution = 4;
|
||||||
|
uint64 cloud_data_size = 5;
|
||||||
|
uint64 zip_data_size = 6;
|
||||||
|
uint64 app_zip_data_size = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PanoramaUploadParam {
|
||||||
|
string user_id = 1;
|
||||||
|
string busi_no = 2;
|
||||||
|
string panorama_name = 3;
|
||||||
|
string mac = 4;
|
||||||
|
uint32 total_files_num = 5;
|
||||||
|
uint32 compressed_files_num = 6;
|
||||||
|
uint64 total_size = 7;
|
||||||
|
uint64 uploaded_size = 8;
|
||||||
|
uint32 step = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCompressPanorama {
|
||||||
|
string panorama_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopCompressPanorama {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqResetPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaFraming {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopPanoramaFramingAndStartGrid {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResStopPanoramaFraming {
|
||||||
|
int32 code = 1;
|
||||||
|
double centerX_degree_offset = 2;
|
||||||
|
double centerY_degree_offset = 3;
|
||||||
|
uint32 framing_rows = 4;
|
||||||
|
uint32 framing_cols = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUpdatePanoramaFramingRect {
|
||||||
|
double norm_x_tl = 1;
|
||||||
|
double norm_y_tl = 2;
|
||||||
|
double norm_x_br = 3;
|
||||||
|
double norm_y_br = 4;
|
||||||
|
}
|
||||||
|
|
||||||
51
dwarfctl/proto/param.proto
Normal file
51
dwarfctl/proto/param.proto
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
|
||||||
|
message ReqSetExposure {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGain {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetWb {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 mode = 2;
|
||||||
|
int32 value = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralIntParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
int32 value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralFloatParam {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
float value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetGeneralBoolParams {
|
||||||
|
uint64 param_id = 1;
|
||||||
|
bool value = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetAutoParam {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 shooting_tech = 2;
|
||||||
|
bool is_auto = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSetAutoParam {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
int32 camera_type = 2;
|
||||||
|
int32 shooting_tech = 3;
|
||||||
|
bool is_auto = 4;
|
||||||
|
bool update_all = 5;
|
||||||
|
int32 code = 6;
|
||||||
|
}
|
||||||
|
|
||||||
20
dwarfctl/proto/rgb.proto
Normal file
20
dwarfctl/proto/rgb.proto
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqOpenRgb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCloseRgb {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPowerDown {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqOpenPowerInd {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqClosePowerInd {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReboot {
|
||||||
|
}
|
||||||
|
|
||||||
156
dwarfctl/proto/schedule.proto
Normal file
156
dwarfctl/proto/schedule.proto
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
enum ShootingScheduleState {
|
||||||
|
SHOOTING_SCHEDULE_STATE_INITIALIZED = 0;
|
||||||
|
SHOOTING_SCHEDULE_STATE_PENDING_SHOOT = 1;
|
||||||
|
SHOOTING_SCHEDULE_STATE_SHOOTING = 2;
|
||||||
|
SHOOTING_SCHEDULE_STATE_COMPLETED = 3;
|
||||||
|
SHOOTING_SCHEDULE_STATE_EXPIRED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleSyncState {
|
||||||
|
SHOOTING_SCHEDULE_SYNC_STATE_PENDING_SYNC = 0;
|
||||||
|
SHOOTING_SCHEDULE_SYNC_STATE_SYNCED = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleResult {
|
||||||
|
SHOOTING_SCHEDULE_RESULT_PENDING_START = 0;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_ALL_COMPLETED = 1;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_PARTIALLY_COMPLETED = 2;
|
||||||
|
SHOOTING_SCHEDULE_RESULT_ALL_FAILED = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingTaskState {
|
||||||
|
SHOOTING_TASK_STATUS_IDLE = 0;
|
||||||
|
SHOOTING_TASK_STATUS_SHOOTING = 1;
|
||||||
|
SHOOTING_TASK_STATUS_SUCCESS = 2;
|
||||||
|
SHOOTING_TASK_STATUS_FAILED = 3;
|
||||||
|
SHOOTING_TASK_STATUS_INTERRUPTED = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ShootingScheduleMode {
|
||||||
|
SHOOTING_SCHEDULE_MODE_ASTRO_DEEP_SKY = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingTaskMsg {
|
||||||
|
string schedule_id = 1;
|
||||||
|
string params = 2;
|
||||||
|
ShootingTaskState state = 3;
|
||||||
|
int32 code = 4;
|
||||||
|
int64 created_time = 5;
|
||||||
|
int64 updated_time = 6;
|
||||||
|
string schedule_task_id = 7;
|
||||||
|
int32 param_mode = 8;
|
||||||
|
int32 param_version = 9;
|
||||||
|
int32 create_from = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingScheduleMsg {
|
||||||
|
string schedule_id = 1;
|
||||||
|
string schedule_name = 2;
|
||||||
|
int32 device_id = 3;
|
||||||
|
string mac_address = 4;
|
||||||
|
int64 start_time = 5;
|
||||||
|
int64 end_time = 6;
|
||||||
|
ShootingScheduleResult result = 7;
|
||||||
|
int64 created_time = 8;
|
||||||
|
int64 updated_time = 9;
|
||||||
|
ShootingScheduleState state = 10;
|
||||||
|
int32 lock = 11;
|
||||||
|
string password = 12;
|
||||||
|
repeated ShootingTaskMsg shooting_tasks = 13;
|
||||||
|
int32 param_mode = 14;
|
||||||
|
int32 param_version = 15;
|
||||||
|
string params = 16;
|
||||||
|
int64 schedule_time = 17;
|
||||||
|
ShootingScheduleSyncState sync_state = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSyncShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSyncShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
repeated string time_conflict_schedule_ids = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
bool can_replace = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqCancelShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResCancelShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetAllShootingSchedule {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetAllShootingSchedule {
|
||||||
|
repeated ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetShootingScheduleById {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetShootingScheduleById {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetShootingTaskById {
|
||||||
|
string id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetShootingTaskById {
|
||||||
|
ShootingTaskMsg shooting_task = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqReplaceShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResReplaceShootingSchedule {
|
||||||
|
ShootingScheduleMsg shooting_schedule = 1;
|
||||||
|
repeated ShootingScheduleMsg replaced_shooting_schedule = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUnlockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResUnlockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqLockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResLockShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
int32 code = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeleteShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
string password = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeleteShootingSchedule {
|
||||||
|
string id = 1;
|
||||||
|
int32 code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
71
dwarfctl/proto/system.proto
Normal file
71
dwarfctl/proto/system.proto
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqSetTime {
|
||||||
|
uint64 timestamp = 1;
|
||||||
|
double timezone_offset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetTimezone {
|
||||||
|
string timezone = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetMtpMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetCpuMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqsetMasterLock {
|
||||||
|
bool lock = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDeviceActivateInfo {
|
||||||
|
int32 issuer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateInfo {
|
||||||
|
int32 activate_state = 1;
|
||||||
|
int32 activate_process_state = 2;
|
||||||
|
string request_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeviceActivateWriteFile {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateWriteFile {
|
||||||
|
int32 code = 1;
|
||||||
|
string request_param = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDeviceActivateSuccessfull {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDeviceActivateSuccessfull {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 activate_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqDisableDeviceActivate {
|
||||||
|
string request_param = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResDisableDeviceActivate {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 activate_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSetLocation {
|
||||||
|
double latitude = 1;
|
||||||
|
double longitude = 2;
|
||||||
|
double altitude = 3;
|
||||||
|
string country_region = 4;
|
||||||
|
string province = 5;
|
||||||
|
string city = 6;
|
||||||
|
string district = 7;
|
||||||
|
bool enable = 8;
|
||||||
|
}
|
||||||
|
|
||||||
203
dwarfctl/proto/task_center.proto
Normal file
203
dwarfctl/proto/task_center.proto
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
import "notify.proto";
|
||||||
|
import "panorama.proto";
|
||||||
|
import "astro.proto";
|
||||||
|
|
||||||
|
enum TaskId {
|
||||||
|
TASK_ID_IDLE = 0;
|
||||||
|
TASK_ID_PANORAMA_UPLOAD = 1;
|
||||||
|
TASK_ID_ASTRO_MULTI_STACK_THUMBNAIL_GENERATION = 2;
|
||||||
|
TASK_ID_ASTRO_MULTI_STACK = 3;
|
||||||
|
TASK_ID_CAPTURE_CALI_FRAME = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ExclusiveTaskType {
|
||||||
|
EXCLUSIVE_TYPE_NONE = 0;
|
||||||
|
EXCLUSIVE_TYPE_CAMERA = 1;
|
||||||
|
EXCLUSIVE_TYPE_MOTOR = 2;
|
||||||
|
EXCLUSIVE_TYPE_FOCUS_MOTOR = 4;
|
||||||
|
EXCLUSIVE_TYPE_SYSTEM_IO = 8;
|
||||||
|
EXCLUSIVE_TYPE_SYSTEM_WIFI = 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskAttr {
|
||||||
|
int32 exclusive_mask = 1;
|
||||||
|
int32 priority = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskState {
|
||||||
|
// oneof extendedState
|
||||||
|
notify.OperationState base_state = 1;
|
||||||
|
notify.AstroState astro_extended_state = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TaskParam {
|
||||||
|
// oneof param
|
||||||
|
PanoramaUploadParam panorama_upload = 1;
|
||||||
|
MakeFitsThumbTaskParam make_fits_thumb_task_param = 2;
|
||||||
|
RepostprocessTaskParam repostprocess_task_param = 3;
|
||||||
|
CaptureCaliFrameTaskParam capture_cali_frame_task_param = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResNotifyTaskState {
|
||||||
|
TaskId task_id = 1;
|
||||||
|
TaskAttr task_attr = 2;
|
||||||
|
TaskState state = 3;
|
||||||
|
TaskParam param = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTask {
|
||||||
|
// oneof param
|
||||||
|
TaskId task_id = 1;
|
||||||
|
ReqStartMakeFitsThumb req_make_fits_thumb_param = 2;
|
||||||
|
ReqStartRepostprocess req_repostprocess_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTask {
|
||||||
|
TaskId task_id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResTaskCenter {
|
||||||
|
int32 code = 1;
|
||||||
|
TaskId task_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientParams {
|
||||||
|
int32 encode_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqEnterCamera {
|
||||||
|
ClientParams client_param = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResEnterCamera {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_mode_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchShootingMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSwitchShootingMode {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_mode_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqSwitchShootingTech {
|
||||||
|
int32 tech = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResSwitchShootingTech {
|
||||||
|
int32 code = 1;
|
||||||
|
int32 shooting_tech_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqGetDeviceStateInfo {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveCameraState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.CaptureRawState capture_raw_state = 1;
|
||||||
|
notify.PhotoState photo_state = 2;
|
||||||
|
notify.BurstState burst_state = 3;
|
||||||
|
notify.RecordState record_state = 4;
|
||||||
|
notify.TimeLapseState timelapse_state = 5;
|
||||||
|
notify.CaptureCaliFrameState capture_cali_frame_state = 6;
|
||||||
|
notify.PanoramaState panorama_state = 7;
|
||||||
|
notify.SentryState sentry_state = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TeleCameraStateInfo {
|
||||||
|
// oneof _cmos_temperature
|
||||||
|
ExclusiveCameraState exclusive_state = 1;
|
||||||
|
notify.StreamType stream_type = 2;
|
||||||
|
double h_fov = 3;
|
||||||
|
double v_fov = 4;
|
||||||
|
uint32 resolution_width = 5;
|
||||||
|
uint32 resolution_height = 6;
|
||||||
|
notify.CmosTemperature cmos_temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WideCameraStateInfo {
|
||||||
|
// oneof _cmos_temperature
|
||||||
|
ExclusiveCameraState exclusive_state = 1;
|
||||||
|
notify.StreamType stream_type = 2;
|
||||||
|
double h_fov = 3;
|
||||||
|
double v_fov = 4;
|
||||||
|
uint32 resolution_width = 5;
|
||||||
|
uint32 resolution_height = 6;
|
||||||
|
notify.CmosTemperature cmos_temperature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveFocusMotorState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.AstroAutoFocusState astro_auto_focus_state = 1;
|
||||||
|
notify.NormalAutoFocusState normal_auto_focus_state = 2;
|
||||||
|
notify.AstroAutoFocusFastState astro_auto_focus_fast_state = 3;
|
||||||
|
notify.AreaAutoFocusState area_auto_focus_state = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FocusMotorStateInfo {
|
||||||
|
// oneof _focus_position
|
||||||
|
ExclusiveFocusMotorState exclusive_state = 1;
|
||||||
|
notify.FocusPosition focus_position = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExclusiveMotionMotorState {
|
||||||
|
// oneof current_state
|
||||||
|
notify.AstroCalibrationState astro_calibration_state = 1;
|
||||||
|
notify.AstroGotoState astro_goto_state = 2;
|
||||||
|
notify.AstroTrackingState astro_tracking_state = 3;
|
||||||
|
notify.NormalTrackState normal_track_state = 4;
|
||||||
|
notify.OneClickGotoState one_click_goto_state = 5;
|
||||||
|
notify.EqSolvingState eq_state = 6;
|
||||||
|
notify.SentryState sentry_state = 7;
|
||||||
|
notify.SkyTargetFinderState sky_target_finder_state = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message MotionMotorStateInfo {
|
||||||
|
ExclusiveMotionMotorState exclusive_state = 1;
|
||||||
|
notify.SentryAutoHand sentry_auto_hand = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeviceStateInfo {
|
||||||
|
notify.RgbState rgb_state = 1;
|
||||||
|
notify.PowerIndState power_ind_state = 2;
|
||||||
|
notify.ChargingState charging_state = 3;
|
||||||
|
notify.StorageInfo storage_info = 4;
|
||||||
|
notify.MTPState mtp_state = 5;
|
||||||
|
notify.CPUMode cpu_mode = 6;
|
||||||
|
notify.Temperature temperature = 7;
|
||||||
|
notify.BodyStatus body_status = 8;
|
||||||
|
notify.BatteryInfo battery_info = 9;
|
||||||
|
notify.CalibrationResult calibration_result = 10;
|
||||||
|
notify.PictureMatching picture_matching = 11;
|
||||||
|
notify.AutoShutdown auto_shutdown = 12;
|
||||||
|
notify.LensDefog lens_defog = 13;
|
||||||
|
notify.AutoCooling auto_cooling = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ConnectionStateInfo {
|
||||||
|
notify.HostSlaveMode host_slave_mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ShootingModeAndTech {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
int32 parent_shooting_mode = 2;
|
||||||
|
repeated int32 shooting_techs = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResGetDeviceStateInfo {
|
||||||
|
int32 shooting_mode = 1;
|
||||||
|
TeleCameraStateInfo tele_camera_state_info = 2;
|
||||||
|
WideCameraStateInfo wide_camera_state_info = 3;
|
||||||
|
FocusMotorStateInfo focus_motor_state_info = 4;
|
||||||
|
MotionMotorStateInfo motion_motor_state_info = 5;
|
||||||
|
DeviceStateInfo device_state_info = 6;
|
||||||
|
int32 code = 7;
|
||||||
|
ConnectionStateInfo connection_state_info = 8;
|
||||||
|
repeated ShootingModeAndTech shooting_mode_and_techs = 9;
|
||||||
|
}
|
||||||
|
|
||||||
40
dwarfctl/proto/track.proto
Normal file
40
dwarfctl/proto/track.proto
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
message ReqStartTrack {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 w = 3;
|
||||||
|
int32 h = 4;
|
||||||
|
int32 cam_id = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqPauseTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqContinueTrack {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartSentryMode {
|
||||||
|
int32 type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStopSentryMode {
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqMOTTrackOne {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqUFOAutoHandMode {
|
||||||
|
int32 mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqStartTrackClick {
|
||||||
|
int32 x = 1;
|
||||||
|
int32 y = 2;
|
||||||
|
int32 cam_id = 3;
|
||||||
|
}
|
||||||
|
|
||||||
139
dwarfctl/proto/voiceassistant.proto
Normal file
139
dwarfctl/proto/voiceassistant.proto
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option go_package = "github.com/antitbone/dwarfctl/proto;pb";
|
||||||
|
import "base.proto";
|
||||||
|
import "notify.proto";
|
||||||
|
import "task_center.proto";
|
||||||
|
|
||||||
|
enum VoiceCommandType {
|
||||||
|
VOICE_CMD_UNKNOWN = 0;
|
||||||
|
VOICE_CMD_GET_STATUS = 1;
|
||||||
|
VOICE_CMD_TAKE_PHOTO = 2;
|
||||||
|
VOICE_CMD_START_RECORD = 3;
|
||||||
|
VOICE_CMD_STOP_RECORD = 4;
|
||||||
|
VOICE_CMD_START_TIMELAPSE = 5;
|
||||||
|
VOICE_CMD_STOP_TIMELAPSE = 6;
|
||||||
|
VOICE_CMD_START_BURST = 7;
|
||||||
|
VOICE_CMD_STOP_BURST = 8;
|
||||||
|
VOICE_CMD_START_ASTRO = 9;
|
||||||
|
VOICE_CMD_STOP_ASTRO = 10;
|
||||||
|
VOICE_CMD_START_SENTRY = 11;
|
||||||
|
VOICE_CMD_STOP_SENTRY = 12;
|
||||||
|
VOICE_CMD_MOVE = 13;
|
||||||
|
VOICE_CMD_GOTO_TARGET = 14;
|
||||||
|
VOICE_CMD_CALIBRATION = 15;
|
||||||
|
VOICE_CMD_AUTO_FOCUS = 16;
|
||||||
|
VOICE_CMD_STOP_FOCUS = 17;
|
||||||
|
VOICE_CMD_STOP_ALL = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReqVoiceCommand {
|
||||||
|
// oneof params
|
||||||
|
VoiceCommandType command_type = 1;
|
||||||
|
int32 shooting_mode = 2;
|
||||||
|
VoicePhotoParams photo_params = 10;
|
||||||
|
VoiceRecordParams record_params = 11;
|
||||||
|
VoiceTimelapseParams timelapse_params = 12;
|
||||||
|
VoiceBurstParams burst_params = 13;
|
||||||
|
VoiceAstroParams astro_params = 14;
|
||||||
|
VoiceSentryParams sentry_params = 15;
|
||||||
|
VoiceMoveParams move_params = 16;
|
||||||
|
VoiceGotoParams goto_params = 17;
|
||||||
|
VoiceCalibrationParams calibration_params = 18;
|
||||||
|
VoiceFocusParams focus_params = 19;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoicePhotoParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceRecordParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 duration_seconds = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceTimelapseParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 interval_seconds = 2;
|
||||||
|
int32 duration_seconds = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceBurstParams {
|
||||||
|
int32 camera_type = 1;
|
||||||
|
int32 count = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceAstroParams {
|
||||||
|
string target_name = 1;
|
||||||
|
double ra = 2;
|
||||||
|
double dec = 3;
|
||||||
|
int32 index = 4;
|
||||||
|
double lon = 5;
|
||||||
|
double lat = 6;
|
||||||
|
bool auto_goto = 7;
|
||||||
|
bool force_start = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceSentryParams {
|
||||||
|
int32 type = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceMoveParams {
|
||||||
|
double azimuth_angle = 1;
|
||||||
|
double altitude_angle = 2;
|
||||||
|
int32 speed = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceGotoParams {
|
||||||
|
string target_name = 1;
|
||||||
|
double ra = 2;
|
||||||
|
double dec = 3;
|
||||||
|
int32 index = 4;
|
||||||
|
double lon = 5;
|
||||||
|
double lat = 6;
|
||||||
|
int32 shooting_mode = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceCalibrationParams {
|
||||||
|
double lon = 1;
|
||||||
|
double lat = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceFocusParams {
|
||||||
|
bool is_infinity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResVoiceCommand {
|
||||||
|
// oneof result
|
||||||
|
int32 code = 1;
|
||||||
|
string message = 2;
|
||||||
|
VoiceCommandType command_type = 3;
|
||||||
|
VoiceStatusResult status_result = 10;
|
||||||
|
VoiceOperationResult operation_result = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AstroShootingProgress {
|
||||||
|
string target_name = 1;
|
||||||
|
int32 captured_count = 2;
|
||||||
|
int32 total_count = 3;
|
||||||
|
int32 stacked_count = 4;
|
||||||
|
int32 progress_percentage = 5;
|
||||||
|
int64 elapsed_time = 6;
|
||||||
|
int64 remaining_time = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceStatusResult {
|
||||||
|
ResGetDeviceStateInfo device_state_info = 1;
|
||||||
|
AstroShootingProgress astro_progress = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message VoiceOperationResult {
|
||||||
|
bool success = 1;
|
||||||
|
string detail_message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ResNotifyVoiceAssistant {
|
||||||
|
VoiceCommandType command_type = 1;
|
||||||
|
notify.OperationState state = 2;
|
||||||
|
string message = 4;
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user