Files
PilotVault/Fly Agent App/README.md
T
tajniak81andClaude Opus 5.5 3dd31b257a Add the Fly Agent App, a Remote ID companion to DJI Fly
A Flutter app that runs next to DJI Fly without the DJI SDK. It receives the
aircraft's Remote ID (Bluetooth, BT5, Wi-Fi NaN and Beacon) in a foreground
service, streams the paired aircraft to the hub over /ws/device, and turns
take-off to landing into a logbook entry filed through /api/flights, queued
when offline. Covers phases A0-A3 of the Fly Agent plan; needs no server change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 19:25:52 +02:00

65 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PilotVault Fly Agent
Android companion app that runs **next to DJI Fly**. DJI Fly flies the aircraft;
the Agent listens to the aircraft's **Remote ID** broadcast, streams the paired
aircraft's position to PilotVault, and files the flight in the logbook. It uses
no DJI SDK and never sends a command, so it works with every DJI Fly aircraft
(Mavic 4 Pro, Air 3S, Mini 5 Pro, …) as long as Remote ID is broadcasting.
Plan and research: `REA/DJI Fly/PilotVault_FlyAgentApp_Plan.md` (outside this repo).
Built so far: phases **A0–A3** (login, Remote ID receiver, live uplink, flight
session → logbook). Not yet: RTMP video (A4), flight-record import (A5), media
metadata (A6), missions to DJI Fly (A7).
## Build
```bash
flutter build apk --debug
```
`build/app/outputs/flutter-apk/app-debug.apk`, package `com.pilotvault.flyagent`.
- `permission_handler` is pinned to 12.x: 13.x needs compileSdk 37.
- `kotlin.incremental=false` in `android/gradle.properties`: the project and the
pub cache are on different drives, which breaks Kotlin's incremental caches.
## How it fits
| Piece | Where |
|---|---|
| Remote ID scanners (BLE legacy + BT5, Wi-Fi NaN, Wi-Fi Beacon) in a foreground service | `android/.../flyagent/*.kt` |
| OpenDroneID decoder (ASTM F3411 / EN 4709-002) | `lib/rid/odid_decoder.dart` |
| Frames → aircraft (merged by serial across transports), pairing | `lib/rid/rid_aircraft.dart`, `rid_service.dart` |
| Live uplink to the hub, `/ws/device?id=agent-<serial>` | `lib/uplink/uplink.dart` |
| Session state machine (armed → active → landed), auto start/stop | `lib/session/flight_session.dart` |
| Filing to `POST /api/flights`, offline queue | `lib/session/session_controller.dart` |
The scanners only strip transport framing; all decoding is in Dart and unit
tested against byte-built messages (`test/`).
**API Server contract.** No server changes were needed:
- Live map: the hub already ingests `telemetry` events (`latitude`, `longitude`,
`altitude` = height above take-off, `velocityX/Y/Z` = north/east/down,
`isFlying`, `phoneLatitude/Longitude`). The Agent adds `source: "remote-id"`,
`ridSerial`, `pilotLatitude/Longitude`, `uaClass`, which ride along in the raw
event. It never sends `flightControllerSerial`, so the Web App's fleet
auto-add does not mint a drone from a Remote ID serial.
- Logbook: entries are filed with `loggingPath: "manual"` and every § 5 manual
field filled from the session (Remote ID is not the aircraft's own flight
recorder, so "automatic" would be a false claim). `logging_path` only allows
`automatic | manual`, so the plan's `"companion"` value would need a migration.
- Pairing lives on the phone (SharedPreferences), not on the drone record; a
`remote_id_serial` drone field is a later server change.
**Privacy.** Every aircraft in range is decoded, but only the paired one is
uploaded or logged. Other operators' broadcasts stay in memory on the phone.
## Limits worth knowing
- Wi-Fi Beacon Remote ID needs Android 11+ and Android throttles Wi-Fi scans to
4 per 2 minutes (turn off "Wi-Fi scan throttling" in Developer options).
An aircraft that only broadcasts over Beacon updates every ~30 s.
- Not yet checked on a real aircraft: which transport each DJI Fly aircraft uses
(research R1), and NaN on the SHT-AL09 tablet (Android 9: no Beacon IEs).