Plan P5: a value bubble on the pitch slider while dragging, press-and-drag on the video as a speed joystick (re-sent at 10 Hz, zero on release), and a gimbal settings sheet: mode, 30° extension, yaw follow, recenter / face down / yaw recenter, roll fine-tune, auto calibration and advanced speed/smoothness rows gated by the gimbal's capability ranges. GimbalBridge reports mode, trim, calibration and stop/overload state in the gimbal telemetry group, and getter-only settings in a new gimbalSettings slow group. The reported-plus-pending overlay moves out of CameraState into a SettingsOverlay mixin shared by camera and gimbal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
142 lines
5.1 KiB
Dart
142 lines
5.1 KiB
Dart
/// Synthetic `productProfile` events, shaped exactly as `ProductProfileBridge.kt`
|
||
/// emits them, for the three reference products of plan P0.
|
||
library;
|
||
|
||
Map<String, dynamic> _camera({
|
||
String name = 'FC1102',
|
||
bool aperture = false,
|
||
bool ssd = false,
|
||
bool zoom = false,
|
||
bool hybridZoom = false,
|
||
List<String> apertures = const <String>[],
|
||
}) =>
|
||
<String, dynamic>{
|
||
'index': 0,
|
||
'displayName': name,
|
||
'isThermal': false,
|
||
'ssdSupported': ssd,
|
||
'opticalZoomSupported': zoom,
|
||
'hybridZoomSupported': hybridZoom,
|
||
'digitalZoomSupported': false,
|
||
'adjustableApertureSupported': aperture,
|
||
'adjustableFocalPointSupported': aperture,
|
||
'meteringSupported': true,
|
||
'playbackSupported': true,
|
||
'mediaDownloadSupported': true,
|
||
'modes': <String>['SHOOT_PHOTO', 'RECORD_VIDEO'],
|
||
'exposureModes': <String>['PROGRAM', 'MANUAL'],
|
||
'isos': <String>['AUTO', '100', '200', '400', '800', '1600'],
|
||
'shutterSpeeds': <String>['1/8000', '1/1000', '1/100', '1/30'],
|
||
'apertures': apertures,
|
||
'exposureCompensations': <String>['-3.0', '0.0', '+3.0'],
|
||
'videoResolutions': <String>[
|
||
'RESOLUTION_3840x2160@FRAME_RATE_29_DOT_970_FPS',
|
||
'RESOLUTION_1920x1080@FRAME_RATE_59_DOT_940_FPS',
|
||
],
|
||
'photoModes': <String>['SINGLE', 'HDR', 'BURST', 'AEB', 'INTERVAL'],
|
||
'whiteBalancePresets': <String>['AUTO', 'SUNNY', 'CLOUDY', 'CUSTOM'],
|
||
'videoStandards': <String>['NTSC', 'PAL'],
|
||
'colors': <String>['NONE', 'D_LOG'],
|
||
};
|
||
|
||
Map<String, dynamic> _gimbal({bool yaw = false, double pitchMax = 0, bool tuning = false}) => <String, dynamic>{
|
||
'index': 0,
|
||
'capabilitiesKnown': true,
|
||
'pitch': <String, dynamic>{'min': -90.0, 'max': pitchMax},
|
||
'yaw': yaw ? <String, dynamic>{'min': -320.0, 'max': 320.0} : null,
|
||
'roll': null,
|
||
'pitchAdjustable': true,
|
||
'yawAdjustable': yaw,
|
||
'rollAdjustable': false,
|
||
'pitchRangeExtensionSupported': pitchMax > 0,
|
||
'controller': tuning
|
||
? <String, dynamic>{
|
||
'pitchMaxSpeed': <String, dynamic>{'min': 1.0, 'max': 100.0},
|
||
'pitchSmoothing': <String, dynamic>{'min': 0.0, 'max': 30.0},
|
||
'yawMaxSpeed': <String, dynamic>{'min': 1.0, 'max': 100.0},
|
||
}
|
||
: <String, dynamic>{},
|
||
};
|
||
|
||
Map<String, dynamic> _fc({bool assistant = true, bool sticks = true}) => <String, dynamic>{
|
||
'flightAssistantSupported': assistant,
|
||
'virtualStickAvailable': sticks,
|
||
'rtkSupported': false,
|
||
'compassCount': 1,
|
||
'imuCount': 1,
|
||
'simulatorAvailable': true,
|
||
};
|
||
|
||
/// Spark over Wi-Fi with no RC: no remote controller component, link reported
|
||
/// as Wi-Fi, one smart battery.
|
||
final Map<String, dynamic> sparkWifi = <String, dynamic>{
|
||
'type': 'productProfile',
|
||
'connected': true,
|
||
'model': 'Spark',
|
||
'modelDisplayName': 'Spark',
|
||
'productKind': 'aircraft',
|
||
'cameras': <dynamic>[_camera(name: 'FC1102')],
|
||
'gimbals': <dynamic>[_gimbal()],
|
||
'link': 'wifi',
|
||
'flightController': _fc(),
|
||
'remoteController': null,
|
||
'batteries': <dynamic>[
|
||
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 3},
|
||
],
|
||
};
|
||
|
||
/// Phantom 4 on Lightbridge, gimbal pitch extendable to +30°.
|
||
final Map<String, dynamic> phantom4 = <String, dynamic>{
|
||
'type': 'productProfile',
|
||
'connected': true,
|
||
'model': 'PHANTOM_4',
|
||
'modelDisplayName': 'Phantom 4',
|
||
'productKind': 'aircraft',
|
||
'cameras': <dynamic>[_camera(name: 'FC330')],
|
||
'gimbals': <dynamic>[_gimbal(pitchMax: 30)],
|
||
'link': 'lightbridge',
|
||
'flightController': _fc(),
|
||
'remoteController': <String, dynamic>{'masterSlaveSupported': false},
|
||
'batteries': <dynamic>[
|
||
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 4},
|
||
],
|
||
};
|
||
|
||
/// Inspire 2 with a Zenmuse X5S: dual batteries, SSD, adjustable aperture,
|
||
/// 3-axis gimbal with yaw, master/slave RC.
|
||
final Map<String, dynamic> inspire2X5s = <String, dynamic>{
|
||
'type': 'productProfile',
|
||
'connected': true,
|
||
'model': 'INSPIRE_2',
|
||
'modelDisplayName': 'Inspire 2',
|
||
'productKind': 'aircraft',
|
||
'cameras': <dynamic>[
|
||
_camera(name: 'Zenmuse X5S', aperture: true, ssd: true, apertures: <String>['f/1.7', 'f/2.8', 'f/5.6', 'f/16']),
|
||
],
|
||
'gimbals': <dynamic>[_gimbal(yaw: true, pitchMax: 30, tuning: true)],
|
||
'link': 'lightbridge',
|
||
'flightController': _fc(),
|
||
'remoteController': <String, dynamic>{'masterSlaveSupported': true},
|
||
'batteries': <dynamic>[
|
||
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 6},
|
||
<String, dynamic>{'index': 1, 'isSmart': true, 'cells': 6},
|
||
],
|
||
};
|
||
|
||
/// Mavic 2 Zoom: hybrid zoom (optical 24–48 mm, then digital), fixed aperture.
|
||
final Map<String, dynamic> mavic2Zoom = <String, dynamic>{
|
||
'type': 'productProfile',
|
||
'connected': true,
|
||
'model': 'MAVIC_2_ZOOM',
|
||
'modelDisplayName': 'Mavic 2 Zoom',
|
||
'productKind': 'aircraft',
|
||
'cameras': <dynamic>[_camera(name: 'FC2204', zoom: true, hybridZoom: true)],
|
||
'gimbals': <dynamic>[_gimbal()],
|
||
'link': 'ocusync',
|
||
'flightController': _fc(),
|
||
'remoteController': <String, dynamic>{'masterSlaveSupported': false},
|
||
'batteries': <dynamic>[
|
||
<String, dynamic>{'index': 0, 'isSmart': true, 'cells': 4},
|
||
],
|
||
};
|