makcar/app/src/main/java/com/aros/apron/activity/MainActivity.kt

1294 lines
56 KiB
Kotlin
Raw Normal View History

2026-01-30 11:47:32 +08:00
package com.aros.apron.activity
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
import android.annotation.SuppressLint
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.View
import android.view.Window
import android.view.WindowManager
import android.widget.Button
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import com.aros.apron.R
import com.aros.apron.base.BaseActivity
import com.aros.apron.callback.MqttCallBack
import com.aros.apron.entity.Movement
2026-04-03 20:41:05 +08:00
import com.aros.apron.entity.Synchronizedstatus
2026-01-30 11:47:32 +08:00
import com.aros.apron.manager.AlternateLandingManager
import com.aros.apron.manager.BatteryManager
import com.aros.apron.manager.CameraManager
import com.aros.apron.manager.FlightManager
import com.aros.apron.manager.FlightManager.FLAG_DOWN_LAND
import com.aros.apron.manager.FlightManager.FLAG_START_DETECT_ARUCO_ALTERNATE
import com.aros.apron.manager.FlightManager.FLAG_START_DETECT_ARUCO_APRON
import com.aros.apron.manager.FlightManager.FLAG_STOP_ARUCO
import com.aros.apron.manager.FlightTaskProgressManager
import com.aros.apron.manager.GimbalManager
import com.aros.apron.manager.LEDsSettingsManager
import com.aros.apron.manager.LTEManager
import com.aros.apron.manager.MediaManager
import com.aros.apron.manager.MissionV3Manager
2026-04-03 20:41:05 +08:00
import com.aros.apron.manager.NavigationSatelliteSystemManager
2026-01-30 11:47:32 +08:00
import com.aros.apron.manager.OSDManager
2026-04-08 13:39:51 +08:00
import com.aros.apron.manager.PayloadWidgetManager
2026-04-03 20:41:05 +08:00
import com.aros.apron.manager.RTKManager
2026-04-08 13:43:50 +08:00
import com.aros.apron.manager.SpeakerManager
2026-01-30 11:47:32 +08:00
import com.aros.apron.manager.StickManager
import com.aros.apron.manager.StreamManager
import com.aros.apron.manager.WirelessLinkManager
2026-04-08 13:43:50 +08:00
import com.aros.apron.mix.Aprondown
import com.aros.apron.mix.Aprongim
2026-01-30 11:47:32 +08:00
import com.aros.apron.tools.AlternateArucoDetect
import com.aros.apron.tools.ApronArucoDetect
2026-04-03 20:41:05 +08:00
import com.aros.apron.tools.ApronArucoDetectPort
2026-01-30 11:47:32 +08:00
import com.aros.apron.tools.DroneHelper
import com.aros.apron.tools.LogUtil
import com.aros.apron.tools.MqttManager
import com.aros.apron.tools.PreferenceUtils
2026-03-12 14:57:34 +08:00
import com.aros.apron.tools.SimplePortScanner
2026-01-30 11:47:32 +08:00
import com.dji.wpmzsdk.manager.WPMZManager
import com.google.gson.Gson
2026-04-03 20:41:05 +08:00
import dji.sdk.keyvalue.key.CameraKey
2026-01-30 11:47:32 +08:00
import dji.sdk.keyvalue.key.DJIKey
import dji.sdk.keyvalue.key.FlightControllerKey
import dji.sdk.keyvalue.key.KeyTools
2026-04-25 15:36:59 +08:00
import dji.sdk.keyvalue.value.camera.CameraMode
2026-01-30 11:47:32 +08:00
import dji.sdk.keyvalue.value.common.CameraLensType
import dji.sdk.keyvalue.value.common.ComponentIndexType
import dji.sdk.keyvalue.value.common.EmptyMsg
2026-02-01 14:34:23 +08:00
import dji.sdk.keyvalue.value.flightassistant.VisionAssistDirection
2026-03-04 11:20:07 +08:00
import dji.sdk.keyvalue.value.flightcontroller.LEDsSettings
2026-01-30 11:47:32 +08:00
import dji.v5.common.callback.CommonCallbacks
import dji.v5.common.callback.CommonCallbacks.CompletionCallback
2026-01-30 11:47:32 +08:00
import dji.v5.common.error.IDJIError
import dji.v5.common.utils.GeoidManager
import dji.v5.manager.KeyManager
import dji.v5.manager.datacenter.MediaDataCenter
import dji.v5.manager.interfaces.ICameraStreamManager
import dji.v5.manager.interfaces.ICameraStreamManager.AvailableCameraUpdatedListener
import dji.v5.network.DJINetworkManager
import dji.v5.network.IDJINetworkStatusListener
import dji.v5.utils.common.JsonUtil
import dji.v5.utils.common.LogPath
import dji.v5.utils.common.LogUtils
import dji.v5.ux.accessory.RTKStartServiceHelper.startRtkService
import dji.v5.ux.cameracore.widget.autoexposurelock.AutoExposureLockWidget
import dji.v5.ux.cameracore.widget.cameracontrols.CameraControlsWidget
import dji.v5.ux.cameracore.widget.cameracontrols.lenscontrol.LensControlWidget
import dji.v5.ux.cameracore.widget.focusexposureswitch.FocusExposureSwitchWidget
import dji.v5.ux.cameracore.widget.focusmode.FocusModeWidget
import dji.v5.ux.cameracore.widget.fpvinteraction.FPVInteractionWidget
import dji.v5.ux.core.base.SchedulerProvider.io
import dji.v5.ux.core.base.SchedulerProvider.ui
import dji.v5.ux.core.communication.BroadcastValues
import dji.v5.ux.core.communication.GlobalPreferenceKeys
import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore
import dji.v5.ux.core.communication.UXKeys
import dji.v5.ux.core.extension.hide
import dji.v5.ux.core.extension.toggleVisibility
import dji.v5.ux.core.panel.systemstatus.SystemStatusListPanelWidget
import dji.v5.ux.core.panel.topbar.TopBarPanelWidget
import dji.v5.ux.core.util.CameraUtil
import dji.v5.ux.core.util.DataProcessor
import dji.v5.ux.core.util.ViewUtil
import dji.v5.ux.core.widget.fpv.FPVStreamSourceListener
import dji.v5.ux.core.widget.fpv.FPVWidget
import dji.v5.ux.core.widget.hsi.HorizontalSituationIndicatorWidget
import dji.v5.ux.core.widget.hsi.PrimaryFlightDisplayWidget
import dji.v5.ux.core.widget.setting.SettingWidget
import dji.v5.ux.gimbal.GimbalFineTuneWidget
import dji.v5.ux.training.simulatorcontrol.SimulatorControlWidget
import dji.v5.ux.training.simulatorcontrol.SimulatorControlWidget.UIState.VisibilityUpdated
import dji.v5.ux.visualcamera.CameraNDVIPanelWidget
import dji.v5.ux.visualcamera.CameraVisiblePanelWidget
import dji.v5.ux.visualcamera.zoom.FocalZoomWidget
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.functions.Consumer
import org.eclipse.paho.client.mqttv3.MqttException
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
2026-02-01 14:34:23 +08:00
import org.opencv.objdetect.Dictionary
import org.opencv.objdetect.Objdetect
2026-01-30 11:47:32 +08:00
import java.util.concurrent.TimeUnit
open class MainActivity : BaseActivity() {
companion object {
// 如果不需要改变 isAppStarted 的值,可以直接这样声明
var isAppStarted: Boolean = false
var streamReceive: Boolean = false
2026-04-03 20:41:05 +08:00
private var instance: MainActivity? = null
2026-01-30 11:47:32 +08:00
2026-04-03 20:41:05 +08:00
fun getInstance(): MainActivity? {
return instance
}
private var vtxHeartbeatHandler: Handler? = null
private var lastVtxFrameTime: Long = 0
private const val VTX_HEARTBEAT_TIMEOUT = 2000L // 3秒没有收到帧就认为图传异常
private var isVtxHeartbeatRunning = false
fun startVtxHeartbeat() {
if (isVtxHeartbeatRunning) return
isVtxHeartbeatRunning = true
lastVtxFrameTime = System.currentTimeMillis()
vtxHeartbeatHandler = Handler(Looper.getMainLooper())
vtxHeartbeatHandler?.post(object : Runnable {
override fun run() {
val currentTime = System.currentTimeMillis()
val timeSinceLastFrame = currentTime - lastVtxFrameTime
if (timeSinceLastFrame > VTX_HEARTBEAT_TIMEOUT) {
//LogUtil.log("MainActivity", "图传心跳超时设置图传状态为false")
Movement.getInstance().isVtx = false
}
if (isVtxHeartbeatRunning) {
vtxHeartbeatHandler?.postDelayed(this, 1000) // 每秒检查一次
}
}
})
}
fun stopVtxHeartbeat() {
isVtxHeartbeatRunning = false
vtxHeartbeatHandler?.removeCallbacksAndMessages(null)
vtxHeartbeatHandler = null
}
fun updateVtxHeartbeat() {
lastVtxFrameTime = System.currentTimeMillis()
}
2026-01-30 11:47:32 +08:00
}
protected var primaryFpvWidget: FPVWidget? = null
protected var fpvInteractionWidget: FPVInteractionWidget? = null
protected var secondaryFPVWidget: FPVWidget? = null
protected var systemStatusListPanelWidget: SystemStatusListPanelWidget? = null
protected var simulatorControlWidget: SimulatorControlWidget? = null
protected var lensControlWidget: LensControlWidget? = null
protected var autoExposureLockWidget: AutoExposureLockWidget? = null
protected var focusModeWidget: FocusModeWidget? = null
protected var focusExposureSwitchWidget: FocusExposureSwitchWidget? = null
protected var cameraControlsWidget: CameraControlsWidget? = null
protected var horizontalSituationIndicatorWidget: HorizontalSituationIndicatorWidget? = null
protected var pfvFlightDisplayWidget: PrimaryFlightDisplayWidget? = null
protected var ndviCameraPanel: CameraNDVIPanelWidget? = null
protected var visualCameraPanel: CameraVisiblePanelWidget? = null
protected var focalZoomWidget: FocalZoomWidget? = null
protected var settingWidget: SettingWidget? = null
protected var topBarPanel: TopBarPanelWidget? = null
protected var fpvParentView: ConstraintLayout? = null
2026-04-03 20:41:05 +08:00
2026-01-30 11:47:32 +08:00
private var mDrawerLayout: DrawerLayout? = null
private var gimbalAdjustDone: TextView? = null
private var btn_test: Button? = null
private var btn_test1: Button? = null
2026-03-12 14:57:34 +08:00
private var btn_test2: Button? = null
private var btn_test3: Button? = null
2026-01-30 11:47:32 +08:00
private var gimbalFineTuneWidget: GimbalFineTuneWidget? = null
private var lastDevicePosition = ComponentIndexType.UNKNOWN
private var lastLensType = CameraLensType.UNKNOWN
private var compositeDisposable: CompositeDisposable? = null
private val cameraSourceProcessor = DataProcessor.create(
CameraSource(
ComponentIndexType.UNKNOWN,
CameraLensType.UNKNOWN
)
)
private val networkStatusListener =
IDJINetworkStatusListener { isNetworkAvailable: Boolean ->
if (isNetworkAvailable) {
LogUtils.d(TAG, "isNetworkAvailable=" + true)
startRtkService(false)
}
}
private val availableCameraUpdatedListener: AvailableCameraUpdatedListener =
object : AvailableCameraUpdatedListener {
override fun onAvailableCameraUpdated(availableCameraList: List<ComponentIndexType>) {
2026-04-03 20:41:05 +08:00
runOnUiThread {
updateFPVWidgetSource(availableCameraList)
}
2026-01-30 11:47:32 +08:00
}
override fun onCameraStreamEnableUpdate(cameraStreamEnableMap: Map<ComponentIndexType, Boolean>) {
//
}
}
2026-03-12 14:57:34 +08:00
private var cameraManager: ICameraStreamManager =
MediaDataCenter.getInstance().cameraStreamManager
2026-01-30 11:47:32 +08:00
private var startArucoType = 0 //1执行机库二维码识别 2执行备降点二维码识别
private var dictionary: Dictionary? = null
override fun useEventBus(): Boolean {
return true
}
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
override fun onResume() {
super.onResume()
2026-03-04 11:20:07 +08:00
2026-02-01 14:34:23 +08:00
dictionary = Objdetect.getPredefinedDictionary(Objdetect.DICT_6X6_250)
2026-03-04 11:20:07 +08:00
2026-01-30 11:47:32 +08:00
compositeDisposable = CompositeDisposable()
2026-04-29 15:44:05 +08:00
// 延迟订阅 RxJava 流,避免在初始 layout 阶段触发大量 widget 更新导致 ANR
Handler(Looper.getMainLooper()).postDelayed({
if (compositeDisposable == null) return@postDelayed
compositeDisposable!!.add(
systemStatusListPanelWidget!!.closeButtonPressed()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { pressed: Boolean ->
if (pressed) {
systemStatusListPanelWidget!!.hide()
2026-01-30 11:47:32 +08:00
}
2026-04-29 15:44:05 +08:00
})
compositeDisposable!!.add(
simulatorControlWidget!!.getUIStateUpdates()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { simulatorControlWidgetState: SimulatorControlWidget.UIState? ->
if (simulatorControlWidgetState is VisibilityUpdated) {
if ((simulatorControlWidgetState as VisibilityUpdated).isVisible) {
hideOtherPanels(simulatorControlWidget!!)
}
}
})
compositeDisposable!!.add(
cameraSourceProcessor.toFlowable()
.observeOn(io())
.throttleLast(500, TimeUnit.MILLISECONDS)
.subscribeOn(io())
.subscribe(Consumer { result: CameraSource ->
runOnUiThread { onCameraSourceUpdated(result.devicePosition, result.lensType) }
})
)
compositeDisposable!!.add(
ObservableInMemoryKeyedStore.getInstance()
.addObserver(UXKeys.create(GlobalPreferenceKeys.GIMBAL_ADJUST_CLICKED))
.observeOn(ui())
.subscribe { broadcastValues: BroadcastValues? ->
isGimableAdjustClicked(
broadcastValues!!
)
})
}, 500)
2026-01-30 11:47:32 +08:00
ViewUtil.setKeepScreen(this, true)
}
override fun onPause() {
2026-04-29 15:44:05 +08:00
// 在后台线程 dispose RxJava 订阅,避免阻塞主线程导致 ANR
// DJI UX widget 的 unregisterReactions() 会同步清理 RxJava 队列,可能耗时很长
val disposable = compositeDisposable
if (disposable != null && !disposable.isDisposed) {
Thread {
try {
disposable.dispose()
} catch (e: Exception) {
LogUtil.log(TAG, "dispose compositeDisposable error: ${e.message}")
}
}.start()
2026-01-30 11:47:32 +08:00
compositeDisposable = null
}
super.onPause()
ViewUtil.setKeepScreen(this, false)
}
//endregion
2026-03-12 14:57:34 +08:00
private fun hideOtherPanels(widget: View?) {
2026-01-30 11:47:32 +08:00
val panels = arrayOf<View>(
simulatorControlWidget!!
)
for (panel in panels) {
if (widget !== panel) {
panel.visibility = View.GONE
}
}
}
private fun updateFPVWidgetSource(availableCameraList: List<ComponentIndexType>?) {
LogUtils.i(TAG, JsonUtil.toJson(availableCameraList))
if (availableCameraList == null) {
return
}
val cameraList = java.util.ArrayList(availableCameraList)
//没有数据
if (cameraList.isEmpty()) {
secondaryFPVWidget!!.visibility = View.GONE
return
}
//仅一路数据
if (cameraList.size == 1) {
primaryFpvWidget!!.updateVideoSource(availableCameraList[0])
secondaryFPVWidget!!.visibility = View.GONE
return
}
2026-04-03 20:41:05 +08:00
//大于两路数据ort1
val primarySource = getSuitableSource(cameraList, ComponentIndexType.PORT_1)
2026-01-30 11:47:32 +08:00
primaryFpvWidget!!.updateVideoSource(primarySource!!)
cameraList.remove(primarySource)
val secondarySource = getSuitableSource(cameraList, ComponentIndexType.FPV)
secondaryFPVWidget!!.updateVideoSource(secondarySource!!)
secondaryFPVWidget!!.visibility = View.VISIBLE
}
private fun getSuitableSource(
cameraList: List<ComponentIndexType>,
defaultSource: ComponentIndexType
): ComponentIndexType? {
if (cameraList.contains(ComponentIndexType.LEFT_OR_MAIN)) {
return ComponentIndexType.LEFT_OR_MAIN
} else if (cameraList.contains(ComponentIndexType.RIGHT)) {
return ComponentIndexType.RIGHT
} else if (cameraList.contains(ComponentIndexType.UP)) {
return ComponentIndexType.UP
} else if (cameraList.contains(ComponentIndexType.PORT_1)) {
return ComponentIndexType.PORT_1
} else if (cameraList.contains(ComponentIndexType.PORT_2)) {
return ComponentIndexType.PORT_2
} else if (cameraList.contains(ComponentIndexType.PORT_3)) {
return ComponentIndexType.PORT_3
} else if (cameraList.contains(ComponentIndexType.PORT_4)) {
return ComponentIndexType.PORT_4
} else if (cameraList.contains(ComponentIndexType.VISION_ASSIST)) {
return ComponentIndexType.VISION_ASSIST
}
return defaultSource
}
private fun onCameraSourceUpdated(
devicePosition: ComponentIndexType,
lensType: CameraLensType
) {
LogUtils.i(LogPath.SAMPLE, "onCameraSourceUpdated", devicePosition, lensType)
if (devicePosition == lastDevicePosition && lensType == lastLensType) {
return
}
lastDevicePosition = devicePosition
lastLensType = lensType
updateViewVisibility(devicePosition, lensType)
updateInteractionEnabled()
//如果无需使能或者显示的,也就没有必要切换了。
if (fpvInteractionWidget!!.isInteractionEnabled) {
fpvInteractionWidget!!.updateCameraSource(devicePosition, lensType)
}
if (lensControlWidget!!.visibility == View.VISIBLE) {
lensControlWidget!!.updateCameraSource(devicePosition, lensType)
}
if (ndviCameraPanel!!.visibility == View.VISIBLE) {
ndviCameraPanel!!.updateCameraSource(devicePosition, lensType)
}
if (visualCameraPanel!!.visibility == View.VISIBLE) {
visualCameraPanel!!.updateCameraSource(devicePosition, lensType)
}
if (autoExposureLockWidget!!.visibility == View.VISIBLE) {
autoExposureLockWidget!!.updateCameraSource(devicePosition, lensType)
}
if (focusModeWidget!!.visibility == View.VISIBLE) {
focusModeWidget!!.updateCameraSource(devicePosition, lensType)
}
if (focusExposureSwitchWidget!!.visibility == View.VISIBLE) {
focusExposureSwitchWidget!!.updateCameraSource(devicePosition, lensType)
}
if (cameraControlsWidget!!.visibility == View.VISIBLE) {
cameraControlsWidget!!.updateCameraSource(devicePosition, lensType)
}
if (focalZoomWidget!!.visibility == View.VISIBLE) {
focalZoomWidget!!.updateCameraSource(devicePosition, lensType)
}
if (horizontalSituationIndicatorWidget!!.visibility == View.VISIBLE) {
horizontalSituationIndicatorWidget!!.updateCameraSource(devicePosition, lensType)
}
}
2026-03-12 14:57:34 +08:00
private fun updateViewVisibility(
2026-01-30 11:47:32 +08:00
devicePosition: ComponentIndexType,
lensType: CameraLensType
) {
//只在fpv下显示
pfvFlightDisplayWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.VISIBLE else View.INVISIBLE
//fpv下不显示
lensControlWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
ndviCameraPanel!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
visualCameraPanel!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
autoExposureLockWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
focusModeWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
focusExposureSwitchWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
cameraControlsWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
focalZoomWidget!!.visibility =
if (CameraUtil.isFPVTypeView(devicePosition)) View.INVISIBLE else View.VISIBLE
horizontalSituationIndicatorWidget!!.setSimpleModeEnable(
CameraUtil.isFPVTypeView(
devicePosition
)
)
//只在部分len下显示
ndviCameraPanel!!.visibility =
if (CameraUtil.isSupportForNDVI(lensType)) View.VISIBLE else View.INVISIBLE
}
/**
* Swap the video sources of the FPV and secondary FPV widgets.
*/
2026-04-03 20:41:05 +08:00
fun swapVideoSource() {
2026-01-30 11:47:32 +08:00
val primarySource = primaryFpvWidget!!.widgetModel.getCameraIndex()
val secondarySource = secondaryFPVWidget!!.widgetModel.getCameraIndex()
//两个source都存在的情况下才进行切换
if (primarySource != ComponentIndexType.UNKNOWN && secondarySource != ComponentIndexType.UNKNOWN) {
primaryFpvWidget!!.updateVideoSource(secondarySource)
secondaryFPVWidget!!.updateVideoSource(primarySource)
}
}
2026-04-29 15:44:05 +08:00
/**
* 强制刷新两个FPVWidget的视频流重新向MediaDataCenter注册
* 用于起飞/航线执行后视频流卡死的场景
*/
fun refreshVideoStream() {
val primarySource = primaryFpvWidget?.widgetModel?.getCameraIndex()
val secondarySource = secondaryFPVWidget?.widgetModel?.getCameraIndex()
if (primarySource != null && primarySource != ComponentIndexType.UNKNOWN) {
primaryFpvWidget?.updateVideoSource(primarySource)
}
if (secondarySource != null && secondarySource != ComponentIndexType.UNKNOWN) {
secondaryFPVWidget?.updateVideoSource(secondarySource)
}
LogUtil.log(TAG, "强制刷新视频流: primary=$primarySource, secondary=$secondarySource")
}
/**
* 智能刷新视频流有云台(secondary)就模拟点击切换没有就直接刷新当前流
* 兼容只有FPV没有云台的设备
*/
fun smartRefreshVideoStream() {
val secondarySource = secondaryFPVWidget?.widgetModel?.getCameraIndex()
if (secondarySource != null && secondarySource != ComponentIndexType.UNKNOWN) {
// 有云台:模拟真实点击,触发 swapVideoSource()
secondaryFPVWidget?.post {
secondaryFPVWidget?.performClick()
}
LogUtil.log(TAG, "智能刷新:有云台,模拟点击 FPV Widget")
} else {
// 没有云台:直接刷新当前流
primaryFpvWidget?.post {
refreshVideoStream()
}
LogUtil.log(TAG, "智能刷新:无云台,直接刷新主视频流")
}
}
2026-01-30 11:47:32 +08:00
private fun updateInteractionEnabled() {
fpvInteractionWidget!!.isInteractionEnabled = !CameraUtil.isFPVTypeView(
primaryFpvWidget!!.widgetModel.getCameraIndex()
)
}
private data class CameraSource(
val devicePosition: ComponentIndexType,
val lensType: CameraLensType
)
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
override fun onBackPressed() {
if (mDrawerLayout!!.isDrawerOpen(GravityCompat.END)) {
mDrawerLayout!!.closeDrawers()
} else {
super.onBackPressed()
}
}
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
// window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
)
setContentView(R.layout.activity_main)
isAppStarted = true
2026-04-03 20:41:05 +08:00
instance = this
2026-01-30 11:47:32 +08:00
// mapWidget = findViewById<MapWidget>(R.id.widget_map)
// mapWidget?.initMapLibreMap(applicationContext, OnMapReadyListener { map: DJIMap ->
// val uiSetting = map.uiSettings
// uiSetting?.setZoomControlsEnabled(false)
2026-04-03 20:41:05 +08:00
//
2026-01-30 11:47:32 +08:00
// mapWidget?.onCreate(savedInstanceState)
GeoidManager.getInstance().init(this)
WPMZManager.getInstance().init(this)
MqttManager.getInstance().needConnect()
initView()
2026-03-12 14:57:34 +08:00
2026-04-29 15:44:05 +08:00
// 后台线程初始化 DJI 相关模块,避免阻塞主线程导致 ANR
Thread {
initDJIManager()
}.start()
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
}
2026-04-08 13:43:50 +08:00
2026-01-30 11:47:32 +08:00
private fun initView() {
2026-03-12 14:57:34 +08:00
fpvParentView = findViewById(R.id.fpv_holder)
mDrawerLayout = findViewById(R.id.root_view)
topBarPanel = findViewById(R.id.panel_top_bar)
2026-01-30 11:47:32 +08:00
settingWidget = topBarPanel?.settingWidget
2026-03-12 14:57:34 +08:00
primaryFpvWidget = findViewById(R.id.widget_primary_fpv)
fpvInteractionWidget = findViewById(R.id.widget_fpv_interaction)
secondaryFPVWidget = findViewById(R.id.widget_secondary_fpv)
systemStatusListPanelWidget = findViewById(R.id.widget_panel_system_status_list)
simulatorControlWidget = findViewById(R.id.widget_simulator_control)
lensControlWidget = findViewById<LensControlWidget>(R.id.widget_lens_control)
ndviCameraPanel = findViewById(R.id.panel_ndvi_camera)
visualCameraPanel = findViewById(R.id.panel_visual_camera)
autoExposureLockWidget = findViewById(R.id.widget_auto_exposure_lock)
focusModeWidget = findViewById(R.id.widget_focus_mode)
focusExposureSwitchWidget = findViewById(R.id.widget_focus_exposure_switch)
pfvFlightDisplayWidget = findViewById(R.id.widget_fpv_flight_display_widget)
focalZoomWidget = findViewById(R.id.widget_focal_zoom)
cameraControlsWidget = findViewById(R.id.widget_camera_controls)
2026-01-30 11:47:32 +08:00
horizontalSituationIndicatorWidget =
findViewById(R.id.widget_horizontal_situation_indicator)
// gimbalAdjustDone = findViewById<TextView>( R.id.fpv_gimbal_ok_btn)
2026-03-12 14:57:34 +08:00
gimbalFineTuneWidget = findViewById(R.id.setting_menu_gimbal_fine_tune)
btn_test = findViewById(R.id.btn_test)
btn_test1 = findViewById(R.id.btn_test1)
btn_test2 = findViewById(R.id.btn_test2)
2026-04-25 15:36:59 +08:00
// btn_test3 = findViewById(R.id.btn_test3)
2026-01-30 11:47:32 +08:00
btn_test?.setOnClickListener {
2026-04-25 15:36:59 +08:00
// if(cameraMode == 3){
// //退出回放模式
// MediaManager.getInstance().disablePlayback();
// }
KeyManager.getInstance().setValue<CameraMode?>(
KeyTools.createKey<CameraMode?>(CameraKey.KeyCameraMode, ComponentIndexType.PORT_1),
CameraMode.find(12),
object : CompletionCallback {
override fun onSuccess() {
OSDManager.getInstance().pushFlightAttitude()
}
override fun onFailure(error: IDJIError) {
}
})
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
}
btn_test1?.setOnClickListener {
2026-04-25 15:36:59 +08:00
KeyManager.getInstance().performAction<EmptyMsg?>(
KeyTools.createKey<EmptyMsg?, EmptyMsg?>(
CameraKey.KeyStartShootPhoto,
ComponentIndexType.PORT_1
),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
LogUtil.log(TAG, "拍照成功")
}
2026-03-12 14:57:34 +08:00
2026-04-25 15:36:59 +08:00
override fun onFailure(error: IDJIError) {
LogUtil.log(TAG, "拍照失败:" + Gson().toJson(error))
}
})
2026-03-12 14:57:34 +08:00
}
2026-04-25 15:36:59 +08:00
btn_test2?.setOnClickListener {
StickManager.getInstance().enableVirtualStick1()
2026-03-12 14:57:34 +08:00
}
2026-04-25 15:36:59 +08:00
// btn_test3?.setOnClickListener {
// StreamManager.getInstance().startstream()
//
// }
2026-02-01 14:34:23 +08:00
2026-01-30 11:47:32 +08:00
initClickListener()
MediaDataCenter.getInstance().cameraStreamManager.addAvailableCameraUpdatedListener(
availableCameraUpdatedListener
)
2026-04-03 20:41:05 +08:00
2026-01-30 11:47:32 +08:00
primaryFpvWidget?.setOnFPVStreamSourceListener(object : FPVStreamSourceListener {
override fun onStreamSourceUpdated(
devicePosition: ComponentIndexType,
lensType: CameraLensType
) {
cameraSourceProcessor.onNext(
CameraSource(devicePosition, lensType)
)
}
})
//小surfaceView放置在顶部避免被大的遮挡
secondaryFPVWidget?.setSurfaceViewZOrderOnTop(true)
secondaryFPVWidget?.setSurfaceViewZOrderMediaOverlay(true)
window.setBackgroundDrawable(ColorDrawable(Color.BLACK))
//实现RTK监测网络并自动重连机制
DJINetworkManager.getInstance().addNetworkStatusListener(networkStatusListener)
2026-02-01 14:34:23 +08:00
2026-01-30 11:47:32 +08:00
}
2026-03-12 14:57:34 +08:00
private fun isGimableAdjustClicked(broadcastValues: BroadcastValues) {
2026-01-30 11:47:32 +08:00
if (mDrawerLayout!!.isDrawerOpen(GravityCompat.END)) {
mDrawerLayout!!.closeDrawers()
}
horizontalSituationIndicatorWidget!!.visibility = View.GONE
if (gimbalFineTuneWidget != null) {
gimbalFineTuneWidget!!.visibility = View.VISIBLE
}
}
2026-03-12 14:57:34 +08:00
private fun initClickListener() {
2026-01-30 11:47:32 +08:00
secondaryFPVWidget!!.setOnClickListener { v: View? -> swapVideoSource() }
if (settingWidget != null) {
settingWidget!!.setOnClickListener { v: View? -> toggleRightDrawer() }
}
// Setup top bar state callbacks
val systemStatusWidget = topBarPanel!!.systemStatusWidget
systemStatusWidget?.setOnClickListener { v: View? -> systemStatusListPanelWidget!!.toggleVisibility() }
val simulatorIndicatorWidget = topBarPanel!!.simulatorIndicatorWidget
simulatorIndicatorWidget?.setOnClickListener { v: View? -> simulatorControlWidget!!.toggleVisibility() }
// gimbalAdjustDone!!.setOnClickListener { view: View? ->
// horizontalSituationIndicatorWidget!!.visibility = View.VISIBLE
// if (gimbalFineTuneWidget != null) {
// gimbalFineTuneWidget!!.visibility = View.GONE
// }
// }
}
2026-03-12 14:57:34 +08:00
private fun toggleRightDrawer() {
2026-01-30 11:47:32 +08:00
mDrawerLayout!!.openDrawer(GravityCompat.END)
}
override fun onDestroy() {
2026-03-12 14:57:34 +08:00
2026-01-30 11:47:32 +08:00
super.onDestroy()
isAppStarted = false
2026-04-03 20:41:05 +08:00
stopVtxHeartbeat()
2026-01-30 11:47:32 +08:00
try {
if (MqttManager.getInstance().mqttAndroidClient != null && MqttManager.getInstance().mqttAndroidClient.isConnected) {
MqttManager.getInstance().mqttAndroidClient.unregisterResources()
MqttManager.getInstance().mqttAndroidClient.disconnect() //断开连接
}
} catch (e: MqttException) {
e.printStackTrace()
}
MediaDataCenter.getInstance().cameraStreamManager.removeAvailableCameraUpdatedListener(
availableCameraUpdatedListener
)
DJINetworkManager.getInstance().removeNetworkStatusListener(networkStatusListener)
}
2026-03-12 14:57:34 +08:00
private var initTimes = 0
2026-02-01 14:34:23 +08:00
2026-01-30 11:47:32 +08:00
private fun initDJIManager() {
2026-04-29 15:44:05 +08:00
// 在后台线程中轮询等待飞控/相机连接,避免阻塞主线程
var isFlightControllerConnect =
2026-01-30 11:47:32 +08:00
KeyManager.getInstance().getValue(DJIKey.create(FlightControllerKey.KeyConnection))
2026-04-29 15:44:05 +08:00
var isCameraConnect =
2026-04-03 20:41:05 +08:00
KeyManager.getInstance()
.getValue(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.PORT_1))
2026-04-29 15:44:05 +08:00
val cameraLocationType = PreferenceUtils.getInstance().cameraLocationType
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
// 根据 cameraLocationType 轮询等待连接
while (true) {
val flightConnected = isFlightControllerConnect != null && isFlightControllerConnect == true
val cameraConnected = isCameraConnect != null && isCameraConnect == true
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
val shouldInit = when (cameraLocationType) {
3 -> flightConnected
4, 5 -> flightConnected || cameraConnected
else -> flightConnected || cameraConnected
2026-04-03 20:41:05 +08:00
}
2026-03-04 11:20:07 +08:00
2026-04-29 15:44:05 +08:00
if (shouldInit) break
2026-03-12 14:57:34 +08:00
2026-04-29 15:44:05 +08:00
try {
Thread.sleep(1000)
} catch (e: InterruptedException) {
Thread.currentThread().interrupt()
return
}
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
isFlightControllerConnect =
KeyManager.getInstance().getValue(DJIKey.create(FlightControllerKey.KeyConnection))
isCameraConnect =
KeyManager.getInstance()
.getValue(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.PORT_1))
}
2026-04-08 13:43:50 +08:00
2026-04-29 15:44:05 +08:00
// 飞控/相机连接后,在主线程执行初始化
runOnUiThread {
when (cameraLocationType) {
3 -> initForCameraLocationType3()
4, 5 -> initForCameraLocationType4Or5()
else -> initForCameraLocationTypeDefault()
}
}
}
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
private fun initForCameraLocationType3() {
initTimes++
LogUtil.log(TAG, "下视觉初始化$initTimes")
cameraManager.setKeepAliveDecoding(true)
FlightManager.getInstance().initFlightInfo()
BatteryManager.getInstance().initBatteryInfo()
StickManager.getInstance().initStickInfo()
GimbalManager.getInstance().initGimbalInfo()
AlternateLandingManager.getInstance().initAlterLandingInfo()
OSDManager.getInstance().initOsd()
FlightTaskProgressManager.getInstance().initFlightTaskProgress()
MediaManager.getInstance().init()
StreamManager.getInstance().initStreamManager()
LEDsSettingsManager.getInstance().initLEDsInfo()
RTKManager.getInstance().initRTKInfo()
NavigationSatelliteSystemManager.getInstance().initNavigationSatelliteSystem()
NavigationSatelliteSystemManager.getInstance().setNavigationSatelliteSystem()
LTEManager.getInstance().initLTEInfo()
WirelessLinkManager.getInstance().initWirelessLink()
CameraManager.getInstance().initCameraInfo()
GeoidManager.getInstance().init(this)
MissionV3Manager.getInstance().initMissionManager()
enableStream()
initFpvStream()
startVtxHeartbeat()
SpeakerManager.getInstance().initMegaphoneInfo()
GimbalManager.getInstance().setmode()
LogUtil.log(TAG, "自定义推流方式:" + PreferenceUtils.getInstance().customStreamType)
Handler(Looper.getMainLooper()).postDelayed({
when (PreferenceUtils.getInstance().customStreamType) {
1 -> StreamManager.getInstance().startLiveWithRTSP()
2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom()
}
SimplePortScanner.getInstance().startScan()
}, 5000)
2026-03-12 14:57:34 +08:00
2026-04-29 15:44:05 +08:00
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)
}
2026-03-12 14:57:34 +08:00
2026-04-29 15:44:05 +08:00
private fun initForCameraLocationType4Or5() {
initTimes++
cameraManager.setKeepAliveDecoding(true)
LogUtil.log(TAG, "云台初始化$initTimes")
FlightManager.getInstance().initFlightInfo()
BatteryManager.getInstance().initBatteryInfo()
StickManager.getInstance().initStickInfo()
GimbalManager.getInstance().initGimbalInfo()
AlternateLandingManager.getInstance().initAlterLandingInfo()
OSDManager.getInstance().initOsd()
FlightTaskProgressManager.getInstance().initFlightTaskProgress()
MediaManager.getInstance().init()
StreamManager.getInstance().initStreamManager()
LEDsSettingsManager.getInstance().initLEDsInfo()
RTKManager.getInstance().initRTKInfo()
LTEManager.getInstance().initLTEInfo()
WirelessLinkManager.getInstance().initWirelessLink()
CameraManager.getInstance().initCameraInfo()
NavigationSatelliteSystemManager.getInstance().initNavigationSatelliteSystem()
NavigationSatelliteSystemManager.getInstance().setNavigationSatelliteSystem()
MissionV3Manager.getInstance().initMissionManager()
enableStream()
initMixedStream()
startVtxHeartbeat()
SpeakerManager.getInstance().initMegaphoneInfo()
GeoidManager.getInstance().init(this)
GimbalManager.getInstance().setmode()
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
LogUtil.log(TAG, "自定义推流方式:" + PreferenceUtils.getInstance().customStreamType)
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
Handler(Looper.getMainLooper()).postDelayed({
when (PreferenceUtils.getInstance().customStreamType) {
1 -> StreamManager.getInstance().startLiveWithRTSP()
2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom()
}
SimplePortScanner.getInstance().startScan()
}, 5000)
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)
}
2026-03-12 14:57:34 +08:00
2026-04-29 15:44:05 +08:00
private fun initForCameraLocationTypeDefault() {
initTimes++
cameraManager.setKeepAliveDecoding(true)
LogUtil.log(TAG, "云台初始化$initTimes")
FlightManager.getInstance().initFlightInfo()
BatteryManager.getInstance().initBatteryInfo()
StickManager.getInstance().initStickInfo()
GimbalManager.getInstance().initGimbalInfo()
AlternateLandingManager.getInstance().initAlterLandingInfo()
OSDManager.getInstance().initOsd()
FlightTaskProgressManager.getInstance().initFlightTaskProgress()
MediaManager.getInstance().init()
StreamManager.getInstance().initStreamManager()
LEDsSettingsManager.getInstance().initLEDsInfo()
RTKManager.getInstance().initRTKInfo()
LTEManager.getInstance().initLTEInfo()
WirelessLinkManager.getInstance().initWirelessLink()
CameraManager.getInstance().initCameraInfo()
NavigationSatelliteSystemManager.getInstance().initNavigationSatelliteSystem()
NavigationSatelliteSystemManager.getInstance().setNavigationSatelliteSystem()
MissionV3Manager.getInstance().initMissionManager()
enableStream()
initCameraStream()
startVtxHeartbeat()
SpeakerManager.getInstance().initMegaphoneInfo()
GeoidManager.getInstance().init(this)
GimbalManager.getInstance().setmode()
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
LogUtil.log(TAG, "自定义推流方式:" + PreferenceUtils.getInstance().customStreamType)
2026-04-03 20:41:05 +08:00
2026-04-29 15:44:05 +08:00
Handler(Looper.getMainLooper()).postDelayed({
when (PreferenceUtils.getInstance().customStreamType) {
1 -> StreamManager.getInstance().startLiveWithRTSP()
2 -> StreamManager.getInstance().startLiveWithCustom()
else -> StreamManager.getInstance().startLiveWithCustom()
2026-04-03 20:41:05 +08:00
}
2026-04-29 15:44:05 +08:00
SimplePortScanner.getInstance().startScan()
}, 5000)
LogUtil.log(TAG, "推流类型:" + PreferenceUtils.getInstance().customStreamType)
2026-01-30 11:47:32 +08:00
}
2026-04-03 20:41:05 +08:00
private fun enableStream() {
cameraManager.enableStream(ComponentIndexType.PORT_1, true);
cameraManager.enableStream(ComponentIndexType.FPV, true);
}
2026-01-30 11:47:32 +08:00
@SuppressLint("SuspiciousIndentation")
2026-04-08 13:39:51 +08:00
private fun initMixedStream() {
// 初始化融合视觉降落识别器
2026-04-08 13:43:50 +08:00
//val mixedLanding = MixedVisionLanding.getInstance()
2026-04-08 13:39:51 +08:00
// 为 PORT_1云台相机添加帧监听器
cameraManager.addFrameListener(
ComponentIndexType.PORT_1,
ICameraStreamManager.FrameFormat.YUV420_888
) { frameData, _, _, width, height, _ ->
Movement.getInstance().isVtx = true
updateVtxHeartbeat()
streamReceive = true
// 使用融合视觉识别器处理云台相机帧
2026-04-08 13:43:50 +08:00
//mixedLanding.processGimbalFrame(height, width, frameData, dictionary)
//使用云台
synchronized(Synchronizedstatus.LOCK_OBJ) {
if (!Synchronizedstatus.isIsruningframe() && Synchronizedstatus.isAprongim() && Synchronizedstatus.isSwitchtime()) {
try {
Synchronizedstatus.setIsruningframe(true)
if (startArucoType == 1) {
Aprongim.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
} else if (startArucoType == 2) {
AlternateArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
}
} finally {
Synchronizedstatus.setIsruningframe(false)
}
}
}
2026-04-08 13:39:51 +08:00
}
2026-04-03 20:41:05 +08:00
2026-04-08 13:39:51 +08:00
// 为 FPV下视相机添加帧监听器
cameraManager.addFrameListener(
ComponentIndexType.FPV,
ICameraStreamManager.FrameFormat.YUV420_888
) { frameData, _, _, width, height, _ ->
Movement.getInstance().isVtx = true
updateVtxHeartbeat()
streamReceive = true
// 使用融合视觉识别器处理下视相机帧
2026-04-08 13:43:50 +08:00
//mixedLanding.processDownwardFrame(height, width, frameData, dictionary)
//使用下视觉
synchronized(Synchronizedstatus.LOCK_OBJ) {
if (!Synchronizedstatus.isIsruningframe() && !Synchronizedstatus.isAprongim() && Synchronizedstatus.isSwitchtime()) {
try {
Synchronizedstatus.setIsruningframe(true)
if (startArucoType == 1) {
Aprondown.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
} else if (startArucoType == 2) {
AlternateArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
}
} finally {
Synchronizedstatus.setIsruningframe(false)
}
}
}
2026-04-08 13:39:51 +08:00
}
2026-04-03 20:41:05 +08:00
}
@SuppressLint("SuspiciousIndentation")
private fun initFpvStream() {
2026-01-30 11:47:32 +08:00
cameraManager.addFrameListener(
2026-02-01 14:34:23 +08:00
ComponentIndexType.FPV,
2026-01-30 11:47:32 +08:00
ICameraStreamManager.FrameFormat.YUV420_888
) { frameData, _, _, width, height, _ ->
2026-03-12 14:57:34 +08:00
Movement.getInstance().isVtx = true
2026-04-03 20:41:05 +08:00
updateVtxHeartbeat()
2026-03-12 14:57:34 +08:00
streamReceive = true
2026-04-03 20:41:05 +08:00
// DualCaptureHelper.getInstance().onFrame(height, width, frameData)
2026-01-30 11:47:32 +08:00
// if (shouldExecute) {
2026-04-03 20:41:05 +08:00
// if (startArucoType == 1&& ApronArucoStatus.getInstance().canProcess(ApronArucoStatus.CameraSource.DOWNWARD)) {
synchronized(Synchronizedstatus.LOCK_OBJ) {
if (!Synchronizedstatus.isIsruningframe()) {
try {
Synchronizedstatus.setIsruningframe(true)
if (startArucoType == 1) {
ApronArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
} else if (startArucoType == 2) {
AlternateArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
}
} finally {
Synchronizedstatus.setIsruningframe(false)
}
}
2026-03-12 14:57:34 +08:00
}
2026-01-30 11:47:32 +08:00
}
2026-04-03 20:41:05 +08:00
}
2026-03-12 14:57:34 +08:00
2026-04-03 20:41:05 +08:00
@SuppressLint("SuspiciousIndentation")
private fun initCameraStream() {
2026-03-12 14:57:34 +08:00
cameraManager.addFrameListener(
ComponentIndexType.PORT_1,
ICameraStreamManager.FrameFormat.YUV420_888
) { frameData, _, _, width, height, _ ->
Movement.getInstance().isVtx = true
2026-04-03 20:41:05 +08:00
updateVtxHeartbeat()
2026-03-12 14:57:34 +08:00
streamReceive = true
2026-04-03 20:41:05 +08:00
// DualCaptureHelper.getInstance().onFrame(height, width, frameData)
2026-03-12 14:57:34 +08:00
// if (shouldExecute) {
2026-04-03 20:41:05 +08:00
// if (startArucoType == 1&& ApronArucoStatus.getInstance().canProcess(ApronArucoStatus.CameraSource.DOWNWARD)) {
synchronized(Synchronizedstatus.LOCK_OBJ) {
if (!Synchronizedstatus.isIsruningframe()) {
try {
Synchronizedstatus.setIsruningframe(true)
if (startArucoType == 1) {
ApronArucoDetectPort.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
} else if (startArucoType == 2) {
AlternateArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary
)
}
} finally {
Synchronizedstatus.setIsruningframe(false)
}
}
2026-03-12 14:57:34 +08:00
}
}
2026-04-03 20:41:05 +08:00
}
2026-02-01 14:34:23 +08:00
// private val mLoaderCallback: BaseLoaderCallback = object : BaseLoaderCallback(this) {
// override fun onManagerConnected(status: Int) {
// if (status == SUCCESS) {
// LogUtil.log(TAG,"Version Name="+BuildConfig.VERSION_NAME)
// ApronArucoDetect.getInstance().init()
//
// } else {
// super.onManagerConnected(status)
// }
// }
// }
2026-01-30 11:47:32 +08:00
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEvent(message: String?) {
when (message) {
2026-04-25 15:36:59 +08:00
FLAG_START_DETECT_ARUCO_APRON -> {
2026-04-29 15:44:05 +08:00
2026-04-25 15:36:59 +08:00
MediaDataCenter.getInstance().getCameraStreamManager().setVisionAssistViewDirection(
VisionAssistDirection.DOWN,
object : CompletionCallback {
override fun onSuccess() {
LogUtil.log(TAG, "下视开启成功")
}
override fun onFailure(idjiError: IDJIError) {
LogUtil.log(TAG, "下视开启失败")
}
})
val leDsSettings = LEDsSettings()
leDsSettings.setNavigationLEDsOn(false)
leDsSettings.setStatusIndicatorLEDsOn(true)
leDsSettings.setFrontLEDsOn(true)
KeyManager.getInstance().setValue<LEDsSettings?>(
KeyTools.createKey<LEDsSettings?>(FlightControllerKey.KeyLEDsSettings),
leDsSettings,
object : CompletionCallback {
override fun onSuccess() {
LogUtil.log(TAG, "夜航灯关闭成功")
}
override fun onFailure(idjiError: IDJIError) {
LogUtil.log(TAG, "夜航灯关闭失败")
}
})
2026-01-30 11:47:32 +08:00
KeyManager.getInstance().performAction<EmptyMsg>(
KeyTools.createKey<EmptyMsg, EmptyMsg>(FlightControllerKey.KeyStopAutoLanding),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
LogUtil.log(TAG, "取消降落,识别机库二维码")
2026-04-03 20:41:05 +08:00
if (PreferenceUtils.getInstance().cameraLocationType == 3) {
Handler().postDelayed(Runnable {
if (!ApronArucoDetect.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
//测试图传丢失
AlternateLandingManager.getInstance().startTaskProcess(null)
}
}, 6000)
2026-04-25 15:36:59 +08:00
} else if (PreferenceUtils.getInstance().cameraLocationType == 4 || PreferenceUtils.getInstance().cameraLocationType == 5) {
2026-04-08 13:43:50 +08:00
Handler().postDelayed(Runnable {
if (!Aprongim.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
//测试图传丢失
AlternateLandingManager.getInstance().startTaskProcess(null)
}
}, 6000)
2026-04-03 20:41:05 +08:00
} else {
Handler().postDelayed(Runnable {
if (!ApronArucoDetectPort.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
//测试图传丢失
AlternateLandingManager.getInstance().startTaskProcess(null)
}
}, 6000)
}
2026-01-30 11:47:32 +08:00
if (startArucoType == 1) {
return
}
startArucoType = 1
ApronArucoDetect.getInstance().setDetectedBigMarkers()
2026-04-03 20:41:05 +08:00
ApronArucoDetectPort.getInstance().setDetectedBigMarkers()
2026-04-08 13:43:50 +08:00
Aprongim.getInstance().setDetectedBigMarkers()
Aprondown.getInstance().setDetectedBigMarkers()
2026-01-30 11:47:32 +08:00
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
DroneHelper.getInstance().isVirtualStickEnable = false
DroneHelper.getInstance().setVerticalModeToVelocity()
}
2026-04-25 15:36:59 +08:00
2026-01-30 11:47:32 +08:00
override fun onFailure(error: IDJIError) {
if (startArucoType == 1) {
return
}
startArucoType = 1
LogUtil.log(TAG, "取消降落,识别机库二维码失败:" + Gson().toJson(error))
ApronArucoDetect.getInstance().setDetectedBigMarkers()
2026-04-03 20:41:05 +08:00
ApronArucoDetectPort.getInstance().setDetectedBigMarkers()
2026-04-08 13:43:50 +08:00
Aprongim.getInstance().setDetectedBigMarkers()
Aprondown.getInstance().setDetectedBigMarkers()
2026-01-30 11:47:32 +08:00
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
2026-03-12 14:57:34 +08:00
DroneHelper.getInstance().isVirtualStickEnable = false
2026-01-30 11:47:32 +08:00
DroneHelper.getInstance().setVerticalModeToVelocity()
}
})
2026-04-25 15:36:59 +08:00
}
2026-01-30 11:47:32 +08:00
FLAG_START_DETECT_ARUCO_ALTERNATE ->
KeyManager.getInstance().performAction<EmptyMsg>(
KeyTools.createKey<EmptyMsg, EmptyMsg>(FlightControllerKey.KeyStopAutoLanding),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
LogUtil.log(TAG, "取消降落,识别备降点二维码")
2026-04-03 20:41:05 +08:00
if (PreferenceUtils.getInstance().cameraLocationType == 3) {
Handler().postDelayed(Runnable {
2026-04-08 13:43:50 +08:00
if (!ApronArucoDetect.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
2026-04-03 20:41:05 +08:00
//测试图传丢失
2026-04-08 13:43:50 +08:00
AlternateLandingManager.getInstance().startTaskProcess(null)
2026-04-03 20:41:05 +08:00
}
2026-04-08 13:43:50 +08:00
}, 6000)
2026-04-25 15:36:59 +08:00
} else if (PreferenceUtils.getInstance().cameraLocationType == 4 || PreferenceUtils.getInstance().cameraLocationType == 5) {
2026-04-08 13:43:50 +08:00
Handler().postDelayed(Runnable {
if (!Aprongim.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
//测试图传丢失
AlternateLandingManager.getInstance().startTaskProcess(null)
}
}, 6000)
2026-04-03 20:41:05 +08:00
} else {
Handler().postDelayed(Runnable {
2026-04-08 13:43:50 +08:00
if (!ApronArucoDetectPort.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
2026-04-03 20:41:05 +08:00
//测试图传丢失
2026-04-08 13:43:50 +08:00
AlternateLandingManager.getInstance().startTaskProcess(null)
2026-04-03 20:41:05 +08:00
}
2026-04-08 13:43:50 +08:00
}, 6000)
2026-04-03 20:41:05 +08:00
}
2026-01-30 11:47:32 +08:00
if (startArucoType == 2) {
return
}
startArucoType = 2
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
DroneHelper.getInstance().isVirtualStickEnable = false
DroneHelper.getInstance().setVerticalModeToVelocity()
}
override fun onFailure(error: IDJIError) {
if (startArucoType == 2) {
return
}
startArucoType = 2
LogUtil.log(
TAG,
"取消降落,识别备降点二维码失败:" + Gson().toJson(error)
)
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
2026-03-12 14:57:34 +08:00
DroneHelper.getInstance().isVirtualStickEnable = false
2026-01-30 11:47:32 +08:00
DroneHelper.getInstance().setVerticalModeToVelocity()
}
})
2026-04-08 13:43:50 +08:00
FLAG_DOWN_LAND -> {
2026-04-08 13:39:51 +08:00
//重置降落变量
ApronArucoDetect.getInstance().setStartAruco(false);
ApronArucoDetectPort.getInstance().setStartAruco(false);
2026-04-08 13:43:50 +08:00
Aprongim.getInstance().setStartAruco(false);
Aprondown.getInstance().setStartAruco(false);
2026-04-08 13:39:51 +08:00
2026-03-04 11:20:07 +08:00
KeyManager.getInstance().performAction<EmptyMsg>(
KeyTools.createKey<EmptyMsg, EmptyMsg>(FlightControllerKey.KeyStartAutoLanding),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
startArucoType = 0
LogUtil.log(TAG, "自动降落调用成功")
}
2026-01-30 11:47:32 +08:00
2026-03-04 11:20:07 +08:00
override fun onFailure(error: IDJIError) {
LogUtil.log(TAG, "自动降落调用失败${error.description()}")
}
})
2026-04-08 13:39:51 +08:00
}
2026-01-30 11:47:32 +08:00
FLAG_STOP_ARUCO ->
startArucoType = 0
2026-04-28 11:39:16 +08:00
"REFRESH_VIDEO_SOURCE" -> {
2026-04-29 15:44:05 +08:00
// 智能刷新:有云台模拟点击,没有云台直接刷新
smartRefreshVideoStream()
2026-04-28 11:39:16 +08:00
}
2026-01-30 11:47:32 +08:00
MqttCallBack.FLAG_RESET_CLEAN_MODE ->
setViewVisibilityWithCleanMode()
}
}
2026-03-04 11:20:07 +08:00
2026-01-30 11:47:32 +08:00
private fun setViewVisibilityWithCleanMode() {
if (PreferenceUtils.getInstance().isCleanMode) {
fpvInteractionWidget?.visibility = View.GONE
horizontalSituationIndicatorWidget?.visibility = View.GONE
gimbalFineTuneWidget?.visibility = View.GONE
ndviCameraPanel?.visibility = View.GONE
visualCameraPanel?.visibility = View.GONE
autoExposureLockWidget?.visibility = View.GONE
focusModeWidget?.visibility = View.GONE
focusExposureSwitchWidget?.visibility = View.GONE
cameraControlsWidget?.visibility = View.GONE
focalZoomWidget?.visibility = View.GONE
// returnHomeWidget?.visibility = View.GONE
// takeOffWidget?.visibility = View.GONE
// lensControlWidget?.visibility = View.GONE
simulatorControlWidget?.visibility = View.GONE
pfvFlightDisplayWidget?.visibility = View.GONE
systemStatusListPanelWidget?.visibility = View.GONE
topBarPanel?.visibility = View.GONE
}
}
}