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
25 KiB
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.xmlis the main nav graph;startDestination = navigation_device(Home).HeartbeatEntryActivityis 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+ stringshome_3/4/5,camera_astro_69):tab id label (en) icon 1 navigation_deviceHome icon_function_tabbar_home2 navigation_atlasAtlas icon_function_tabbar_atlas3 navigation_albumAlbum icon_function_tabbar_album4 navigation_settingsSettings 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
HomeFragmentwhich shows a device-discovery / connect CTA when no scope is paired. - App upgrade available: shows
AppUpdateDialog(force-update path usesFirmwareForceUpdateDialog). - System notice:
AppNoticebanner.
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_disconnectedbackground 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
(
isDefaultPwdarg →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; showsitem_long_press_stoppill "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;isDefaultPwdflag) →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, contactsupport@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. FirmwareForceUpdateDialogblocks the app if firmware is too old for a required feature (e.g. astrophotography — seecamera_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 (Chinesevalues-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/envs/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)
- Screens to build first (MVP): Splash → Home (connect CTA) →
DeviceSearch (BLE) → DeviceConnect (password) → Capture (preview + shutter
- params + joystick) → Settings (My Device + Connection).
- 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. - Capture screen is the hard part — replicate the overlay z-order
(§5.7) and drive the capture button from
CaptureState. - Two preview surfaces (Tele main + Wide PIP) each need an RTSP
consumer; toggle PIP via
CMD_SWITCH_MAIN_PREVIEW(14809). - Keep the mode-driven visibility model: each
ShootingModeTypeflag (isWidePreviewOnly,isAstroFocus,isShowZoomLens…) controls which controls render — don't hardcode per-screen logic.