diff --git a/Fly App/android/app/src/main/kotlin/com/dji/flutter/dji_msdk_sample/DjiSdkBridge.kt b/Fly App/android/app/src/main/kotlin/com/dji/flutter/dji_msdk_sample/DjiSdkBridge.kt index d21d6a8..8b25187 100644 --- a/Fly App/android/app/src/main/kotlin/com/dji/flutter/dji_msdk_sample/DjiSdkBridge.kt +++ b/Fly App/android/app/src/main/kotlin/com/dji/flutter/dji_msdk_sample/DjiSdkBridge.kt @@ -38,9 +38,15 @@ class DjiSdkBridge( private const val METHOD_CHANNEL = "dji_msdk/methods" private const val EVENT_CHANNEL = "dji_msdk/events" - /** Serial/firmware polling: the SDK reports null until it has talked to the aircraft. */ + /** + * Serial/firmware polling: the SDK reports null until it has talked to the + * aircraft. The serial lands within seconds; the firmware package version can + * take far longer (a Mavic Pro was still null after a minute), so this window + * is a best-effort head start, not a guarantee — whenever it expires first, the + * next `connection` event still carries the version through [connectionMap]. + */ private const val IDENTITY_RETRY_MS = 2_000L - private const val IDENTITY_MAX_ATTEMPTS = 6 + private const val IDENTITY_MAX_ATTEMPTS = 30 } private val mainHandler = Handler(Looper.getMainLooper()) @@ -230,8 +236,10 @@ class DjiSdkBridge( * Neither is readable the instant a product connects — `getFirmwarePackageVersion` * returns null and the flight controller's callbacks fail until the SDK has * finished handshaking — so this re-checks every [IDENTITY_RETRY_MS] until both - * are known or [IDENTITY_MAX_ATTEMPTS] is reached. Each resolved value is emitted - * as it arrives, so the UI fills in the serial even if firmware never resolves. + * are known or [IDENTITY_MAX_ATTEMPTS] is reached. Each value is emitted as it + * arrives and the two resolve on very different timescales: the serial lands in + * seconds, while the firmware may outlast the whole window (see the constants). + * The UI shows the serial regardless, and firmware stays blank rather than wrong. * * [generation] guards against overlapping chains: a product change or disconnect * bumps [identityGeneration], stranding any retry still queued for the old product. @@ -262,18 +270,12 @@ class DjiSdkBridge( override fun onFailure(error: DJIError?) = Unit }) } - // Component-level firmware is the fallback when the product-level package - // version stays null (some aircraft only report the former). - if (firmwareVersion == null) { - controller.getFirmwareVersion(object : CommonCallbacks.CompletionCallbackWith { - override fun onSuccess(value: String?) { - if (value.isNullOrBlank()) return - mainHandler.post { setFirmware(generation, value) } - } - - override fun onFailure(error: DJIError?) = Unit - }) - } + // Deliberately NOT falling back to controller.getFirmwareVersion(): a + // component reports its own firmware, which is a different quantity from + // the aircraft's. On a Mavic Pro the flight controller says 01.03.0800 + // where the aircraft is 03.02.35.05, so using it as a stand-in publishes a + // wrong version and pre-empts the real one (seen live). The package version + // is the only source for this field — leave it blank until it is readable. } if ((serialNumber == null || firmwareVersion == null) && attempt + 1 < IDENTITY_MAX_ATTEMPTS) { @@ -281,6 +283,7 @@ class DjiSdkBridge( } } + /** Publishes the product-level package version — the aircraft firmware. */ private fun setFirmware(generation: Int, value: String) { if (generation != identityGeneration || firmwareVersion == value) return firmwareVersion = value