# DWARF Device Models — Feature Matrix

Reverse-engineered from `DeviceType.java` and `CameraFeatureGate.java` in
`DWARFLAB.apk` v3.4.0.

The APK knows **6 device models**. The `DeviceType` enum uses `WhenMappings`
to dispatch per-model behavior. Mapping values (used in switch statements):

| `WhenMappings` value | DeviceType     | deviceId |
|----------------------|----------------|----------|
| 1                    | **DWARF_MINI** | 4        |
| 2                    | DWARF_2        | 1        |
| 3                    | DWARF_3        | 2        |
| 4                    | DWARF_4        | 5        |
| 5                    | DWARF_DRAGON   | 6        |
| 6                    | Unknown        | 0        |

## Feature support by model

| Feature                    | MINI | DWARF_2 | DWARF_3 | DWARF_4 | DRAGON |
|----------------------------|:----:|:-------:|:-------:|:-------:|:------:|
| `isSupportAdvancedSettings`  | ✅ | ❌ | ❌ | ❌ | ❌ |
| `isSupportAutoShutdownSetting` | ❌ | ✅ | ✅ | ✅ | ✅ |
| `isSupportNfc`              | ❌ | ✅ | ✅ | ✅ | ✅ |
| `isSupportNormalTrack`      | ✅ | ✅ | ❌ | ❌ | ❌ |
| `isSupportPanoramaCreate`   | ❌ | ✅ | ❌ | ✅ | ✅ |
| `isSupportWideNormalTrack`  | ❌ | ✅ | ❌ | ❌ | ❌ |

**Key DWARF_MINI differences:**
- **No NFC**, **no auto-shutdown setting** — the Mini is the stripped-down model.
- **Only model with Advanced Settings** enabled (probably lens-defog / cooling).
- **Normal Track supported** (single-tap tracking on main camera).
- **No Wide Normal Track** (the wide camera cannot track).
- **No panorama create** (cannot start a panorama grid scan from the app).

## Field of View (degrees)

### Tele camera — `getTeleFovInfo` (precise, used for computations)

| Model       | Horizontal | Vertical |
|-------------|-----------|----------|
| DWARF_MINI  | 3.188     | 1.794    |
| DWARF_2     | 2.95      | 1.66     |
| DWARF_3     | 2.14      | 1.2      |
| DWARF_4     | 2.95      | 1.66     |
| DWARF_DRAGON| 2.95      | 1.66     |

### Tele camera — `getTeleFov` (display rounded)

| Model       | Horizontal | Vertical |
|-------------|-----------|----------|
| DWARF_MINI  | 8.0       | 6.5      |
| DWARF_2     | 7.4       | 6.0      |
| DWARF_3     | 5.37      | 4.3      |
| DWARF_4     | 4.8       | 3.8      |
| DWARF_DRAGON| 7.4       | 6.0      |

### Wide camera — `getWideFov`

| Model       | Horizontal | Vertical |
|-------------|-----------|----------|
| DWARF_MINI  | **8.0**   | **6.5**  |
| DWARF_2     | 83.43     | 51.9     |
| DWARF_3     | 83.43     | 51.9     |
| DWARF_4     | 130.0     | 86.5     |
| DWARF_DRAGON| 7.4       | 6.0      |

**Note:** DWARF_MINI has identical tele and wide FoV (8.0×6.5 display,
3.188×1.794 precise) — this strongly suggests the Mini has **a single camera
sensor** (or two identical sensors), unlike the dual-cam design of the
DWARF_2/3/4. The DWARF_DRAGON similarly has a narrow wide camera (7.4×6.0).

## Live observation vs APK data

The connected device reports via `GetDeviceState`:
- Tele: h_fov=2.140, v_fov=1.200, 1920×1080
- Wide: h_fov=42.650, v_fov=24.450, 1920×1080

This **matches DWARF_3** (getTeleFovInfo: 2.14×1.2), not DWARF_MINI
(3.188×1.794). The `h_fov`/`v_fov` reported by the firmware in
`tele_camera_state_info` reflects the **physical sensor FoV at current zoom**,
which can differ from the app's display values. The wide value (42.65×24.45)
is roughly half of DWARF_3's 83.43×51.9, suggesting the live stream is at
~2× digital zoom.

**Conclusion:** the user reports a DWARF Mini, but the firmware advertises
DWARF_3 FoV values. The Mini likely shares optics/sensor with the DWARF_3
and is differentiated by feature gating (NFC, panorama, auto-shutdown) and
industrial design rather than optics. Verify the actual `device_id` reported
by BLE (`DwarfEcho.model.family/revision`) to confirm.

## Other per-model data

- `getDeviceNameLength` — max characters for the device name (per model).
- `getEqModelUrl` — URL to the 3D EQ-alignment helper (`assets/www/modules/eq/`).
  "Bilbo" index is used for the next-gen model.
- `getImgHomeConnectedDevice` / `getImgConnectingDevice` / `getUnconnectedLottieResId` —
  app illustrations/animations per model.
- `isNorth` / `getEqHemisphereInstruction` — EQ alignment instructions differ
  by hemisphere (Northern/Southern).

## CaptureActivity Mini-specific behavior

At line 8905 of `CaptureActivity.java`:
```java
boolean z4 = num != null && num.intValue() == DeviceType.DWARF_MINI.getDeviceId();
```
This flag is checked when starting a **Moon GoTo** — the Mini (and DWARF_3/4/DRAGON)
gets a confirmation dialog that the DWARF_2 does not, because only the DWARF_2
supports the older sun/moon tracking flow without extra confirmation.

## Suggested implementation in dwarfctl

1. Add a `DeviceType` enum in Go matching the APK's ids (1=DWARF_2, 2=DWARF_3,
   4=MINI, 5=DWARF_4, 6=DRAGON).
2. Read `device_id` from `GetDeviceState` (field `shooting_mode` is NOT it —
   need to find the actual device-type field, likely from BLE handshake or a
   dedicated state field).
3. Gate features client-side: warn when attempting panorama on a Mini,
   hide auto-shutdown, etc.
4. Log the reported FoV in `health` output to help identify the model.
5. **Visual odometry calibration:** the Mini's wide-cam FoV is uncertain
   (8.0°×6.5° display vs 42.65°×24.45° live-reported — see above). When using
   `dwarfctl orient`, the pixel shift is always correct; to get accurate degree
   values, calibrate `--fov-h`/`--fov-v` by slewing a known motor angle.
