Compare commits

...

No commits in common. "main" and "qushuijiku" have entirely different histories.

1238 changed files with 815029 additions and 1116 deletions

77
.gitignore vendored
View File

@ -1,67 +1,26 @@
<<<<<<< HEAD
# ----------- Gradle / 构建产物 -----------
# Android 构建产物(不上传)
.gradle/
.idea/
app/build/
*/build/
build/
*.apk
*.aab
# ----------- 本地密钥 / 环境文件 -----------
local.properties
*.jks
*.keystore
google-services.json
# ----------- IDEA / AS 缓存 & 个人配置 -----------
.idea/caches/
.idea/libraries/
.idea/workspace.xml
.idea/tasks.xml
.idea/navEditor.xml
.idea/assetWizardSettings.xml
*.iml
# ----------- OS 垃圾 -----------
.DS_Store
Thumbs.db
# ----------- NDK / 外部构建缓存 -----------
.externalNativeBuild
.cxx
*.hprof
=======
# ---> Android
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Log/OS Files
*.log
# Android Studio generated files and folders
captures/
.externalNativeBuild/
.cxx/
*.apk
output.json
*.aab
*.dex
local.properties
*.log
# IntelliJ
*.iml
.idea/
misc.xml
deploymentTargetDropDown.xml
render.experimental.xml
# 系统文件
.DS_Store
Thumbs.db
# Keystore files
*.jks
*.keystore
# Google Services (e.g. APIs or Firebase)
google-services.json
# Android Profiling
*.hprof
>>>>>>> 91bdec4aa6da285c4dd9a861e3b748515542f0b4
# 允许上传的(源码+配置)
!app/src/
!build.gradle
!settings.gradle
!gradle/
!gradlew
!gradlew.bat

3
.idea/.gitignore vendored
View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -1 +0,0 @@
MSDKSample

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="17" />
</component>
</project>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/android-sdk-v5-uxsdk" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

View File

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.7.21" />
</component>
</project>

View File

@ -1,9 +0,0 @@
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,3 +0,0 @@
# makcar
马克图姆小车

View File

@ -1,14 +1,15 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion Integer.parseInt(project.ANDROID_COMPILE_SDK_VERSION)
compileSdkVersion 32
resourcePrefix "uxsdk_"
defaultConfig {
minSdkVersion Integer.parseInt(project.ANDROID_MIN_SDK_VERSION)
targetSdkVersion Integer.parseInt(project.ANDROID_TARGET_SDK_VERSION)
minSdkVersion 24
targetSdkVersion 32
versionCode 1
versionName "1.0"
}
@ -22,49 +23,50 @@ android {
jvmTarget = JavaVersion.VERSION_1_8
freeCompilerArgs += ["-Xjvm-default=all"]
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation deps.annotation
implementation deps.appcompat
implementation deps.multidex
implementation deps.legacySupport
implementation deps.recyclerview
implementation deps.okio
implementation deps.wire
implementation deps.constraintLayout
implementation deps.lifecycleJava8
implementation deps.lifecycleRuntime
implementation deps.lifecycleProcess
implementation deps.media
implementation deps.kotlinLib
implementation deps.ktxCore
implementation deps.rx3Android
implementation deps.wpmzSdk
implementation deps.rx3Kt
implementation deps.lottie
implementation deps.cardview
implementation deps.mikepenzCommunityMaterial
implementation deps.mikepenzGoogleMaterial
implementation deps.mikepenzIconicsViews
implementation deps.mikepenzIconicsCore
implementation deps.mikepenzIonicons
implementation deps.material
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.squareup.okio:okio:1.17.2'
implementation 'com.squareup.wire:wire-runtime:2.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime:2.3.1'
implementation 'androidx.lifecycle:lifecycle-process:2.3.1'
implementation 'androidx.media:media:1.0.0'
// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION"
implementation "androidx.core:core-ktx:1.3.2"
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
implementation 'io.reactivex.rxjava3:rxkotlin:3.0.0'
api deps.maplibreTurf
api deps.maplibreSdk
implementation 'com.dji:wpmzsdk:1.0.1.7'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
implementation 'com.airbnb.android:lottie:3.3.1'//RTK扫描页中使用
implementation 'androidx.cardview:cardview:1.0.0'//PopoverView中使用
implementation "com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar"
implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar'
implementation 'com.mikepenz:iconics-views:4.0.2@aar'
implementation 'com.mikepenz:iconics-core:4.0.2@aar'
implementation 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar'
implementation 'com.google.android.material:material:1.0.0'//AvoidanceShortcutWidget使用
api 'org.maplibre.gl:android-sdk-turf:5.9.1'
api 'org.maplibre.gl:android-sdk:10.3.1'
api deps.playservicesplaces
api deps.playservicesmaps
api deps.playserviceslocation
api deps.playservicesbase
api 'com.google.android.gms:play-services-places:16.0.0'
api 'com.google.android.gms:play-services-maps:16.0.0'
api 'com.google.android.gms:play-services-location:16.0.0'
api 'com.google.android.gms:play-services-base:16.0.0'
compileOnly deps.aircraftProvided
implementation deps.aircraft
compileOnly "com.dji:dji-sdk-v5-aircraft-provided:5.15.0"
compileOnly "com.dji:dji-sdk-v5-aircraft:5.15.0"
}

View File

@ -169,7 +169,7 @@ public class CameraCaptureWidget extends ConstraintLayoutWidget<Object> implemen
widgetMap.put(cameraMode, view);
view.setVisibility(INVISIBLE);
addView(view);
ConstraintLayout.LayoutParams lp = new Constraints.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
LayoutParams lp = new Constraints.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
view.setLayoutParams(lp);
}

View File

@ -336,7 +336,7 @@ public class ShootPhotoWidgetModel extends WidgetModel implements ICameraIndex {
private boolean isSupportShootPhoto(){
CameraType cameraType = KeyManager.getInstance().getValue(KeyTools.createKey(CameraKey.KeyCameraType ,cameraIndex) ,CameraType.NOT_SUPPORTED);
return cameraType == CameraType.M3T || cameraType == CameraType.M3E || cameraType == CameraType.M3TA || cameraType == CameraType.M3M || cameraType == CameraType.ZENMUSE_H20T;
return cameraType == CameraType.M3T || cameraType == CameraType.M3E || cameraType == CameraType.M3M || cameraType == CameraType.ZENMUSE_H20T;
}
//region Helpers

View File

@ -228,7 +228,7 @@ public class FPVInteractionWidget extends FrameLayoutWidget<Object> implements V
addDisposable(Flowable.combineLatest(widgetModel.getControlMode(), widgetModel.isAeLocked(), Pair::new)
.firstOrError()
.observeOn(SchedulerProvider.ui())
.subscribe((Pair<SettingDefinitions.ControlMode, Boolean> values) -> updateTarget(values.first, values.second, targetX, targetY),
.subscribe((Pair<ControlMode, Boolean> values) -> updateTarget(values.first, values.second, targetX, targetY),
UxErrorHandle.logErrorConsumer(TAG, "Update Target: ")));
}
break;

View File

@ -80,7 +80,7 @@ public class CompassCalibrationDialog extends BaseDialog implements View.OnClick
initialize(context);
}
protected CompassCalibrationDialog(@NonNull Context context, boolean cancelable, @Nullable DialogInterface.OnCancelListener cancelListener) {
protected CompassCalibrationDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
super(context, cancelable, cancelListener);
initialize(context);
}

View File

@ -42,7 +42,7 @@ public class DJISDKModel {
}
public static DJISDKModel getInstance() {
return DJISDKModel.SingletonHolder.instance;
return SingletonHolder.instance;
}
/**

View File

@ -86,7 +86,7 @@ public class TabModeWidget extends RoundedLinearLayout implements View.OnClickLi
addView(tab);
if (mFixedSize) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)tab.getLayoutParams();
LayoutParams params = (LayoutParams)tab.getLayoutParams();
if (params != null) {
params.weight = 1;
params.width = 0;

View File

@ -16,7 +16,7 @@ public class PreviewChartTouchHandler extends ChartTouchHandler {
this.isValueSelectionEnabled = false;
}
protected class PreviewChartGestureListener extends ChartTouchHandler.ChartGestureListener {
protected class PreviewChartGestureListener extends ChartGestureListener {
protected PreviewChartGestureListener() {
super();
}

View File

@ -6,12 +6,12 @@ public class SelectedValue {
private SelectedValueType type;
public SelectedValue() {
this.type = SelectedValue.SelectedValueType.NONE;
this.type = SelectedValueType.NONE;
this.clear();
}
public SelectedValue(int firstIndex, int secondIndex, SelectedValueType type) {
this.type = SelectedValue.SelectedValueType.NONE;
this.type = SelectedValueType.NONE;
this.set(firstIndex, secondIndex, type);
}
@ -21,7 +21,7 @@ public class SelectedValue {
if (null != type) {
this.type = type;
} else {
this.type = SelectedValue.SelectedValueType.NONE;
this.type = SelectedValueType.NONE;
}
}
@ -33,7 +33,7 @@ public class SelectedValue {
}
public void clear() {
this.set(Integer.MIN_VALUE, Integer.MIN_VALUE, SelectedValue.SelectedValueType.NONE);
this.set(Integer.MIN_VALUE, Integer.MIN_VALUE, SelectedValueType.NONE);
}
public boolean isSet() {

View File

@ -8,7 +8,7 @@ public class Viewport implements Parcelable {
public float top;
public float right;
public float bottom;
public static final Parcelable.Creator<Viewport> CREATOR = new Parcelable.Creator<Viewport>() {
public static final Creator<Viewport> CREATOR = new Creator<Viewport>() {
public Viewport createFromParcel(Parcel in) {
Viewport v = new Viewport();
v.readFromParcel(in);

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2018-2020 DJI
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package dji.v5.ux.core.communication;
/**
* Class containing all UX keys related to camera functions
*/
public final class CameraKeys extends UXKeys {
@UXParamKey(type = Integer.class, updateType = UpdateType.ON_CHANGE)
public static final String PEAK_THRESHOLD = "PeakThreshold";
private CameraKeys() {
super();
}
}

View File

@ -39,7 +39,7 @@ public class FlatStore {
}
public static FlatStore getInstance() {
return FlatStore.SingletonHolder.instance;
return SingletonHolder.instance;
}
/**

View File

@ -57,7 +57,7 @@ public class ObservableInMemoryKeyedStore implements ObservableKeyedStore {
}
public static ObservableInMemoryKeyedStore getInstance() {
return ObservableInMemoryKeyedStore.SingletonHolder.instance;
return SingletonHolder.instance;
}
/**

View File

@ -175,7 +175,7 @@ var ImageView.imageDrawable: Drawable?
* @param dialogClickListener
*/
fun View.showAlertDialog(
@StyleRes dialogTheme: Int = R.style.Theme_AppCompat_Dialog,
@StyleRes dialogTheme: Int = com.airbnb.lottie.R.style.Theme_AppCompat_Dialog,
title: String? = getString(R.string.uxsdk_alert),
icon: Drawable? = null,
message: String? = null,
@ -206,7 +206,7 @@ fun View.showAlertDialog(
* @param dialogClickListener
*/
fun View.showConfirmationDialog(
@StyleRes dialogTheme: Int = R.style.Theme_AppCompat_Dialog,
@StyleRes dialogTheme: Int = com.airbnb.lottie.R.style.Theme_AppCompat_Dialog,
title: String? = getString(R.string.uxsdk_alert),
icon: Drawable? = null,
message: String? = null,

View File

@ -91,17 +91,17 @@ public class RangeSeekBar extends View {
// 高度
int heightNeeded = mThumbSize;
int heightSize = View.MeasureSpec.getSize(heightMeasureSpec);
int heightMode = View.MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == View.MeasureSpec.EXACTLY) {
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(heightSize, View.MeasureSpec.EXACTLY);
} else if (heightMode == View.MeasureSpec.AT_MOST) {
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
heightSize < heightNeeded ? heightSize : heightNeeded, View.MeasureSpec.EXACTLY);
if (heightMode == MeasureSpec.EXACTLY) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
} else if (heightMode == MeasureSpec.AT_MOST) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
heightSize < heightNeeded ? heightSize : heightNeeded, MeasureSpec.EXACTLY);
} else {
heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(
heightNeeded, View.MeasureSpec.EXACTLY);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(
heightNeeded, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

View File

@ -66,8 +66,8 @@ public class QTabView extends TabView {
private void initBadge() {
mBadge = new TextView(mContext);
FrameLayout.LayoutParams
params2 = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT);
LayoutParams
params2 = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params2.gravity = Gravity.RIGHT | Gravity.TOP;
params2.setMargins(0, dp2px(5), dp2px(5), 0);
mBadge.setLayoutParams(params2);
@ -104,7 +104,7 @@ public class QTabView extends TabView {
int dp = AndUtil.isTabletDevice(ContextUtil.getContext()) ? 10 : 7;
mIcon.setPadding(dp2px(dp), dp2px(dp), dp2px(dp), dp2px(dp));
mIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp),
LayoutParams params = new LayoutParams(getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp),
getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp));
mIcon.setLayoutParams(params);
if (mTabIcon.mNormalIcon != 0) {
@ -119,15 +119,15 @@ public class QTabView extends TabView {
}
private void setBadgeImp(int num) {
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mBadge.getLayoutParams();
LayoutParams lp = (LayoutParams) mBadge.getLayoutParams();
if (num <= 9) {
lp.width = dp2px(12);
lp.height = dp2px(12);
gd.setShape(GradientDrawable.OVAL);
mBadge.setPadding(0, 0, 0, 0);
} else {
lp.width = FrameLayout.LayoutParams.WRAP_CONTENT;
lp.height = FrameLayout.LayoutParams.WRAP_CONTENT;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
mBadge.setPadding(dp2px(3), 0, dp2px(3), 0);
gd.setShape(GradientDrawable.RECTANGLE);
gd.setCornerRadius(dp2px(6));
@ -291,8 +291,8 @@ public class QTabView extends TabView {
public Builder() {
mSelectedIcon = 0;
mNormalIcon = 0;
mIconWidth = FrameLayout.LayoutParams.WRAP_CONTENT;
mIconHeight = FrameLayout.LayoutParams.WRAP_CONTENT;
mIconWidth = LayoutParams.WRAP_CONTENT;
mIconHeight = LayoutParams.WRAP_CONTENT;
mIconGravity = Gravity.LEFT;
mBackground = 0;
}

View File

@ -97,7 +97,6 @@ public final class CameraUtil {
CAMERA_TYPE_STRING_MAP.put(CameraType.M30T, "M30T");
CAMERA_TYPE_STRING_MAP.put(CameraType.M3E, "M3E");
CAMERA_TYPE_STRING_MAP.put(CameraType.M3T, "M3T");
CAMERA_TYPE_STRING_MAP.put(CameraType.M3TA, "M3TA");
CAMERA_TYPE_STRING_MAP.put(CameraType.M3M, "M3M");
CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_L1, "L1");
CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_P1, "P1");

View File

@ -0,0 +1,48 @@
//package dji.v5.ux.core.util;
//
//import java.util.ArrayList;
//import java.util.List;
//
//import dji.sdk.keyvalue.value.common.ComponentIndexType;
//
///**
// * Class Description
// *
// * @author Hoker
// * @date 2021/11/23
// * <p>
// * Copyright (c) 2021, DJI All Rights Reserved.
// */
//public class CommonUtils {
//
// public static List<Integer> toList(int [] ints){
// List<Integer> list = new ArrayList<>();
// if (ints == null){
// return list;
// }
// for (int i : ints){
// list.add(i);
// }
// return list;
// }
//
// public static SettingDefinitions.GimbalIndex getGimbalIndex(ComponentIndexType devicePosition) {
// if (devicePosition == null){
// return SettingDefinitions.GimbalIndex.UNKONWN;
// }
// switch (devicePosition) {
// case LEFT_OR_MAIN:
// return SettingDefinitions.GimbalIndex.PORT;
// case RIGHT:
// return SettingDefinitions.GimbalIndex.STARBOARD;
// case UP:
// return SettingDefinitions.GimbalIndex.TOP;
// default:
// return SettingDefinitions.GimbalIndex.UNKONWN;
// }
// }
//
// private CommonUtils() {
//
// }
//}

View File

@ -86,7 +86,7 @@ public class MobileGPSLocationUtil {
}
public static MobileGPSLocationUtil getInstance() {
return MobileGPSLocationUtil.LazyHolder.INSTANCE;
return LazyHolder.INSTANCE;
}
private MobileGPSLocationUtil() {

View File

@ -107,7 +107,7 @@ public class BatteryGroupInfoWidget extends ConstraintLayoutWidget<Object> {
batteryChargeRemaining.setText(getResources().getString(R.string.uxsdk_battery_percent, percent));
}
public void setOnDetailOnClickListener(@Nullable View.OnClickListener listener) {
public void setOnDetailOnClickListener(@Nullable OnClickListener listener) {
batteryDetail.setVisibility(listener == null ? GONE : VISIBLE);
batteryDetail.setOnClickListener(listener);
}

View File

@ -190,7 +190,11 @@ open class FlightModeWidget @JvmOverloads constructor(
//region Reactions to model
private fun updateUI(flightModeState: FlightModeState) {
if (flightModeState is FlightModeState.FlightModeUpdated) {
flightModeTextView.text = flightModeState.flightModeString
if (flightModeState.flightModeString.equals("P-GPS")){
flightModeTextView.text = ""
}else{
flightModeTextView.text = flightModeState.flightModeString
}
iconImageView.setColorFilter(connectedStateIconColor, PorterDuff.Mode.SRC_IN)
flightModeTextView.setTextColor(connectedStateTextColor)
widgetStateDataProcessor.onNext(FlightModeUpdated(flightModeState.flightModeString))

View File

@ -362,7 +362,7 @@ open class FPVWidget @JvmOverloads constructor(
private fun updateCameraName(cameraName: String) {
cameraNameTextView.text = cameraName
if (cameraName.isNotEmpty() && isCameraSourceNameVisible) {
cameraNameTextView.visibility = View.VISIBLE
cameraNameTextView.visibility = View.INVISIBLE
} else {
cameraNameTextView.visibility = View.INVISIBLE
}
@ -371,7 +371,7 @@ open class FPVWidget @JvmOverloads constructor(
private fun updateCameraSide(cameraSide: String) {
cameraSideTextView.text = cameraSide
if (cameraSide.isNotEmpty() && isCameraSourceSideVisible) {
cameraSideTextView.visibility = View.VISIBLE
cameraSideTextView.visibility = View.INVISIBLE
} else {
cameraSideTextView.visibility = View.INVISIBLE
}

View File

@ -190,12 +190,19 @@ open class SystemStatusWidget @JvmOverloads constructor(
}
private fun updateMessage(messageData: SystemStatusWidgetModel.WarningStatusMessageData) {
systemStatusTextView.text =
if (isMaxHeightMessage(messageData.message)) {
messageData.message + " - " + formatMaxHeight(messageData.maxHeight, messageData.unitType)
} else {
if (isMaxHeightMessage(messageData.message)){
systemStatusTextView.text =messageData.message + " - " + formatMaxHeight(messageData.maxHeight, messageData.unitType)
}else{
val str:String = if (messageData.message.contains("(GPS)")){
messageData.message.replace("(GPS)", "").trim()
}else if(messageData.message.contains("GPS")){
messageData.message.replace("GPS", "").trim()
}else{
messageData.message
}
systemStatusTextView.text =str
}
}
private fun isMaxHeightMessage(text: String?): Boolean {

View File

@ -33,7 +33,7 @@ public class FocalZoomWidget extends ConstraintLayoutWidget<Object> implements I
int widthMeasureSpec = (int) getResources().getDimension(R.dimen.uxsdk_42_dp);
int heightMeasureSpec = (int) getResources().getDimension(R.dimen.uxsdk_250_dp);
focalZoomWidgetView = new FocalZoomWidgetView(context, attrs, defStyleAttr);
ConstraintLayout.LayoutParams layoutParams = new ConstraintLayout.LayoutParams(widthMeasureSpec, heightMeasureSpec);
LayoutParams layoutParams = new LayoutParams(widthMeasureSpec, heightMeasureSpec);
this.addView(focalZoomWidgetView, layoutParams);
}

1
app/.gitignore vendored
View File

@ -1 +0,0 @@
/build

BIN
app/apron.jks Normal file

Binary file not shown.

View File

@ -1,100 +1,232 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
plugins {
id 'com.android.application'
// id 'com.google.protobuf'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.makcar'
compileSdk 34
compileSdk 32
defaultConfig {
applicationId "com.example.makcar"
minSdk 27
targetSdk 33
versionCode 1
versionName "1.0"
applicationId "com.aros.apron"
minSdk 24
targetSdk 29
versionCode 46
versionName "v1.9.1"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
ndk {
abiFilters 'arm64-v8a' // MSDK arm64-v8a
}
// MSDK so
packagingOptions {
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}
// MSDK so
packagingOptions {
doNotStrip "*/*/libconstants.so"
doNotStrip "*/*/libdji_innertools.so"
doNotStrip "*/*/libdjibase.so"
doNotStrip "*/*/libDJICSDKCommon.so"
doNotStrip "*/*/libDJIFlySafeCore-CSDK.so"
doNotStrip "*/*/libdjifs_jni-CSDK.so"
doNotStrip "*/*/libDJIRegister.so"
doNotStrip "*/*/libdjisdk_jni.so"
doNotStrip "*/*/libDJIUpgradeCore.so"
doNotStrip "*/*/libDJIUpgradeJNI.so"
doNotStrip "*/*/libDJIWaypointV2Core-CSDK.so"
doNotStrip "*/*/libdjiwpv2-CSDK.so"
doNotStrip "*/*/libFlightRecordEngine.so"
doNotStrip "*/*/libvideo-framing.so"
doNotStrip "*/*/libwaes.so"
doNotStrip "*/*/libagora-rtsa-sdk.so"
doNotStrip "*/*/libc++.so"
doNotStrip "*/*/libc++_shared.so"
doNotStrip "*/*/libmrtc_28181.so"
doNotStrip "*/*/libmrtc_agora.so"
doNotStrip "*/*/libmrtc_core.so"
doNotStrip "*/*/libmrtc_core_jni.so"
doNotStrip "*/*/libmrtc_data.so"
doNotStrip "*/*/libmrtc_log.so"
doNotStrip "*/*/libmrtc_onvif.so"
doNotStrip "*/*/libmrtc_rtmp.so"
doNotStrip "*/*/libmrtc_rtsp.so"
// SO库架构
// abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
abiFilters 'arm64-v8a'
}
}
// buildTypes {
// release {
// minifyEnabled false
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
// }
// }
buildTypes {
release {
minifyEnabled false
minifyEnabled true //
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
//
}
debug {
minifyEnabled true
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
signingConfigs {
debug {
storeFile file('apron.jks')
storePassword "123456"
keyAlias "key0"
keyPassword "123456"
}
}
dexOptions {
javaMaxHeapSize "4g"
}
// proto src/main/proto
// sourceSets
sourceSets {
// main {
// proto {
// srcDir 'src/main/proto'
// }
// }
}
// protobuf {
// protoc {
// artifact = 'com.google.protobuf:protoc:3.17.3'
// }
//
// // build/generated/source/proto
// // buildType debug / release
// generatedFilesBaseDir = "$projectDir/src/proto"
//
// generateProtoTasks {
// all().each { task ->
// task.builtins {
// java {
// option "lite"
//// outputSubDir = "../" // debug / release
// }
// }
// }
// }
// }
// clean {
// delete protobuf.generatedFilesBaseDir
// }
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = "1.8"
freeCompilerArgs += [
"-Xjvm-default=all",
]
}
packagingOptions {
// mrtc库内部使用了NDK的c++_shared的编译参数
//
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}
packagingOptions {
doNotStrip "*/*/libconstants.so"
doNotStrip "*/*/libdji_innertools.so"
doNotStrip "*/*/libdjibase.so"
doNotStrip "*/*/libDJICSDKCommon.so"
doNotStrip "*/*/libDJIFlySafeCore-CSDK.so"
doNotStrip "*/*/libdjifs_jni-CSDK.so"
doNotStrip "*/*/libDJIRegister.so"
doNotStrip "*/*/libdjisdk_jni.so"
doNotStrip "*/*/libDJIUpgradeCore.so"
doNotStrip "*/*/libDJIUpgradeJNI.so"
doNotStrip "*/*/libDJIWaypointV2Core-CSDK.so"
doNotStrip "*/*/libdjiwpv2-CSDK.so"
doNotStrip "*/*/libffmpeg.so"
doNotStrip "*/*/libFlightRecordEngine.so"
doNotStrip "*/*/libvideo-framing.so"
doNotStrip "*/*/libwaes.so"
doNotStrip "*/*/libagora-rtsa-sdk.so"
doNotStrip "*/*/libc++.so"
doNotStrip "*/*/libc++_shared.so"
doNotStrip "*/*/libmrtc_28181.so"
doNotStrip "*/*/libmrtc_agora.so"
doNotStrip "*/*/libmrtc_core.so"
doNotStrip "*/*/libmrtc_core_jni.so"
doNotStrip "*/*/libmrtc_data.so"
doNotStrip "*/*/libmrtc_log.so"
doNotStrip "*/*/libmrtc_onvif.so"
doNotStrip "*/*/libmrtc_rtmp.so"
doNotStrip "*/*/libmrtc_rtsp.so"
}
buildFeatures {
viewBinding true
}
configurations {
cleanedAnnotations
implementation.exclude group: 'org.jetbrains', module: 'annotations'
}
namespace 'com.aros.apron'
}
dependencies {
implementation project(":android-sdk-v5-uxsdk")
implementation "com.dji:dji-sdk-v5-aircraft:$SDK_VERSION"
compileOnly "com.dji:dji-sdk-v5-aircraft-provided:$SDK_VERSION"
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.7.1"
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-common-java8:2.3.1'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'
implementation 'androidx.lifecycle:lifecycle-process:2.5.1'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation "androidx.fragment:fragment-ktx:1.3.3"
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation files('libs\\dom4j-2.1.4.jar')
implementation project(':opencv')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation 'com.yanzhenjie:permission:2.0.3'
implementation 'com.commonsware.cwac:saferoom.x:1.3.0'
// implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.10')
// implementation 'org.jetbrains.kotlin:kotlin-stdlib' //
// 2. jdk7/jdk8
configurations.all {
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
}
implementation 'com.dji:dji-sdk-v5-aircraft:5.15.0'
compileOnly 'com.dji:dji-sdk-v5-aircraft-provided:5.15.0'
implementation 'com.dji:dji-sdk-v5-networkImp:5.15.0'
// implementation 'com.shd:dji-uxsdk:5.9.1'
implementation 'com.squareup.okio:okio:1.15.0'
implementation 'com.squareup.wire:wire-runtime:2.2.0'
implementation 'com.airbnb.android:lottie:3.3.1'
implementation 'com.iqiyi.xcrash:xcrash-android-lib:3.1.0'
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.0'
implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
implementation 'org.greenrobot:eventbus:3.1.1'
implementation 'com.orhanobut:logger:2.1.1'
api 'com.squareup.retrofit2:retrofit:2.9.0'
api 'com.squareup.retrofit2:converter-gson:2.9.0'
api 'com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.9'
implementation 'com.google.protobuf:protobuf-javalite:4.0.0-rc-2'
// implementation 'com.thoughtworks.xstream:xstream:1.4.20'
implementation 'com.tencent.bugly:crashreport:4.0.4'
//latest.release指代最新Bugly SDK版本号4.0.3
implementation 'com.amap.api:3dmap:7.3.0'
implementation 'com.amap.api:search:7.3.0'
implementation 'io.reactivex.rxjava3:rxkotlin:3.0.0'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//H264推流
// implementation 'com.github.pedroSG94.RootEncoder:library:2.3.3'
//amazonaws
implementation 'com.amazonaws:aws-android-sdk-s3:2.72.0'
implementation 'com.amazonaws:aws-android-sdk-mobile-client:2.72.0'
// implementation 'io.minio:minio:8.3.7'
////
// implementation 'com.github.licheedev:Android-SerialPort-API:2.0.0'
// // modbus4j
// implementation 'com.github.licheedev:modbus4j:v3.0.6-alpha1'
// implementation 'com.github.licheedev:Modbus4Android:2.0.2'
// implementation 'com.quickbirdstudios:opencv-contrib:4.5.3.0'
//implementation 'com.quickbirdstudios:opencv-contrib:3.4.5'
implementation project(path: ':android-sdk-v5-uxsdk')
}

BIN
app/libs/dom4j-2.1.4.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

172
app/proguard-rules.pro vendored
View File

@ -1,21 +1,157 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
-keepattributes Exceptions,InnerClasses,*Annotation*,Signature,EnclosingMethod
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-dontshrink
-dontoptimize
-dontpreverify
-dontnote
-ignorewarnings
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
-keepclassmembers enum * {
public static <methods>;
}
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# 避免混淆Annotation内部类泛型匿名类
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod
-keep class com.aros.apron.entity.** { *; }
-keep class com.aros.apron.callback.** { *; }
# 保持Paho MQTT库的关键类不被混淆
-keep class org.eclipse.paho.** { *; }
-keepclassmembers class org.eclipse.paho.** { *; }
-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
-keep class * extends android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}
-keep,allowshrinking class * extends dji.publics.DJIUI.** {
public <methods>;
}
#加固后的AAR其内容无法被混淆工具识别所以MSDK外部依赖的类必须被Keep
-keep class net.sqlcipher.** { *; }
-keep class net.sqlcipher.database.* { *; }
-keep class dji.** { *; }
-keep class com.dji.** { *; }
-keep class djimrtc.** { *; }
-keep class com.google.** { *; }
-keep class org.bouncycastle.** { *; }
-keep class org.** { *; }
-keep class com.squareup.wire.** { *; }
-keep class sun.misc.Unsafe { *; }
-keep class com.secneo.** {*;}
-keep class org.greenrobot.eventbus.**{*;}
-keep class com.commonsware.**{*;}
-keep class io.reactivex.**{*;}
-keep class okhttp3.**{*;}
-keep class okio.**{*;}
-keep class org.bouncycastle.**{*;}
-keep class sun.**{*;}
-keep class java.**{*;}
-keep class com.amap.api.**{*;}
-keep class com.here.**{*;}
-keep class com.mapbox.**{*;}
-keep class retrofit2.**{*;}
-keepclasseswithmembers,allowshrinking class * {
native <methods>;
}
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keep class androidx.appcompat.widget.SearchView { *; }
-keepclassmembers class * extends android.app.Service
-keepclassmembers public class * extends android.view.View {
void set*(***);
*** get*();
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keep class kotlin.** { *; }
-keep class androidx.** { *; }
-keep class android.** { *; }
-keep class com.android.** { *; }
-keep class android.media.** { *; }
-keep class okio.** { *; }
-keep class com.lmax.disruptor.** {
*;
}
-dontwarn com.mapbox.services.android.location.LostLocationEngine
-dontwarn com.mapbox.services.android.location.MockLocationEngine
-keepclassmembers class * implements android.arch.lifecycle.LifecycleObserver {
<init>(...);
}
# ViewModel's empty constructor is considered to be unused by proguard
-keepclassmembers class * extends android.arch.lifecycle.ViewModel {
<init>(...);
}
# keep Lifecycle State and Event enums values
-keepclassmembers class android.arch.lifecycle.Lifecycle$State { *; }
-keepclassmembers class android.arch.lifecycle.Lifecycle$Event { *; }
# keep methods annotated with @OnLifecycleEvent even if they seem to be unused
# (Mostly for LiveData.LifecycleBoundObserver.onStateChange(), but who knows)
-keepclassmembers class * {
@android.arch.lifecycle.OnLifecycleEvent *;
}
-keepclassmembers class * implements android.arch.lifecycle.LifecycleObserver {
<init>(...);
}
-keep class * implements android.arch.lifecycle.LifecycleObserver {
<init>(...);
}
-keepclassmembers class android.arch.** { *; }
-keep class android.arch.** { *; }
-dontwarn android.arch.**
#<------------ utmiss config start------------>
-keep class dji.sdk.utmiss.** { *; }
-keep class utmisslib.** { *; }
#<------------ utmiss config end------------>
# 地图相关
-keep class com.dji.mapkit.amap.provider.AMapProvider {*;}
-keep class com.dji.mapkit.maplibre.provider.MapLibreProvider {*;}
-keep class com.dji.mapkit.core.** {*;}
-keep class com.autonavi.** {*;}
-keep class com.alibaba.fastjson.**{*;}
## keep 千寻相关接口
-keep class com.qx.wz.dj.rtcm.** {*;}
# 在项目的proguard-rules.pro文件中添加以下规则
# 排除OpenCV的.so文件
-keep class org.opencv.** { *; }
-keep class org.opencv.engine.** { *; }
-keep class org.opencv.imgproc.** { *; }
-keep class org.opencv.core.** { *; }
-keep class org.opencv.features2d.** { *; }
-keep class org.opencv.ml.** { *; }
-keep class org.opencv.photo.** { *; }
-keep class org.opencv.video.** { *; }
-keep class org.opencv.calib3d.** { *; }
-keep class org.opencv.utils.** { *; }
-keep class org.opencv.flann.** { *; }
-keep class org.opencv.objdetect.** { *; }
-keep class org.opencv.xfeatures2d.** { *; }
-keep class org.opencv.ximgproc.** { *; }
-keep class org.opencv.xphoto.** { *; }
# 如果你有自定义的OpenCV类确保也要保证这些类不被混淆
-keep class com.example.opencv.** { *; }

View File

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.aros.apron",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 46,
"versionName": "v1.9.1",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

View File

@ -1,24 +0,0 @@
package com.example.makcar
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.example.makcar", appContext.packageName)
}
}

View File

@ -1,51 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!-- bugly -->
<uses-permission android:name="android.permission.READ_LOGS" />
<!-- 开机启动所需权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-feature
android:name="android.hardware.usb.host"
android:required="false" />
android:required="false"/>
<uses-feature
android:name="android.hardware.usb.accessory"
android:required="true" />
android:required="true"/>
<application
android:screenOrientation="landscape"
android:name=".MyApplication"
android:name="com.aros.apron.app.ApronApp"
android:largeHeap = "true"
android:hardwareAccelerated = "false"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:icon="@mipmap/app_icon"
android:label="@string/appName"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Makcar"
tools:targetApi="31">
android:theme="@style/Theme.ApronV5"
android:requestLegacyExternalStorage="true"
android:networkSecurityConfig="@xml/network_security_config"
>
<!-- AMaps -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="988f506b616b82b02e4d656c9b20c82f" />
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="d237f2b4554af77800e894d2"/>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
<activity
android:name=".LoadingPage"
android:name=".activity.ConnectionActivity"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="@xml/accessory_filter" />
</activity>
<meta-data
android:name="com.dji.sdk.API_KEY"
android:value="9c7503f4b88032fe08905212" />
<activity
android:name=".MainActivity"
android:name=".activity.MediaActivity"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:exported="true">
</activity>
<activity
android:name=".activity.ConfigActivity"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:exported="true">
</activity>
<activity
android:name=".activity.MainActivity"
android:configChanges="orientation"
android:screenOrientation="landscape"
android:windowSoftInputMode="stateAlwaysHidden"
android:exported="true">
</activity>
<service android:name="org.eclipse.paho.android.service.MqttService" />
<!-- 开机启动 -->
<receiver
android:name=".receiver.AutoStartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!--.接收启动完成的广播-->
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<service android:name="com.amazonaws.mobileconnectors.s3.transferutility.TransferService" android:enabled="true" />
</application>
</manifest>

View File

@ -0,0 +1,381 @@
package com.aros.apron.activity
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.widget.CompoundButton.GONE
import android.widget.CompoundButton.VISIBLE
import com.aros.apron.base.BaseActivity
import com.aros.apron.databinding.ActivityConfigBinding
import com.aros.apron.tools.LogUtil
import com.aros.apron.tools.PreferenceUtils
import com.aros.apron.tools.RestartAPPTool.restartApp
import com.aros.apron.tools.ToastUtil
import dji.sdk.keyvalue.key.FlightControllerKey
import dji.sdk.keyvalue.key.KeyTools
import dji.v5.manager.KeyManager
class ConfigActivity : BaseActivity() {
private lateinit var configBinding: ActivityConfigBinding
override fun useEventBus(): Boolean {
return false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
configBinding = ActivityConfigBinding.inflate(layoutInflater)
setContentView(configBinding.root)
initView()
LogUtil.log(TAG,"进入AMS配置界面")
}
private fun initView() {
configBinding.cbHaveRtk.isChecked = PreferenceUtils.getInstance().haveRTK
configBinding.cbLteEnable.isChecked = PreferenceUtils.getInstance().lteEnable
configBinding.cbCloseObstacle.isChecked = PreferenceUtils.getInstance().closeObsEnable
configBinding.cbDebuggingMode.isChecked = PreferenceUtils.getInstance().isDebugMode
configBinding.cbCleanMode.isChecked = PreferenceUtils.getInstance().isCleanMode
configBinding.cbLEDsSettings.isChecked = PreferenceUtils.getInstance().navigationLEDsOn
configBinding.rbRtkCustom.isChecked = PreferenceUtils.getInstance().rtkType == 1
configBinding.rbRtkDji.isChecked = PreferenceUtils.getInstance().rtkType == 2
configBinding.layoutRtkCustom.visibility =
if (PreferenceUtils.getInstance().rtkType == 1) VISIBLE else {
GONE
}
configBinding.rbRtkCustom.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
configBinding.layoutRtkCustom.visibility = VISIBLE
} else {
configBinding.layoutRtkCustom.visibility = GONE
}
}
configBinding.rbRtsp.isChecked = PreferenceUtils.getInstance().customStreamType==1
configBinding.rbRtmp.isChecked = PreferenceUtils.getInstance().customStreamType==2
configBinding.rbNo.isChecked = PreferenceUtils.getInstance().customStreamType==3
configBinding.layoutStreamRtsp.visibility =
if (PreferenceUtils.getInstance().customStreamType==1) VISIBLE else {
GONE
}
configBinding.layoutStream.visibility =
if (PreferenceUtils.getInstance().customStreamType==2) VISIBLE else {
GONE
}
configBinding.rbRtsp.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
configBinding.layoutStreamRtsp.visibility = VISIBLE
} else {
configBinding.layoutStreamRtsp.visibility = GONE
}
}
configBinding.rbRtmp.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
configBinding.layoutStream.visibility = VISIBLE
} else {
configBinding.layoutStream.visibility = GONE
}
}
configBinding.rbNo.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
configBinding.layoutStream.visibility = GONE
configBinding.layoutStreamRtsp.visibility = GONE
}
}
configBinding.etStreamUrl.setText(PreferenceUtils.getInstance().customStreamUrl)
configBinding.etRtspUserName.setText(PreferenceUtils.getInstance().rtspUserName)
configBinding.etRtspPassword.setText(PreferenceUtils.getInstance().rtspPassWord)
configBinding.etRtspPort.setText(PreferenceUtils.getInstance().rtspPort)
configBinding.etNtrip.setText(PreferenceUtils.getInstance().ntrip)
configBinding.etNtrPort.setText(PreferenceUtils.getInstance().ntrPort)
configBinding.etNtrAccount.setText(PreferenceUtils.getInstance().ntrAccount)
configBinding.etNtrPassword.setText(PreferenceUtils.getInstance().ntrPassword)
configBinding.etNtrMountpoint.setText(PreferenceUtils.getInstance().ntrMountPoint)
configBinding.etMqttServerUri.setText(PreferenceUtils.getInstance().mqttServerUri)
configBinding.etMqttUsername.setText(PreferenceUtils.getInstance().mqttUserName)
configBinding.etMqttPassword.setText(PreferenceUtils.getInstance().mqttPassword)
configBinding.etMqttSn.setText(PreferenceUtils.getInstance().mqttSn)
configBinding.etMinioUploadUrl.setText(PreferenceUtils.getInstance().uploadUrl)
configBinding.etMinioBucketName.setText(PreferenceUtils.getInstance().bucketName)
configBinding.etMinioObjectKey.setText(PreferenceUtils.getInstance().objectKey)
configBinding.etMinioAccessKey.setText(PreferenceUtils.getInstance().accessKey)
configBinding.etMinioSecretKey.setText(PreferenceUtils.getInstance().secretKey)
// configBinding.etDockerLat.setText(PreferenceUtils.getInstance().dockerLat)
// configBinding.etDockerLon.setText(PreferenceUtils.getInstance().dockerLon)
// configBinding.etAircraftHeading.setText(PreferenceUtils.getInstance().aircraftHeading)
configBinding.etMinimumBattery.setText(PreferenceUtils.getInstance().minumumBattery)
configBinding.etForcedBattery.setText(PreferenceUtils.getInstance().forcedBattery)
configBinding.etSetAlternateTimes.setText(PreferenceUtils.getInstance().alternatePointTimes)
configBinding.cbNeedUploadVideo.isChecked = PreferenceUtils.getInstance().needUpLoadVideo
when (PreferenceUtils.getInstance().missionInterruptAction) {
1 -> configBinding.rbHover.isChecked = true
2 -> configBinding.rbResume.isChecked = true
3 -> configBinding.rbGohome.isChecked = true
}
configBinding.rbRtkFirst.isChecked = PreferenceUtils.getInstance().landType == 1
configBinding.rbVisionFirst.isChecked = PreferenceUtils.getInstance().landType == 2
configBinding.rbGps.isChecked = PreferenceUtils.getInstance().satelliteSystem == 1
configBinding.rbBeidou.isChecked = PreferenceUtils.getInstance().satelliteSystem == 2
configBinding.rbCameraCenter.isChecked = PreferenceUtils.getInstance().cameraLocationType ==1//中间
configBinding.rbCameraRight.isChecked = PreferenceUtils.getInstance().cameraLocationType ==2//右边
configBinding.btnConfig.setOnClickListener { config() }
configBinding.tvSetAircraftLoc.setOnClickListener {
val isConnect = KeyManager.getInstance()
.getValue(KeyTools.createKey(FlightControllerKey.KeyConnection))
if (isConnect != null && isConnect) {
var locationCoordinate3D = KeyManager.getInstance()
.getValue(KeyTools.createKey(FlightControllerKey.KeyAircraftLocation3D))
if (locationCoordinate3D != null) {
configBinding.etDockerLat.setText(locationCoordinate3D?.latitude.toString())
configBinding.etDockerLon.setText(locationCoordinate3D?.longitude.toString())
configBinding.etAircraftHeading.setText("假数据")
} else {
configBinding.etDockerLat.setText("")
configBinding.etDockerLon.setText("")
configBinding.etAircraftHeading.setText("")
ToastUtil.showToast("获取机库位置失败")
}
} else {
ToastUtil.showToast("设备未连接")
}
}
}
private fun config() {
if (configBinding.rbRtkCustom.isChecked) {
if (TextUtils.isEmpty(configBinding.etNtrip.text)) {
ToastUtil.showToast("未配置网络RTK地址")
return
}
if (TextUtils.isEmpty(configBinding.etNtrPort.text)) {
ToastUtil.showToast("未配置网络RTK端口")
return
}
if (TextUtils.isEmpty(configBinding.etNtrAccount.text)) {
ToastUtil.showToast("未配置网络RTK账户")
return
}
if (TextUtils.isEmpty(configBinding.etNtrPassword.text)) {
ToastUtil.showToast("未配置网络RTK密码")
return
}
if (TextUtils.isEmpty(configBinding.etNtrMountpoint.text)) {
ToastUtil.showToast("未配置网络RTK挂载点")
return
}
}
if (configBinding.cbHaveRtk.isChecked) {
if (!configBinding.rbRtkCustom.isChecked && !configBinding.rbRtkDji.isChecked) {
ToastUtil.showToast("未配置RTK类型")
return
}
}
if (TextUtils.isEmpty(configBinding.etMqttServerUri.text)) {
ToastUtil.showToast("未配置MQTT服务器地址")
return
}
if (TextUtils.isEmpty(configBinding.etMqttUsername.text)) {
ToastUtil.showToast("未配置MQTT用户名")
return
}
if (TextUtils.isEmpty(configBinding.etMqttPassword.text)) {
ToastUtil.showToast("未配置MQTT密码")
return
}
if (TextUtils.isEmpty(configBinding.etMqttSn.text)) {
ToastUtil.showToast("未配置MQTT设备编号")
return
}
if (TextUtils.isEmpty(configBinding.etMinioUploadUrl.text)) {
ToastUtil.showToast("未配置minio文件上传地址")
return
}
if (TextUtils.isEmpty(configBinding.etMinioBucketName.text)) {
ToastUtil.showToast("未配置minio桶名")
return
}
if (TextUtils.isEmpty(configBinding.etMinioObjectKey.text)) {
ToastUtil.showToast("未配置minio ObjectKey")
return
}
if (TextUtils.isEmpty(configBinding.etMinioAccessKey.text)) {
ToastUtil.showToast("未配置minio AccessKey")
return
}
if (TextUtils.isEmpty(configBinding.etMinioSecretKey.text)) {
ToastUtil.showToast("未配置minio SecretKey")
return
}
if (!configBinding.rbHover.isChecked && !configBinding.rbResume.isChecked && !configBinding.rbGohome.isChecked) {
ToastUtil.showToast("未配置航线中断动作")
return
}
if (!configBinding.rbRtkFirst.isChecked && !configBinding.rbVisionFirst.isChecked) {
ToastUtil.showToast("至少配置一种降落方式")
return
}
if (configBinding.rbRtkFirst.isChecked) {
if (!configBinding.cbHaveRtk.isChecked) {
ToastUtil.showToast("RTK优先需配置RTK模块")
return
}
}
if (!configBinding.rbCameraRight.isChecked && !configBinding.rbCameraCenter.isChecked) {
ToastUtil.showToast("未配置主相机位置")
return
}
if (configBinding.rbRtsp.isChecked) {
if (TextUtils.isEmpty(configBinding.etRtspUserName.text)) {
ToastUtil.showToast("未配置Rtsp用户名")
return
}
if (TextUtils.isEmpty(configBinding.etRtspPassword.text)) {
ToastUtil.showToast("未配置Rtsp密码")
return
}
if (TextUtils.isEmpty(configBinding.etRtspPort.text)) {
ToastUtil.showToast("未配置Rtsp端口")
return
}
}
// if (TextUtils.isEmpty(configBinding.etDockerLat.text) || TextUtils.isEmpty(configBinding.etDockerLon.text)
// || TextUtils.isEmpty(configBinding.etAircraftHeading.text)) {
// ToastUtil.showToast("未标定起飞朝向")
// return
// }
if (TextUtils.isEmpty(configBinding.etMinimumBattery.text) || TextUtils.isEmpty(configBinding.etForcedBattery.text)) {
ToastUtil.showToast("未配置电池阈值")
return
}
var minimumBattery=configBinding.etMinimumBattery.text.toString()
var forcedBattery=configBinding.etForcedBattery.text.toString()
if (minimumBattery.toInt()<35){
ToastUtil.showToast("允许起飞电量不得低于35%")
return
}
if (forcedBattery.toInt()>=minimumBattery.toInt()){
ToastUtil.showToast("强制返航电量需小于允许起飞电量")
return
}
if ((minimumBattery.toInt()-forcedBattery.toInt())<10){
ToastUtil.showToast("强制返航电量需小于允许起飞电量最少10%")
return
}
PreferenceUtils.getInstance().minumumBattery =
configBinding.etMinimumBattery.text.toString()
PreferenceUtils.getInstance().forcedBattery =
configBinding.etForcedBattery.text.toString()
PreferenceUtils.getInstance().alternatePointTimes =
configBinding.etSetAlternateTimes.text.toString()
PreferenceUtils.getInstance().setHaveRtk(configBinding.cbHaveRtk.isChecked)
PreferenceUtils.getInstance().closeObsEnable = configBinding.cbCloseObstacle.isChecked
if (configBinding.rbRtkCustom.isChecked) {
PreferenceUtils.getInstance().rtkType = 1
} else if (configBinding.rbRtkDji.isChecked) {
PreferenceUtils.getInstance().rtkType = 2
} else {
PreferenceUtils.getInstance().rtkType = -1
}
PreferenceUtils.getInstance().isDebugMode = configBinding.cbDebuggingMode.isChecked
PreferenceUtils.getInstance().isCleanMode = configBinding.cbCleanMode.isChecked
PreferenceUtils.getInstance().navigationLEDsOn = configBinding.cbLEDsSettings.isChecked
PreferenceUtils.getInstance().lteEnable = configBinding.cbLteEnable.isChecked
if (configBinding.rbRtsp.isChecked) {
PreferenceUtils.getInstance().customStreamType = 1
} else if (configBinding.rbRtmp.isChecked) {
PreferenceUtils.getInstance().customStreamType = 2
} else if (configBinding.rbNo.isChecked) {
PreferenceUtils.getInstance().customStreamType = 3
} else {
PreferenceUtils.getInstance().rtkType = -1
}
if (configBinding.rbRtmp.isChecked) {
PreferenceUtils.getInstance().customStreamUrl =
configBinding.etStreamUrl.text.toString().replace("", "")
}
if (configBinding.rbRtsp.isChecked) {
PreferenceUtils.getInstance().rtspUserName =
configBinding.etRtspUserName.text.toString().replace("", "")
PreferenceUtils.getInstance().rtspPassWord =
configBinding.etRtspPassword.text.toString().replace("", "")
PreferenceUtils.getInstance().rtspPort =
configBinding.etRtspPort.text.toString().replace("", "")
}
PreferenceUtils.getInstance().ntrip = configBinding.etNtrip.text.toString().replace(" ", "")
PreferenceUtils.getInstance().ntrPort =
configBinding.etNtrPort.text.toString().replace(" ", "")
PreferenceUtils.getInstance().ntrAccount =
configBinding.etNtrAccount.text.toString().replace(" ", "")
PreferenceUtils.getInstance().ntrPassword =
configBinding.etNtrPassword.text.toString().replace(" ", "")
PreferenceUtils.getInstance().ntrMountPoint =
configBinding.etNtrMountpoint.text.toString().replace(" ", "")
PreferenceUtils.getInstance().mqttServerUri =
configBinding.etMqttServerUri.text.toString().replace(" ", "")
PreferenceUtils.getInstance().mqttUserName =
configBinding.etMqttUsername.text.toString().replace(" ", "")
PreferenceUtils.getInstance().mqttPassword =
configBinding.etMqttPassword.text.toString().replace(" ", "")
PreferenceUtils.getInstance().mqttSn =
configBinding.etMqttSn.text.toString().replace(" ", "")
PreferenceUtils.getInstance().uploadUrl =
configBinding.etMinioUploadUrl.text.toString().replace(" ", "")
PreferenceUtils.getInstance().bucketName =
configBinding.etMinioBucketName.text.toString().replace(" ", "")
PreferenceUtils.getInstance().objectKey =
configBinding.etMinioObjectKey.text.toString().replace(" ", "")
PreferenceUtils.getInstance().accessKey =
configBinding.etMinioAccessKey.text.toString().replace(" ", "")
PreferenceUtils.getInstance().secretKey =
configBinding.etMinioSecretKey.text.toString().replace(" ", "")
PreferenceUtils.getInstance().needUpLoadVideo = configBinding.cbNeedUploadVideo.isChecked
if (configBinding.rbHover.isChecked) {
PreferenceUtils.getInstance().missionInterruptAction = 1
} else if (configBinding.rbResume.isChecked) {
PreferenceUtils.getInstance().missionInterruptAction = 2
} else {
PreferenceUtils.getInstance().missionInterruptAction = 3
}
if (configBinding.rbVisionFirst.isChecked) {
PreferenceUtils.getInstance().landType = 2
} else {
PreferenceUtils.getInstance().landType = 1
}
if (configBinding.rbGps.isChecked) {
PreferenceUtils.getInstance().satelliteSystem = 1
} else {
PreferenceUtils.getInstance().satelliteSystem = 2
}
if (configBinding.rbCameraCenter.isChecked) {
PreferenceUtils.getInstance().cameraLocationType = 1
} else {
PreferenceUtils.getInstance().cameraLocationType = 2
}
ToastUtil.showToast("配置已保存")
Handler().postDelayed(Runnable {
restartApp()
}, 1000)
}
}

View File

@ -0,0 +1,377 @@
package com.aros.apron.activity
import android.Manifest
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.aros.apron.R
import com.aros.apron.app.ApronApp
import com.aros.apron.base.BaseActivity
import com.aros.apron.constant.AMSConfig
import com.aros.apron.databinding.ActivityConnectionBinding
import com.aros.apron.models.MSDKInfoVm
import com.aros.apron.models.MSDKManagerVM
import com.aros.apron.models.globalViewModels
import com.aros.apron.tools.LogUtil
import com.aros.apron.tools.MqttManager
import com.aros.apron.tools.PreferenceUtils
import com.aros.apron.tools.RestartAPPTool.restartApp
import com.aros.apron.tools.ToastUtil
import com.tencent.bugly.crashreport.CrashReport
import com.yanzhenjie.permission.AndPermission
import dji.sdk.keyvalue.key.CameraKey
import dji.sdk.keyvalue.key.DJIKey
import dji.sdk.keyvalue.key.FlightControllerKey
import dji.sdk.keyvalue.key.KeyTools
import dji.sdk.keyvalue.value.camera.CameraType
import dji.sdk.keyvalue.value.common.ComponentIndexType
import dji.v5.manager.KeyManager
import dji.v5.utils.common.StringUtils
open class ConnectionActivity : BaseActivity() {
private val REQUIRED_PERMISSION_LIST = arrayOf(
Manifest.permission.VIBRATE,
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_WIFI_STATE,
Manifest.permission.WAKE_LOCK,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_NETWORK_STATE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.CHANGE_WIFI_STATE,
Manifest.permission.CHANGE_NETWORK_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
// Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS,
// Manifest.permission.WRITE_SETTINGS,
Manifest.permission.BLUETOOTH,
Manifest.permission.BLUETOOTH_ADMIN,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO
)
private val msdkInfoVm: MSDKInfoVm by viewModels()
private val TAG="ConnectionActivity"
private val msdkManagerVM: MSDKManagerVM by globalViewModels()
private lateinit var connectionBinding: ActivityConnectionBinding
private val handler: Handler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
connectionBinding = ActivityConnectionBinding.inflate(layoutInflater)
setContentView(connectionBinding.root)
window.decorView.apply {
systemUiVisibility =
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
initMSDKInfoView()
checkAndRequestPermissions()
connectionBinding.config?.setOnClickListener {
startActivity(Intent(this, ConfigActivity::class.java))
}
// Utils.sHA1(this)
//默认自动启动辅助服务
// Settings.Secure.putString(
// contentResolver,
// Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
// "${packageName}/${BluetoothAccessibilityService::class.java.canonicalName}"
// )
// Settings.Secure.putInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, 1);
// //开启蓝牙辅助服务
// Intent(this@ConnectionActivity, BluetoothAccessibilityService::class.java).also {
// LogUtil.log("ConnectionActivity", "start BluetoothAccessibilityService")
// startService(it)
// }
initBugly()
initConfig()
}
private fun initConfig(){
if (TextUtils.isEmpty(PreferenceUtils.getInstance().forcedBattery)){
PreferenceUtils.getInstance().forcedBattery =
"20"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().minumumBattery)){
PreferenceUtils.getInstance().minumumBattery =
"35"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().mqttServerUri)){
PreferenceUtils.getInstance().mqttServerUri =
//"tcp://192.168.2.90:2883"
"tcp://broker.emqx.io"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().mqttUserName)){
PreferenceUtils.getInstance().mqttUserName =
"admin"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().mqttPassword)){
PreferenceUtils.getInstance().mqttPassword =
"Admin123"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().mqttSn)){
PreferenceUtils.getInstance().mqttSn =
"1"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().uploadUrl)){
PreferenceUtils.getInstance().uploadUrl =
"http://192.168.2.90:9090"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().bucketName)){
PreferenceUtils.getInstance().bucketName =
"media"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().objectKey)){
PreferenceUtils.getInstance().objectKey =
"1"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().accessKey)){
PreferenceUtils.getInstance().accessKey =
"aros"
}
if (TextUtils.isEmpty(PreferenceUtils.getInstance().secretKey)){
PreferenceUtils.getInstance().secretKey =
"Aros2023"
}
if (PreferenceUtils.getInstance().satelliteSystem!=2){
PreferenceUtils.getInstance().satelliteSystem =
1
}
}
private fun initBugly() {
//bugly
CrashReport.UserStrategy(this).apply {
appPackageName = packageName
isEnableANRCrashMonitor = true
isEnableCatchAnrTrace = true
setCrashHandleCallback(object : CrashReport.CrashHandleCallback() {
override fun onCrashHandleStart(
crashType: Int, errorType: String,
errorMessage: String, errorStack: String
): Map<String, String> {
return mapOf()
}
override fun onCrashHandleStart2GetExtraDatas(
crashType: Int, errorType: String,
errorMessage: String, errorStack: String
): ByteArray {
LogUtil.log("---crash----", "\n" + errorMessage + "\n" + errorStack)
//如果处理了让主程序继续运行3秒再退出保证异步的写操作能及时完成
try {
Thread.sleep((1000).toLong())
} catch (e: InterruptedException) {
e.printStackTrace()
}
restartApp()
return "autoRestart".toByteArray(charset("UTF-8"))
}
})
CrashReport.setAllThreadStackEnable(ApronApp.context, true, true)
// CrashReport.initCrashReport(context, "5894201d87", true, this)
CrashReport.initCrashReport(ApronApp.context, "67f68269b0", true, this)
}
}
@SuppressLint("SetTextI18n")
private fun initMSDKInfoView() {
msdkInfoVm.msdkInfo.observe(this) {
connectionBinding.textViewVersion.text =
StringUtils.getResStr(R.string.sdk_version, it.SDKVersion + " " + it.buildVer)
connectionBinding.textViewProductName.text =
StringUtils.getResStr(R.string.product_name, it.productType.name)
connectionBinding.textViewPackageProductCategory.text =
StringUtils.getResStr(R.string.package_product_category, it.packageProductCategory)
connectionBinding.textViewIsDebug.text =
StringUtils.getResStr(R.string.is_sdk_debug, it.isDebug)
}
// 获取当前应用的 PackageManager 实例
val packageManager = packageManager
// 获取当前应用的 PackageInfo 对象
val packageInfo = packageManager.getPackageInfo(packageName, 0)
// 获取版本名
val versionName = packageInfo.versionName
connectionBinding.textViewAmsVersion?.text=versionName
}
private var checkTimes=0
private fun observeSDKManagerStatus() {
msdkManagerVM.lvRegisterState.observe(this) { resultPair ->
val statusText: String?
if (resultPair.first) {
statusText = StringUtils.getResStr(this, R.string.registered)
msdkInfoVm.initListener()
// connectionBinding.defaultLayoutButton.isEnabled = true
// enableShowCaseButton(
// connectionBinding.defaultLayoutButton,
// MainActivity::class.java
// )
if (TextUtils.isEmpty(PreferenceUtils.getInstance().mqttServerUri)
|| TextUtils.isEmpty(PreferenceUtils.getInstance().mqttUserName)
|| TextUtils.isEmpty(PreferenceUtils.getInstance().mqttPassword)
|| TextUtils.isEmpty(PreferenceUtils.getInstance().mqttSn)
) {
ToastUtil.showToast("未配置MQTT参数")
LogUtil.log(TAG, "未配置MQTT参数")
} else if(TextUtils.isEmpty(PreferenceUtils.getInstance().uploadUrl)||
TextUtils.isEmpty(PreferenceUtils.getInstance().bucketName)||
TextUtils.isEmpty(PreferenceUtils.getInstance().objectKey)||
TextUtils.isEmpty(PreferenceUtils.getInstance().accessKey)||
TextUtils.isEmpty(PreferenceUtils.getInstance().secretKey)){
ToastUtil.showToast("minio参数配置有误")
LogUtil.log(TAG, "minio参数配置有误")
}else if (PreferenceUtils.getInstance().haveRTK &&PreferenceUtils.getInstance().rtkType!=1&&PreferenceUtils.getInstance().rtkType!=2 ){
LogUtil.log(TAG, "未配置RTK类型")
ToastUtil.showToast("未配置RTK类型")
}else if (PreferenceUtils.getInstance().haveRTK &&PreferenceUtils.getInstance().rtkType==1&& (TextUtils.isEmpty(
PreferenceUtils.getInstance().ntrip
) ||
TextUtils.isEmpty(PreferenceUtils.getInstance().ntrAccount) ||
TextUtils.isEmpty(PreferenceUtils.getInstance().ntrPassword) ||
TextUtils.isEmpty(PreferenceUtils.getInstance().ntrMountPoint))
) {
LogUtil.log(TAG, "未配置网络RTK参数")
ToastUtil.showToast("未配置网络RTK参数")
} else if (PreferenceUtils.getInstance().landType != 1 && PreferenceUtils.getInstance().landType != 2) {
ToastUtil.showToast("未配置降落方式")
LogUtil.log(TAG, "未配置降落方式")
} else if (PreferenceUtils.getInstance().landType == 1 && !PreferenceUtils.getInstance().haveRTK) {
ToastUtil.showToast("RTK降落未配置网络RTK参数")
LogUtil.log(TAG, "RTK降落未配置网络RTK参数")
} else if (PreferenceUtils.getInstance().customStreamType==2&&TextUtils.isEmpty(PreferenceUtils.getInstance().customStreamUrl)) {
ToastUtil.showToast("未配置自定义推流地址")
LogUtil.log(TAG, "未配置自定义推流地址")
}else if (PreferenceUtils.getInstance().customStreamType==1&&
(TextUtils.isEmpty(PreferenceUtils.getInstance().rtspUserName)
||TextUtils.isEmpty(PreferenceUtils.getInstance().rtspPassWord)
||TextUtils.isEmpty(PreferenceUtils.getInstance().rtspPort))) {
ToastUtil.showToast("未配置rtsp参数")
LogUtil.log(TAG, "未配置rtsp参数")
}else if (PreferenceUtils.getInstance().cameraLocationType == 0){
ToastUtil.showToast("未配置主相机位置")
LogUtil.log(TAG, "未配置主相机位置")
}else if (TextUtils.isEmpty(PreferenceUtils.getInstance().minumumBattery)||
TextUtils.isEmpty(PreferenceUtils.getInstance().forcedBattery)) {
ToastUtil.showToast("未配置允许起飞或强制返航电量阈值")
LogUtil.log(TAG, "未配置允许起飞或强制返航电量阈值")
}else if (TextUtils.isEmpty(PreferenceUtils.getInstance().alternatePointTimes) ) {
ToastUtil.showToast("未设置最大允许复降次数")
LogUtil.log(TAG, "未设置最大允许复降次数")
}
else {
LogUtil.log(TAG, "已加载AMS配置文件")
AMSConfig.getInstance().mqttServerUri =
PreferenceUtils.getInstance().mqttServerUri
AMSConfig.getInstance().userName = PreferenceUtils.getInstance().mqttUserName
AMSConfig.getInstance().password = PreferenceUtils.getInstance().mqttPassword
AMSConfig.getInstance().serialNumber = PreferenceUtils.getInstance().mqttSn
AMSConfig.getInstance().alternateLandingTimes = PreferenceUtils.getInstance().alternatePointTimes
AMSConfig.getInstance().mqttServer2MsdkTopic =
"nest/${AMSConfig.getInstance().serialNumber}/uav_services"
AMSConfig.getInstance().mqttMsdkReplyMessage2ServerTopic =
"nest/${AMSConfig.getInstance().serialNumber}/uav_services_reply"
AMSConfig.getInstance().mqttMsdkPushMessage2ServerTopic =
"nest/${AMSConfig.getInstance().serialNumber}/uav_status_message"
AMSConfig.getInstance().mqttMsdkPushEvent2ServerTopic =
"nest/${AMSConfig.getInstance().serialNumber}/events"
AMSConfig.getInstance().mqttPSDKPushEvent2ServerTopic =
"nest/${AMSConfig.getInstance().serialNumber}/uav_payload_message"
toMain()
}
} else {
LogUtil.log(TAG, "SDK Register Failure: ${resultPair.second}")
ToastUtil.showToast("Register Failure: ${resultPair.second}")
statusText = StringUtils.getResStr(this, R.string.unregistered)
}
connectionBinding.textViewRegistered.text =
StringUtils.getResStr(R.string.registration_status, statusText)
}
msdkManagerVM.lvProductConnectionState.observe(this) { isConnect ->
}
msdkManagerVM.lvProductChanges.observe(this) { productId ->
ToastUtil.showToast("Product: $productId Changed")
}
msdkManagerVM.lvInitProcess.observe(this) { processPair ->
// ToastUtil.showToast("Init Process event: ${processPair.first.name}")
}
msdkManagerVM.lvDBDownloadProgress.observe(this) { resultPair ->
ToastUtil.showToast("Database Download Progress current: ${resultPair.first}, total: ${resultPair.second}")
}
}
/**
* Checks if there is any missing permissions, and requests runtime permission if needed.
*/
private fun checkAndRequestPermissions() {
AndPermission.with(this)
.runtime()
.permission(REQUIRED_PERMISSION_LIST)
.onGranted {
observeSDKManagerStatus()
}
.onDenied {
// Storage permission are not allowed.
ToastUtil.showToast("请给予app运行所需权限")
finish()
}
.start()
}
private fun toMain(){
// val isFlightControllerConnect =
// KeyManager.getInstance().getValue(DJIKey.create(FlightControllerKey.KeyConnection))
val cameraType = KeyManager.getInstance().getValue(
KeyTools.createKey(
CameraKey.KeyCameraType,
ComponentIndexType.PORT_1
)
)
// if (isFlightControllerConnect == null || !isFlightControllerConnect||cameraType==CameraType.NOT_SUPPORTED) {
// handler.postDelayed({
// toMain()
// }, 1000)
// } else {
// checkTimes++
LogUtil.log(TAG, "飞机是否连接$checkTimes${cameraType?.name}")
if (!MainActivity.isAppStarted) {
startActivity(Intent(this, MainActivity::class.java))
}
// }
}
private fun <T> enableShowCaseButton(view: View, cl: Class<T>) {
view.isEnabled = true
view.setOnClickListener {
Intent(this, cl).also {
startActivity(it)
}
}
}
override fun onResume() {
super.onResume()
LogUtil.log(TAG,"进入首页连接")
}
override fun useEventBus(): Boolean {
return false
}
}

View File

@ -0,0 +1,855 @@
package com.aros.apron.activity
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.os.Message
import android.text.TextUtils
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.BuildConfig
import com.aros.apron.R
import com.aros.apron.base.BaseActivity
import com.aros.apron.callback.MqttCallBack
import com.aros.apron.entity.MQMessage
import com.aros.apron.entity.Movement
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.GimbalManager
import com.aros.apron.manager.LEDsSettingsManager
import com.aros.apron.manager.MLTEManager
import com.aros.apron.manager.MediaManager
import com.aros.apron.manager.MegaphoneManager
import com.aros.apron.manager.MissionManager
import com.aros.apron.manager.NavigationSatelliteSystemManager
import com.aros.apron.manager.OffSiteLandingManager
import com.aros.apron.manager.PayloadWidgetManager
import com.aros.apron.manager.PerceptionManager
import com.aros.apron.manager.RTKManager
import com.aros.apron.manager.RemoteManager
import com.aros.apron.manager.StickManager
import com.aros.apron.manager.StreamManager
import com.aros.apron.manager.WayLineExecutingInterruptManager
import com.aros.apron.tools.AlternateArucoDetect
import com.aros.apron.tools.ApronArucoDetect
import com.aros.apron.tools.DroneHelper
import com.aros.apron.tools.LogUtil
import com.aros.apron.tools.MqttManager
import com.aros.apron.tools.PreferenceUtils
import com.dji.wpmzsdk.manager.WPMZManager
import com.google.gson.Gson
import dji.sdk.keyvalue.key.CameraKey
import dji.sdk.keyvalue.key.DJIKey
import dji.sdk.keyvalue.key.FlightControllerKey
import dji.sdk.keyvalue.key.KeyTools
import dji.sdk.keyvalue.key.ProductKey
import dji.sdk.keyvalue.value.common.CameraLensType
import dji.sdk.keyvalue.value.common.ComponentIndexType
import dji.sdk.keyvalue.value.common.EmptyMsg
import dji.v5.common.callback.CommonCallbacks
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
import org.opencv.objdetect.Dictionary
import org.opencv.objdetect.Objdetect
import java.util.concurrent.TimeUnit
open class MainActivity : BaseActivity() {
companion object {
// 如果不需要改变 isAppStarted 的值,可以直接这样声明
var isAppStarted: Boolean = false
var streamReceive: Boolean = false
}
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
private var mDrawerLayout: DrawerLayout? = null
private var gimbalAdjustDone: TextView? = null
private var btn_test: Button? = null
private var btn_test1: Button? = null
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>) {
runOnUiThread { updateFPVWidgetSource(availableCameraList) }
}
override fun onCameraStreamEnableUpdate(cameraStreamEnableMap: Map<ComponentIndexType, Boolean>) {
//
}
}
private var cameraManager: ICameraStreamManager = MediaDataCenter.getInstance().cameraStreamManager
private var startArucoType = 0 //1执行机库二维码识别 2执行备降点二维码识别
private var dictionary: Dictionary? = null
private var mqMessage: MQMessage? = null
override fun useEventBus(): Boolean {
return true
}
override fun onResume() {
super.onResume()
dictionary = Objdetect.getPredefinedDictionary(Objdetect.DICT_6X6_250)
compositeDisposable = CompositeDisposable()
compositeDisposable!!.add(
systemStatusListPanelWidget!!.closeButtonPressed()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { pressed: Boolean ->
if (pressed) {
systemStatusListPanelWidget!!.hide()
}
})
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!!
)
})
ViewUtil.setKeepScreen(this, true)
}
override fun onPause() {
if (compositeDisposable != null) {
compositeDisposable!!.dispose()
compositeDisposable = null
}
super.onPause()
ViewUtil.setKeepScreen(this, false)
}
//endregion
private fun hideOtherPanels(widget: View?) {
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
}
//大于两路数据
val primarySource = getSuitableSource(cameraList, ComponentIndexType.LEFT_OR_MAIN)
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)
}
}
private fun updateViewVisibility(
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.
*/
private fun swapVideoSource() {
val primarySource = primaryFpvWidget!!.widgetModel.getCameraIndex()
val secondarySource = secondaryFPVWidget!!.widgetModel.getCameraIndex()
//两个source都存在的情况下才进行切换
if (primarySource != ComponentIndexType.UNKNOWN && secondarySource != ComponentIndexType.UNKNOWN) {
primaryFpvWidget!!.updateVideoSource(secondarySource)
secondaryFPVWidget!!.updateVideoSource(primarySource)
}
}
private fun updateInteractionEnabled() {
fpvInteractionWidget!!.isInteractionEnabled = !CameraUtil.isFPVTypeView(
primaryFpvWidget!!.widgetModel.getCameraIndex()
)
}
private data class CameraSource(
val devicePosition: ComponentIndexType,
val lensType: CameraLensType
)
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
// mapWidget = findViewById<MapWidget>(R.id.widget_map)
// mapWidget?.initMapLibreMap(applicationContext, OnMapReadyListener { map: DJIMap ->
// val uiSetting = map.uiSettings
// uiSetting?.setZoomControlsEnabled(false)
// })
// mapWidget?.onCreate(savedInstanceState)
GeoidManager.getInstance().init(this)
WPMZManager.getInstance().init(this)
MqttManager.getInstance().needConnect()
initDJIManager()
initCameraManager()
initCameraStream()
initView()
}
private fun initView() {
fpvParentView = findViewById( R.id.fpv_holder)
mDrawerLayout = findViewById( R.id.root_view)
topBarPanel = findViewById( R.id.panel_top_bar)
settingWidget = topBarPanel?.settingWidget
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)
horizontalSituationIndicatorWidget =
findViewById(R.id.widget_horizontal_situation_indicator)
// gimbalAdjustDone = findViewById<TextView>( R.id.fpv_gimbal_ok_btn)
gimbalFineTuneWidget = findViewById( R.id.setting_menu_gimbal_fine_tune)
btn_test = findViewById( R.id.btn_test)
btn_test1 = findViewById( R.id.btn_test1)
btn_test?.setOnClickListener {
// MissionManager.getInstance().test()
val message = MQMessage().apply {
megaphonePlayMode = 1
msg_type = 60110
megaphoneVolume=100
megaphoneWord="阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1阿罗斯信息技术公司1"
}
MegaphoneManager.getInstance().startMegaphonePlay(message)
}
btn_test1?.setOnClickListener {
// FlightManager.getInstance().stopPropellerRotation(null)
MegaphoneManager.getInstance().stopPlay(null)
}
initClickListener()
MediaDataCenter.getInstance().cameraStreamManager.addAvailableCameraUpdatedListener(
availableCameraUpdatedListener
)
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)
}
private fun isGimableAdjustClicked(broadcastValues: BroadcastValues) {
if (mDrawerLayout!!.isDrawerOpen(GravityCompat.END)) {
mDrawerLayout!!.closeDrawers()
}
horizontalSituationIndicatorWidget!!.visibility = View.GONE
if (gimbalFineTuneWidget != null) {
gimbalFineTuneWidget!!.visibility = View.VISIBLE
}
}
private fun initClickListener() {
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
// }
// }
}
private fun toggleRightDrawer() {
mDrawerLayout!!.openDrawer(GravityCompat.END)
}
override fun onDestroy() {
super.onDestroy()
isAppStarted = false
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)
}
private val handler: Handler = Handler(Looper.getMainLooper())
private var initTimes=0
private fun initDJIManager() {
val isFlightControllerConnect =
KeyManager.getInstance().getValue(DJIKey.create(FlightControllerKey.KeyConnection))
if (isFlightControllerConnect == null || !isFlightControllerConnect) {
handler.postDelayed({
initDJIManager()
}, 1000)
} else {
initTimes++
LogUtil.log(TAG, "初始化$initTimes")
RTKManager.getInstance().initRTKInfo()
StreamManager.getInstance().initStreamManager()
FlightManager.getInstance().initFlightInfo()
MissionManager.getInstance().initMissionManager()
BatteryManager.getInstance().initBatteryInfo()
MediaManager.getInstance().init()
LEDsSettingsManager.getInstance().initLEDsInfo()
AlternateLandingManager.getInstance().initAlterLandingInfo()
WayLineExecutingInterruptManager.getInstance().initWayLineExecutingInterruptInfo()
CameraManager.getInstance().initCameraInfo()
StickManager.getInstance().initStickInfo()
GimbalManager.getInstance().initGimbalInfo()
OffSiteLandingManager.getInstance().initOffSiteLandingInfo()
RemoteManager.getInstance().initRemoteInfo()
PayloadWidgetManager.getInstance().initPayloadInfo()
NavigationSatelliteSystemManager.getInstance().initNavigationSatelliteSystem()
NavigationSatelliteSystemManager.getInstance().setNavigationSatelliteSystem()
PerceptionManager.getInstance().init()
//ApronArucoDetect.getInstance().init()
if (PreferenceUtils.getInstance().lteEnable){
MLTEManager.getInstance().initLTEManager()
Handler().postDelayed(Runnable { MLTEManager.getInstance().setLTEEnhancedTransmissionType()},3000)
}
//这里修改推流逻辑
if (PreferenceUtils.getInstance().customStreamType!=3) {
Handler().postDelayed(Runnable {
if (PreferenceUtils.getInstance().customStreamType==1){
StreamManager.getInstance()
.startLiveWithRTSP()
}else if (PreferenceUtils.getInstance().customStreamType==2){
StreamManager.getInstance()
.startLiveWithCustom()
}else{
LogUtil.log(TAG,"推流方式配置有误")
}
}, 5000)
}else if(!TextUtils.isEmpty(PreferenceUtils.getInstance().customStreamUrl)){
Handler().postDelayed(Runnable {
StreamManager.getInstance()
.startLiveWithCustom()
}, 5000)
}
val productType =
KeyManager.getInstance().getValue(KeyTools.createKey(ProductKey.KeyProductType))
val cameraType = KeyManager.getInstance().getValue(
KeyTools.createKey(
CameraKey.KeyCameraType,
ComponentIndexType.PORT_1
)
)
if (cameraType != null && productType != null) {
LogUtil.log(TAG, "设备类型:" + productType.name + "相机类型:" + cameraType.name)
} else {
LogUtil.log(TAG, "设备类型:" + (productType?.name ?: "未知") + "相机类型:" + (cameraType?.name ?: "未知"))
}
}
}
private val cameraHandler: Handler = Handler(Looper.getMainLooper())
private var initCameraTimes=0
private fun initCameraManager() {
val isConnect = KeyManager.getInstance()
.getValue(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.PORT_1))
if (isConnect == null || !isConnect) {
cameraHandler.postDelayed({
initDJIManager()
}, 1000)
} else {
initCameraTimes++
LogUtil.log(TAG, "初始化相机$initCameraTimes")
CameraManager.getInstance().initCameraInfo()
}
}
// var shouldExecute = true
@SuppressLint("SuspiciousIndentation")
private fun initCameraStream() {
// mainBinding?.svCameraStream?.holder?.addCallback(object : SurfaceHolder.Callback {
// override fun surfaceCreated(holder: SurfaceHolder) {}
// override fun surfaceChanged(
// holder: SurfaceHolder,
// format: Int,
// width: Int,
// height: Int
// ) {
// cameraManager.putCameraStreamSurface(
// ComponentIndexType.PORT_1,
// holder.surface,
// width,
// height,
// ICameraStreamManager.ScaleType.FIX_XY
// )
// }
//
// override fun surfaceDestroyed(holder: SurfaceHolder) {
// cameraManager.removeCameraStreamSurface(holder.surface)
// }
// })
cameraManager.addFrameListener(
ComponentIndexType.PORT_1,
ICameraStreamManager.FrameFormat.YUV420_888
) { frameData, _, _, width, height, _ ->
Movement.getInstance().isVtx=true
//检测到图传
streamReceive=true
// if (shouldExecute) {
if (startArucoType == 1) {
ApronArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary,
)
} else if (startArucoType == 2) {
AlternateArucoDetect.getInstance()?.detectArucoTags(
height,
width,
frameData,
dictionary,
)
}
// }
// shouldExecute = !shouldExecute
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onEvent(message: String?) {
when (message) {
FLAG_START_DETECT_ARUCO_APRON ->
KeyManager.getInstance().performAction<EmptyMsg>(
KeyTools.createKey<EmptyMsg, EmptyMsg>(FlightControllerKey.KeyStopAutoLanding),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
LogUtil.log(TAG, "取消降落,识别机库二维码")
Handler().postDelayed(Runnable {
if (!ApronArucoDetect.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:飞往备降点")
//测试图传丢失
AlternateLandingManager.getInstance().startTaskProcess(null)
}
}, 6000)
if (startArucoType == 1) {
return
}
startArucoType = 1
ApronArucoDetect.getInstance().setDetectedBigMarkers()
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
DroneHelper.getInstance().isVirtualStickEnable = false
DroneHelper.getInstance().setVerticalModeToVelocity()
}
override fun onFailure(error: IDJIError) {
if (startArucoType == 1) {
return
}
startArucoType = 1
LogUtil.log(TAG, "取消降落,识别机库二维码失败:" + Gson().toJson(error))
ApronArucoDetect.getInstance().setDetectedBigMarkers()
DroneHelper.getInstance().setGimbalPitchDegree()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
DroneHelper.getInstance().isVirtualStickEnable=false
DroneHelper.getInstance().setVerticalModeToVelocity()
}
})
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, "取消降落,识别备降点二维码")
Handler().postDelayed(Runnable {
if (!AlternateArucoDetect.getInstance().isTriggerSuccess) {
LogUtil.log(TAG, "图传异常:备降点直接降落")
//测试图传丢失
FlightManager.getInstance().startAutoLanding(null)
}
}, 4000)
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()
//每次触发识别二维码时,为避免获取控制权失败,使多次获取控制权
DroneHelper.getInstance().isVirtualStickEnable=false
DroneHelper.getInstance().setVerticalModeToVelocity()
}
})
FLAG_DOWN_LAND ->
KeyManager.getInstance().performAction<EmptyMsg>(
KeyTools.createKey<EmptyMsg, EmptyMsg>(FlightControllerKey.KeyStartAutoLanding),
object : CommonCallbacks.CompletionCallbackWithParam<EmptyMsg?> {
override fun onSuccess(emptyMsg: EmptyMsg?) {
startArucoType = 0
LogUtil.log(TAG, "自动降落调用成功")
}
override fun onFailure(error: IDJIError) {
LogUtil.log(TAG, "自动降落调用失败${error.description()}")
}
})
FLAG_STOP_ARUCO ->
startArucoType = 0
MqttCallBack.FLAG_RESET_CLEAN_MODE ->
setViewVisibilityWithCleanMode()
}
}
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
}
}
}

View File

@ -0,0 +1,101 @@
package com.aros.apron.activity
import android.os.Bundle
import android.util.Log
import com.aros.apron.base.BaseActivity
import com.aros.apron.databinding.ActivityGalleryBinding
import com.aros.apron.manager.MediaManager
import com.aros.apron.tools.GalleryAdapter
import com.aros.apron.tools.RecyclerViewHelper
import dji.sdk.keyvalue.key.FlightControllerKey
import dji.sdk.keyvalue.key.KeyTools
import dji.v5.common.callback.CommonCallbacks
import dji.v5.common.error.IDJIError
import dji.v5.manager.KeyManager
import dji.v5.manager.datacenter.MediaDataCenter
import dji.v5.manager.datacenter.media.MediaFileListData
import dji.v5.manager.datacenter.media.MediaFileListState
import dji.v5.manager.datacenter.media.PullMediaFileListParam
class MediaActivity : BaseActivity() {
private var adapter: GalleryAdapter? = null
private var mediaFileListData: MediaFileListData? = null
private lateinit var galleryBinding: ActivityGalleryBinding
override fun useEventBus(): Boolean {
return false
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
galleryBinding = ActivityGalleryBinding.inflate(layoutInflater)
setContentView(galleryBinding.root)
galleryBinding.btnDisable?.setOnClickListener {
MediaManager.getInstance().disablePlayback()
}
galleryBinding.btnEnable?.setOnClickListener {
MediaManager.getInstance().enablePlayback()
}
galleryBinding.btnRemoveAll?.setOnClickListener {
deleteMediaFiles()
}
galleryBinding.btnRefreshFileList?.setOnClickListener {
MediaDataCenter.getInstance().mediaManager.pullMediaFileListFromCamera(
PullMediaFileListParam.Builder().count(20).build(), object :
CommonCallbacks.CompletionCallback {
override fun onSuccess() {
Log.e("MediaActivity", "fetch success")
}
override fun onFailure(error: IDJIError) {
Log.e("MediaActivity", "fetch failed$error")
}
})
}
adapter = GalleryAdapter()
RecyclerViewHelper.initRecyclerViewG(this, galleryBinding.rvPic, adapter, 2)
// addMediaFileStateListener()
}
private fun addMediaFileStateListener() {
val isConnect =
KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection))
if (isConnect != null && isConnect) {
val mediaManager = MediaDataCenter.getInstance().mediaManager
mediaManager.addMediaFileListStateListener { mediaFileListState ->
Log.e("MediaActivity", "状态" + mediaFileListState.name)
if (mediaFileListState == MediaFileListState.UP_TO_DATE) {
mediaFileListData = mediaManager.mediaFileListData
Log.e("MediaActivity", "媒体文件数量" + mediaManager.mediaFileListData.data.size)
runOnUiThread {
adapter?.setData(mediaFileListData)
}
}
}
} else {
Log.e("MediaActivity", "设备未连接")
}
}
//删除
private fun deleteMediaFiles() {
val mediaManager = MediaDataCenter.getInstance().mediaManager
Log.e("MediaActivity", "清除文件数量" + mediaFileListData?.data?.size+"")
mediaManager.deleteMediaFiles(mediaFileListData?.data,
object : CommonCallbacks.CompletionCallback {
override fun onSuccess() {
TODO("Not yet implemented")
adapter?.setData(mediaFileListData)
}
override fun onFailure(p0: IDJIError) {
Log.e("MediaActivity", "清除文件失败" + p0.description())
}
})
}
}

View File

@ -0,0 +1,10 @@
package com.aros.apron.api;
public class BaseUrl {
public static String ipAddress = "http://36.154.125.61:17071/manage/api/v1/";
}

View File

@ -0,0 +1,21 @@
package com.aros.apron.api;
import android.util.Log;
import okhttp3.logging.HttpLoggingInterceptor;
public class HttpLogger implements HttpLoggingInterceptor.Logger {
private String TAG;
public HttpLogger(String TAG) {
this.TAG = TAG;
}
@Override
public void log(String message) {
Log.d(TAG, message);
}
}

View File

@ -0,0 +1,33 @@
package com.aros.apron.api;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class HttpUtil {
/**
* 初始化okhttpclient.
* @return okhttpClient
*/
public OkHttpClient okhttpclient() {
// HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger(getClass().getSimpleName()));
// logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.build();
return mOkHttpClient;
}
public UavApi createRequest() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BaseUrl.ipAddress)
.client(okhttpclient())
.addConverterFactory(GsonConverterFactory.create())
.build();
UavApi vamApi = retrofit.create(UavApi.class);
return vamApi;
}
}

View File

@ -0,0 +1,56 @@
package com.aros.apron.api;
import android.util.Log;
import java.io.IOException;
import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
/**
* @author Rain
* created:2019/3/29 11:46
* desc:类作用描述
*/
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
//这个chain里面包含了request和response所以你要什么都可以从这里拿
Request request = chain.request();
long t1 = System.nanoTime();//请求发起的时间
String method = request.method();
if ("POST".equals(method)) {
StringBuilder sb = new StringBuilder();
if (request.body() instanceof FormBody) {
FormBody body = (FormBody) request.body();
for (int i = 0; i < body.size(); i++) {
sb.append(body.encodedName(i) + "=" + body.encodedValue(i) + ",");
}
sb.delete(sb.length() - 1, sb.length());
Log.e("CSDN_LQR", String.format("发送请求 %s on %s %n%s %nRequestParams:{%s}",
request.url(), chain.connection(), request.headers(), sb.toString()));
}
} else {
Log.e("CSDN_LQR", String.format("发送请求 %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
}
Response response = chain.proceed(request);
long t2 = System.nanoTime();//收到响应的时间
//这里不能直接使用response.body().string()的方式输出日志
//因为response.body().string()之后response中的流会被关闭程序会报错我们需要创建出一
//个新的response给应用层处理
ResponseBody responseBody = response.peekBody(1024 * 1024);
Log.e("CSDN_LQR",
String.format("接收响应: [%s] %n返回json:【%s】 %.1fms %n%s",
response.request().url(),
responseBody.string(),
(t2 - t1) / 1e6d,
response.headers()
));
return response;
}
}

View File

@ -0,0 +1,20 @@
package com.aros.apron.api;
/**
* Created by James on 2022/6/21.
*/
public interface UavApi {
// /**
// * 登录
// *
// * @return
// */
// @Headers("Content-Type:application/json")
// @POST("login")
// Call<LoginResult> userLogin(@Body LoginValues loginValues);
}

View File

@ -0,0 +1,78 @@
package com.aros.apron.app
import android.app.Application
import android.content.Context
import com.aros.apron.models.MSDKManagerVM
import com.aros.apron.models.globalViewModels
import com.aros.apron.tools.LogUtil
import com.aros.apron.xclog.CrashHandler
import com.aros.apron.xclog.XcFileLog
import com.aros.apron.xclog.XcLogConfig
import com.dji.wpmzsdk.manager.WPMZManager
import com.orhanobut.logger.AndroidLogAdapter
import com.orhanobut.logger.Logger
import com.orhanobut.logger.PrettyFormatStrategy
import dji.v5.common.utils.GeoidManager
import dji.v5.utils.common.ContextUtil
import org.opencv.android.OpenCVLoader
open class ApronApp : Application() {
companion object {
fun getApplication(): Context? {
return context
}
var context: Context? = null
}
private val msdkManagerVM: MSDKManagerVM by globalViewModels()
override fun onCreate() {
super.onCreate()
context=this
initConfig()
msdkManagerVM.initMobileSDK(this)
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
com.cySdkyc.clx.Helper.install(this)
}
/**
* Logger 初始化配置
*/
private fun initConfig() {
var formatStrategy = PrettyFormatStrategy.newBuilder()
.showThreadInfo(false) // 隐藏线程信息 默认:显示
.methodCount(0) // 决定打印多少行每一行代表一个方法默认2
.methodOffset(7) // (Optional) Hides internal method calls up to offset. Default 5
// .tag("Aros") // (Optional) Global tag for every log. Default PRETTY_LOGGER
.build()
Logger.addLogAdapter(object : AndroidLogAdapter(formatStrategy) {
override fun isLoggable(priority: Int, tag: String): Boolean {
// return super.isLoggable(priority, tag);
return true
}
})
XcFileLog.init(XcLogConfig())
//打印崩溃日志
CrashHandler.getInstance().init()
// 初始化 OpenCV
if (OpenCVLoader.initLocal()) {
LogUtil.log("qwq","opencv" +
"初始化完成")
return;
}else{
LogUtil.log("qwq","opencv" +
"初始化失败")
}
}
}

View File

@ -0,0 +1,49 @@
package com.aros.apron.base;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.aros.apron.tools.AppManager;
import org.greenrobot.eventbus.EventBus;
public abstract class BaseActivity extends AppCompatActivity {
/**
* activity堆栈管理
*/
protected AppManager appManager = AppManager.getAppManager();
protected String TAG;
protected boolean useEventBus = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loggerSimpleName();
if (useEventBus()) {
EventBus.getDefault().register(this);
}
appManager.addActivity(this);
}
public abstract boolean useEventBus();
public void loggerSimpleName() {
TAG = getClass().getSimpleName();
// Log.e("Aros","当前界面 "+ TAG);
}
@Override
protected void onDestroy() {
super.onDestroy();
// 从栈中移除activity
appManager.finishActivity(this);
if (useEventBus == true) {
EventBus.getDefault().unregister(this);
}
}
}

View File

@ -0,0 +1,27 @@
package com.aros.apron.base;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
public abstract class BaseAdapter<T,V extends ViewBinding> extends RecyclerView.Adapter<BaseHolder> {
@NonNull
@Override
public BaseHolder<V> onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
return new BaseHolder(onBindingView(viewGroup));
}
@Override
public void onBindViewHolder(@NonNull BaseHolder holder, int position) {
// onBindingData(holder,data.get(position),position);
onBindingData(holder,null,position);
}
protected abstract void onBindingData(BaseHolder<V> holder, T t, int position);
protected abstract V onBindingView(ViewGroup viewGroup);
}

View File

@ -0,0 +1,25 @@
package com.aros.apron.base;
import com.aros.apron.tools.LogUtil;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
public class BaseCallback {
public void publish(MqttAndroidClient client, String topic, MqttMessage message) {
if (client.isConnected()) {
try {
client.publish(topic, message);
} catch (MqttException e) {
e.printStackTrace();
LogUtil.log(this.getClass().getSimpleName(), "推送失败:" + topic + e.toString());
}
} else {
LogUtil.log(this.getClass().getSimpleName(), "推送失败:mqtt 未连接");
}
}
}

View File

@ -0,0 +1,17 @@
package com.aros.apron.base;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
public class BaseHolder<V extends ViewBinding> extends RecyclerView.ViewHolder {
private V viewBinding;
public BaseHolder(V viewBinding) {
super(viewBinding.getRoot());
this.viewBinding = viewBinding;
}
public V getViewBinding() {
return viewBinding;
}
}

View File

@ -0,0 +1,266 @@
package com.aros.apron.base;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.FileUploadResult;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.entity.MessageReply;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.util.List;
public abstract class BaseManager {
/**
* 发送多个 PSDK 负载信息
* @param psdkList 多个负载信息列表
*/
public void sendMultiplePsdk2Server(List<?> psdkList){
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
Wrapper wrapper = new Wrapper(psdkList);
Gson gson = new GsonBuilder()
.serializeNulls()
.create();
String json = gson.toJson(wrapper);
MqttMessage mqttMessage = new MqttMessage(json.getBytes("UTF-8"));
mqttMessage.setQos(1);
MqttManager.getInstance().mqttAndroidClient.publish(
AMSConfig.getInstance().getMqttPSDKPushEvent2ServerTopic(),
mqttMessage
);
}
} catch (Exception e) {
LogUtil.log(TAG, "发送多个PSDK异常" + e.toString());
}
}
public String TAG = getClass().getSimpleName();
class Wrapper {
private Object data;
public Wrapper(Object data) {
this.data = data;
}
}
public void sendMsg2Server( MQMessage entity, String msg) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MessageReply messageReply = new MessageReply();
messageReply.setMsg_type(entity.getMsg_type());
messageReply.setResult(-1);
messageReply.setMsg(msg);
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(messageReply).getBytes("UTF-8"));
mqttMessage.setQos(1);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, "回复失败mqtt 未连接");
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.log(TAG, "回复异常:" + e.toString());
}
}
public void sendMsg2Server(MQMessage entity) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected() && entity != null) {
MessageReply messageReply = new MessageReply();
messageReply.setMsg_type(entity.getMsg_type());
messageReply.setResult(1);
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(messageReply).getBytes("UTF-8"));
mqttMessage.setQos(1);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, "回复失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "回复异常:" + e.toString());
e.printStackTrace();
}
}
// public static long lastTime;
//
// public boolean isFlyClickTime() {
// long time = System.currentTimeMillis();
// if (time - lastTime > 1000||time-lastTime<0) {
// lastTime = time;
// return true;
// }
// return false;
// }
public void publish(MqttAndroidClient client, String topic, MqttMessage message) {
try {
if (client.isConnected()) {
client.publish(topic, message);
// LogUtil.log(TAG, "推送消息==》"+message);
} else {
LogUtil.log(TAG, "推送飞机状态失败:mqtt未连接");
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.log(TAG, "推送飞机状态失败异常:" + topic + e.toString());
}
}
//任务流程事件
public void sendMissionExecuteEvents(String event) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
MessageReply message = new MessageReply();
message.setMsg_type(60113);
message.setResult(1);
message.setMsg(event);
mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
mqttMessage.setQos(2);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, event+"-流程发送失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "流程发送异常:"+e.toString());
e.printStackTrace();
}
}
//媒体文件上传结果上报
public void sendFileUploadCallback(int msgType, FileUploadResult result) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
result.setMsg_type(msgType);
mqttMessage = new MqttMessage(new Gson().toJson(result).getBytes("UTF-8"));
mqttMessage.setQos(2);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
LogUtil.log(TAG, "文件上传发送成功:"+new Gson().toJson(result));
} else {
LogUtil.log(TAG, "文件上传发送失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "文件上传发送异常mqtt 未连接");
e.printStackTrace();
}
}
//推送航点动作组执行状态
public void sendMsgWaypointActionState2Server(String data,String index) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
MessageReply message = new MessageReply();
message.setMsg_type(60133);
message.setResult(1);
message.setWaypointActionState(data);
message.setWaypointIndex(index);
mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
mqttMessage.setQos(0);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance(). getMqttMsdkPushEvent2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, "推送航点动作组失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "推送航点动作组发送异常mqtt 未连接");
e.printStackTrace();
}
}
//获取总飞行里程
public void sendAircraftTotalFlightDistance2Server( MQMessage mqMessage, double data) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
MessageReply message = new MessageReply();
message.setMsg_type(60132);
message.setResult(1);
message.setFlag(mqMessage.getFlag());
message.setAircraftTotalFlightDistance(data+"");
mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
mqttMessage.setQos(0);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, "总飞行里程发送失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "总飞行里程发送异常mqtt 未连接");
e.printStackTrace();
}
}
//收到暂停航线命令后发送经纬度给后端
public void sendLowBatteryRTHPosition2Server() {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
MessageReply message = new MessageReply();
message.setMsg_type(60201);
message.setResult(1);
message.setLat(Movement.getInstance().getCurrentLatitude());
message.setLon(Movement.getInstance().getCurrentLongitude());
message.setTask_id(PreferenceUtils.getInstance().getTaskId());
message.setFlyingHeight(Movement.getInstance().getFlyingHeight()+"");
message.setWaypointIndex(Movement.getInstance().getCurrentWaypointIndex()+"");
mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
mqttMessage.setQos(2);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage);
LogUtil.log(TAG,"低电量返航发送成功");
} else {
LogUtil.log(TAG, "触发低电量返航发送失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "触发低电量返航发送失败mqtt 未连接");
e.printStackTrace();
}
}
//自定义到达/离开航点的事件
public void sendCustomReachOrLeave2Server(String data,String index) {
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
MqttMessage mqttMessage = null;
MessageReply message = new MessageReply();
message.setMsg_type(60203);
message.setResult(1);
message.setWaypointActionState(data);
message.setWaypointIndex(index);
mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
mqttMessage.setQos(0);
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkPushEvent2ServerTopic(), mqttMessage);
} else {
LogUtil.log(TAG, "推送自定义到达/离开航点的事件失败mqtt 未连接");
}
} catch (Exception e) {
LogUtil.log(TAG, "推送自定义到达/离开航点的事件异常mqtt 未连接");
e.printStackTrace();
}
}
public boolean getGimbalAndCameraEnabled() {
if (!PreferenceUtils.getInstance().getNeedTriggerApronArucoLand() && !PreferenceUtils.getInstance().getNeedTriggerAlterArucoLand()&& Movement.getInstance().getGoHomeState()!=1&&Movement.getInstance().getGoHomeState()!=2) {
return true;
} else {
LogUtil.log(TAG, "降落时不允许操作云台/相机/虚拟摇杆");
return false;
}
}
}

View File

@ -0,0 +1,59 @@
package com.aros.apron.callback;
import android.os.Handler;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.ToastUtil;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
public class MqttActionCallBack implements IMqttActionListener {
private final String TAG = "MqttActionCallBack";
private MqttAndroidClient mqttAndroidClient;
private MqttConnectOptions options;
public MqttActionCallBack(MqttAndroidClient mqttAndroidClient, MqttConnectOptions options) {
this.mqttAndroidClient = mqttAndroidClient;
this.options = options;
}
@Override
public void onSuccess(IMqttToken asyncActionToken) {
ToastUtil.showToast("MQtt连接成功");
LogUtil.log(TAG, "MQtt连接成功-------");
try {
mqttAndroidClient.subscribe(AMSConfig.getInstance().getMqttServer2MsdkTopic(), 1);//订阅主题:注册
} catch (MqttException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LogUtil.log(TAG, "MQtt连接失败:" + exception.toString());
try {
if (!mqttAndroidClient.isConnected()){
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
try {
mqttAndroidClient.connect(options, null, MqttActionCallBack.this); // 再次尝试连接
} catch (MqttException e) {
LogUtil.log(TAG,"mqtt重连异常:"+e.toString());
e.printStackTrace();
}
}
},1500);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,635 @@
package com.aros.apron.callback;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import com.aros.apron.app.ApronApp;
import com.aros.apron.base.BaseManager;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.ApronExecutionStatus;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.entity.Movement;
import com.aros.apron.manager.AMSLogManager;
import com.aros.apron.manager.AlternateLandingManager;
import com.aros.apron.manager.CameraManager;
import com.aros.apron.manager.FlightManager;
import com.aros.apron.manager.GimbalManager;
import com.aros.apron.manager.MediaManager;
import com.aros.apron.manager.MegaphoneManager;
import com.aros.apron.manager.MissionManager;
import com.aros.apron.manager.OffSiteLandingManager;
import com.aros.apron.manager.PayloadWidgetManager;
import com.aros.apron.manager.PerceptionManager;
import com.aros.apron.manager.ResetHomePointManager;
import com.aros.apron.manager.StickManager;
import com.aros.apron.manager.StreamManager;
import com.aros.apron.manager.SystemManager;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.aros.apron.tools.RestartAPPTool;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;
import java.io.UnsupportedEncodingException;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.aircraft.virtualstick.VirtualStickManager;
public class MqttCallBack extends BaseManager implements MqttCallbackExtended {
private String TAG = "MqttCallBack";
@Override
public void connectionLost(Throwable cause) {
LogUtil.log(TAG, "MQtt connectionLost:" + cause.toString());
}
//断线重连
public void reConnect() throws Exception {
if (null != MqttManager.getInstance().mqttAndroidClient) {
LogUtil.log(TAG, "MQtt reConnect-----");
}
}
public static boolean isReceiverMission = false;
private boolean isReceiverMissionAgain = false;
private boolean isWaiting30Min = false;
@Override
public void messageArrived(String topic, MqttMessage mqttMessage) {
String jsonString = null;
try {
jsonString = new String(mqttMessage.getPayload(), "UTF-8");
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "解析异常");
throw new RuntimeException(e);
}
MQMessage message = new Gson().fromJson(jsonString, MQMessage.class);
switch (message.getMsg_type()) {
//检测遥控器与开发板是否连接
case 60001:
LogUtil.log(TAG, "收到命令:遥控器是否连接" + jsonString);
SystemManager.getInstance().checkRemoteControlPowerStatus(message);
break;
//检测飞机是否开机
case 60002:
LogUtil.log(TAG, "收到命令:飞机是否开机" + jsonString);
SystemManager.getInstance().checkAircraftPowerStatus(message);
break;
//航线和推流地址指令收到后立即回复1自行处理航线和推流逻辑
case 60003:
if (Movement.getInstance().getIsVirtualStickEnable() == 1) {
VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "收到航线时取消虚拟摇杆");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "收到航线时取消虚拟摇杆失败:" + getIDJIErrorMsg(error));
}
});
}
//默认规定不在返航时才可以上传航线
//收到航线时将状态设置为不可关机状态
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(false);
Movement.getInstance().setTaskFail(false);
Movement.getInstance().setVirtualStickQuitMission(false);
if (Movement.getInstance().getGoHomeState() != 1 && Movement.getInstance().getGoHomeState() != 2) {
PreferenceUtils.getInstance().setIsNewRoute(message.isNewRoute());
PreferenceUtils.getInstance().setMissionType(message.getMissionType());
if (!message.isNewRoute()) {
LogUtil.log(TAG, "收到命令:航线" + jsonString);
//如果是一键起飞航线返回给前端就一直是一键起飞航线
Movement.getInstance().setMissionType(message.getMissionType());
// 0.起飞前检查图传
checkVtxWithDelay(() -> {
if (isReceiverMission == false) {
isReceiverMission = true;
// 1.收到60003直接回复
StreamManager.getInstance().sendReply2Server(message);
//2.检查航线参数
if (!SystemManager.getInstance().checkMissionParameter(message)) {
return;
}
if (PreferenceUtils.getInstance().getCustomStreamType() == 3) {
// 3.开启推流
StreamManager.getInstance().startLive(message);
}
// 4.关闭避障
PerceptionManager.getInstance().setPerceptionEnable(false);
// 5.清空sd卡
CameraManager.getInstance().formatStorage(null);
MissionManager.getInstance().startTaskProcess(message);
//可能遥控器上次流程结束未关机就再次起飞
} else {
SystemManager.getInstance().replyAlreadyFlown(message);
// if (isReceiverMissionAgain==false){
// isReceiverMissionAgain=true;
// new Handler().postDelayed(new Runnable() {
// @Override
// public void run() {
// //这里需要考虑taskFail和waitForShutDown等参数的重置
// isWaiting30Min=true;
// }
// },30000);
// }else{
// //等待30秒如果飞机
// if (isWaiting30Min&&!Movement.getInstance().isPlaneWing()){
// RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext());
// }else{
// LogUtil.log(TAG,"重复收到航线,正在确认飞机状态后飞行:"+"isWaiting30Min="+isWaiting30Min+"isPlaneWing="+Movement.getInstance().isPlaneWing());
// }
// }
}
});
} else {
LogUtil.log(TAG, "收到命令:指点飞行" + jsonString);
// 1.收到60003直接回复
StreamManager.getInstance().sendReply2Server(message);
// 2.下载航线
MissionManager.getInstance().startTaskProcess(message);
}
} else {
LogUtil.log(TAG, "返航中,无法上传航线");
}
break;
//航线暂停
case 60004:
LogUtil.log(TAG, "收到命令:航线暂停" + jsonString);
MissionManager.getInstance().pauseMission(message);
break;
//航线继续
case 60005:
LogUtil.log(TAG, "收到命令:航线继续" + jsonString);
MissionManager.getInstance().resumeMission(message);
break;
//返航
case 60006:
LogUtil.log(TAG, "收到命令:返航" + jsonString);
if(Movement.getInstance().isIsflyalter()==false){
FlightManager.getInstance().startGoHome(message);
}else{
sendMsg2Server( message, "飞备降禁止返航" );
}
break;
//获取控制权
case 60007:
LogUtil.log(TAG, "收到命令:获取控制权" + jsonString);
StickManager.getInstance().setVirtualStickModeEnabled(message);
break;
//虚拟摇杆数据
case 60008:
LogUtil.log(TAG, "收到命令:虚拟摇杆数据" + jsonString);
StickManager.getInstance().sendVirtualStickAdvancedParam(message);
break;
//云台角度控制
case 60009:
LogUtil.log(TAG, "收到命令:云台角度控制" + jsonString);
GimbalManager.getInstance().gimbalRotateByRelativeAngle(message);
break;
case 60024:
LogUtil.log(TAG, "收到命令:云台角度控制绝对角度" + jsonString);
// GimbalManager.getInstance().gimbalRotateByAbsoluteAngle(message);
break;
//收到此指令表示舱门已关闭等待归中60012后可调用60011关机
case 60010:
// LogUtil.log(TAG, "收到命令:舱门已关闭" + jsonString);
// SystemManager.getInstance().droneShutdown(message);
break;
//收到60012表示已归中立即回复60012且上传相册后可以发送60011关闭飞机和遥控器
//收到60012表示服务端在确认飞机此时时候处于可关机的状态
case 60012:
LogUtil.log(TAG, "收到命令:飞机是否可关机" + jsonString);
SystemManager.getInstance().aircraftStoredReply(message);
break;
//收到60014表示Server已收到架次开始
case 60014:
LogUtil.log(TAG, "收到Server架次开始");
break;
//收到60015表示Server已收到架次结束
case 60015:
LogUtil.log(TAG, "收到Server架次结束");
break;
//取消控制权
case 60016:
LogUtil.log(TAG, "收到命令:取消控制权" + jsonString);
StickManager.getInstance().setVirtualStickModeDisable(message);
break;
//切换视频源 1广角 2变焦 3红外
case 60017:
LogUtil.log(TAG, "收到命令:切换视频源" + jsonString);
CameraManager.getInstance().setCameraVideoStreamSource(message);
break;
//设置相机模式 0拍照 1录像
case 60018:
LogUtil.log(TAG, "收到命令:设置相机模式" + jsonString);
CameraManager.getInstance().setCameraMode(message);
break;
//开始拍照
case 60019:
LogUtil.log(TAG, "收到命令:开始拍照" + jsonString);
CameraManager.getInstance().startShootPhoto(message);
break;
//开始录像
case 60020:
LogUtil.log(TAG, "收到命令:开始录像" + jsonString);
CameraManager.getInstance().startRecordVideo(message);
break;
//停止录像
case 60021:
LogUtil.log(TAG, "收到命令:停止录像" + jsonString);
CameraManager.getInstance().stopRecordVideo(message);
break;
//设置变焦倍率
case 60022:
//CameraManager.getInstance().setCameraZoomRatios(message);
LogUtil.log(TAG, "收到命令:设置变焦倍率" + jsonString);
new Handler(Looper.getMainLooper()).postDelayed(() ->
CameraManager.getInstance().setCameraZoomRatios(message), 500);
break;
//设置红外变焦倍率
case 60023:
LogUtil.log(TAG, "收到命令:设置红外变焦倍率" + jsonString);
new Handler(Looper.getMainLooper()).postDelayed(() ->
CameraManager.getInstance().setThermalZoomRatios(message), 500);
// CameraManager.getInstance().setThermalZoomRatios(message);
break;
//开始推流可配置推流视角
case 60100:
LogUtil.log(TAG, "收到命令:开始推流" + jsonString);
StreamManager.getInstance().startLive(message);
break;
//设置推流分辨率
case 60101:
LogUtil.log(TAG, "收到命令:设置推流分辨率" + jsonString);
StreamManager.getInstance().setLiveStreamQuality(message);
break;
//设置限高
case 60102:
LogUtil.log(TAG, "收到命令:设置限高" + jsonString);
FlightManager.getInstance().setHeightLimit(message);
break;
//设置限远
case 60103:
LogUtil.log(TAG, "收到命令:设置限远" + jsonString);
FlightManager.getInstance().setDistanceLimit(message);
break;
//设置限远是否启用
case 60104:
LogUtil.log(TAG, "收到命令:设置限远是否启用" + jsonString);
FlightManager.getInstance().setDistanceLimitEnabled(message);
break;
//设置红外分屏
case 60105:
LogUtil.log(TAG, "收到命令:设置红外分屏" + jsonString);
CameraManager.getInstance().setThermalDisplayMode(message);
break;
//取消返航
case 60106:
LogUtil.log(TAG, "收到命令:取消返航" + jsonString);
FlightManager.getInstance().stopGoHome(message);
break;
//终止航线
case 60109:
LogUtil.log(TAG, "收到命令:终止航线" + jsonString);
MissionManager.getInstance().stopMission(message);
break;
//开始喊话
case 60110:
LogUtil.log(TAG, "收到命令:开始喊话" + jsonString);
MegaphoneManager.getInstance().startMegaphonePlay(message);
break;
//结束喊话
case 60111:
LogUtil.log(TAG, "收到命令:结束喊话" + jsonString);
MegaphoneManager.getInstance().stopPlay(message);
break;
//一键飞往紧急备降点
case 60112:
LogUtil.log(TAG, "收到命令:备降点降落" + jsonString);
AlternateLandingManager.getInstance().startTaskProcess(message);
break;
//降落
case 60113:
LogUtil.log(TAG, "收到命令:降落" + jsonString);
FlightManager.getInstance().startAutoLanding(message);
break;
//取消降落
case 60114:
LogUtil.log(TAG, "收到命令:取消降落" + jsonString);
FlightManager.getInstance().stopAutoLanding(message);
break;
//解锁抛投器
case 60115:
LogUtil.log(TAG, "收到命令:解锁" + jsonString);
//PayloadWidgetManager.getInstance().unlock(message);
break;
//锁定抛投器
case 60116:
LogUtil.log(TAG, "收到命令:锁定" + jsonString);
// PayloadWidgetManager.getInstance().lock(message);
break;
//抛投
case 60117:
LogUtil.log(TAG, "收到命令:抛投" + jsonString);
//PayloadWidgetManager.getInstance().throwOne(message);
break;
//一键全抛
case 60118:
LogUtil.log(TAG, "收到命令:一键全投" + jsonString);
//PayloadWidgetManager.getInstance().throwAll(message);
break;
//设置备降点
// case 60119:
// LogUtil.log(TAG, "收到命令:设置备降点" + jsonString);
// AlternateLandingManager.getInstance().setAlternatePoint(message);
// break;
//开始定时拍照
case 60120:
LogUtil.log(TAG, "收到命令:开始定时拍照" + jsonString);
CameraManager.getInstance().startTakePhotoWithInterval(message);
break;
//结束拍照
case 60121:
LogUtil.log(TAG, "收到命令:结束拍照" + jsonString);
CameraManager.getInstance().stopShootPhoto(message);
break;
//重置相机
case 60122:
LogUtil.log(TAG, "收到命令:重置相机设置" + jsonString);
CameraManager.getInstance().resetCameraSetting(message);
break;
//云台回中
case 60123:
LogUtil.log(TAG, "收到命令:云台回中" + jsonString);
GimbalManager.getInstance().gimbalResetWithPitchAndYaw(message);
break;
//设置对焦模式
case 60124:
LogUtil.log(TAG, "收到命令:设置对焦模式" + jsonString);
CameraManager.getInstance().setCameraFocusMode(message);
break;
//指点对焦
case 60125:
LogUtil.log(TAG, "收到命令:指点对焦" + jsonString);
CameraManager.getInstance().tapZoomAtTarget(message);
break;
//设置照片xmp写入
case 60126:
LogUtil.log(TAG, "收到命令写入exif" + jsonString);
MediaManager.getInstance().setMediaFileXMPCustomInfo(message);
break;
//设置曝光模式
case 60127:
LogUtil.log(TAG, "收到命令:设置曝光模式" + jsonString);
CameraManager.getInstance().setExposureMode(message);
break;
//设置ev
case 60128:
LogUtil.log(TAG, "收到命令:设置曝光补偿" + jsonString);
CameraManager.getInstance().setExposureCompensation(message);
break;
//发送数据到psdk
case 60129:
LogUtil.log(TAG, "收到命令发送数据到psdk" + jsonString);
//PayloadWidgetManager.getInstance().sendMsgToPayload(message);
break;
//停止推流
case 60130:
LogUtil.log(TAG, "收到命令:停止推流" + jsonString);
StreamManager.getInstance().stopLive(message);
break;
//设置对焦值
case 60131:
LogUtil.log(TAG, "收到命令:设置对焦值" + jsonString);
CameraManager.getInstance().setCameraFocusRingValue(message);
break;
//获取里程
case 60132:
LogUtil.log(TAG, "收到命令:获取里程" + jsonString);
FlightManager.getInstance().getAircraftTotalFlightDistance(message);
break;
//上传媒体文件
case 60134:
// LogUtil.log(TAG, "收到命令:获取里程" + jsonString);
// FlightManager.getInstance().getAircraftTotalFlightDistance(message);
break;
//异地降落
case 60135:
LogUtil.log(TAG, "收到命令:异地降落" + jsonString);
OffSiteLandingManager.getInstance().startTaskProcess(message);
break;
//刷新返航点
case 60136:
LogUtil.log(TAG, "收到命令:重置返航点" + jsonString);
ResetHomePointManager.getInstance().startTaskProcess(message);
break;
//设置纯净模式
case 60137:
LogUtil.log(TAG, "收到命令:设置纯净模式" + jsonString);
PreferenceUtils.getInstance().setIsCleanMode(message.getIsCleanMode() == 1 ? true : false);
EventBus.getDefault().post(FLAG_RESET_CLEAN_MODE);
break;
//设置测温模式
case 60138:
LogUtil.log(TAG, "收到命令:设置测温模式" + jsonString);
CameraManager.getInstance().setThermalTemperatureMeasureMode(message);
break;
//设置测温点
case 60139:
LogUtil.log(TAG, "收到命令:设置测温点" + jsonString);
CameraManager.getInstance().setThermalSpotMetersurePoint(message);
break;
//设置测温区域
case 60140:
LogUtil.log(TAG, "收到命令:设置测温区域" + jsonString);
CameraManager.getInstance().setThermalRegionMetersureArea(message);
break;
//切换直播视角
case 60141:
LogUtil.log(TAG, "收到命令:切换直播视角" + jsonString);
StreamManager.getInstance().switchCurrentView(message);
break;
//设置云台控制的最大速度
case 60142:
LogUtil.log(TAG, "收到命令:设置云台控制的最大速度" + jsonString);
GimbalManager.getInstance().setGimbalControlMaxSpeed(message);
break;
//紧急悬停
case 60143:
LogUtil.log(TAG, "收到命令:设置紧急悬停" + jsonString);
FlightManager.getInstance().emergencyHover(message);
break;
//设置失控动作
case 60144:
LogUtil.log(TAG, "收到命令:设置失控动作" + jsonString);
FlightManager.getInstance().setFailsafeAction(message);
break;
//设置返航高度
case 60145:
LogUtil.log(TAG, "收到命令:设置返航高度" + jsonString);
FlightManager.getInstance().setGoHomeHeight(message);
break;
//设置低电量报警阈值
case 60146:
LogUtil.log(TAG, "收到命令:设置低电量报警阈值" + jsonString);
FlightManager.getInstance().setLowBatteryWarningThreshold(message);
break;
//设置严重低电量报警阈值
case 60147:
LogUtil.log(TAG, "收到命令:设置严重低电量报警阈值" + jsonString);
FlightManager.getInstance().setSeriousLowBatteryWarningThreshold(message);
break;
//设置智能低电量返航
case 60148:
LogUtil.log(TAG, "收到命令:设置智能低电量返航" + jsonString);
FlightManager.getInstance().setLowBatteryRTHEnabled(message);
break;
//指点对焦
case 60149:
LogUtil.log(TAG, "收到命令:指点对焦" + jsonString);
break;
//云台偏航回中
case 60150:
LogUtil.log(TAG, "收到命令:云台偏航回中" + jsonString);
GimbalManager.getInstance().gimbalResetWithYaw(message);
break;
//云台偏航向下
case 60151:
LogUtil.log(TAG, "收到命令:云台偏航向下" + jsonString);
GimbalManager.getInstance().gimbalDownWithPitch(message);
break;
//云台向下
case 60152:
LogUtil.log(TAG, "收到命令:云台向下" + jsonString);
GimbalManager.getInstance().gimbalDownWithPitchAndYaw(message);
break;
//开启低速转浆
case 60153:
LogUtil.log(TAG, "收到命令:开启低速转浆" + jsonString);
FlightManager.getInstance().startPropellerRotation(message);
break;
//停止低速转浆
case 60154:
LogUtil.log(TAG, "收到命令:停止低速转浆" + jsonString);
FlightManager.getInstance().stopPropellerRotation(message);
break;
//msdk日志上传
case 60666:
LogUtil.log(TAG, "收到命令:日志上传" + jsonString);
AMSLogManager.getInstance().enableLogList(message);
break;
//设置PSDK控件值
case 60667:
LogUtil.log(TAG, "收到命令设置psdk控件" + jsonString);
PayloadWidgetManager.getInstance().setWidget(message);
break;
//监听机库收到AMS命令后的回执
case 60999:
if (!TextUtils.isEmpty(message.getStatus())) {
switch (message.getStatus()) {
case "0":
LogUtil.log(TAG, "收到命令:服务端响应关舱门" + jsonString);
break;
case "1":
ApronExecutionStatus.getInstance().setServerReplyDockOpen(true);
LogUtil.log(TAG, "收到命令:服务端响应开舱门" + jsonString);
break;
case "2":
ApronExecutionStatus.getInstance().setServerReplyDockIn(true);
LogUtil.log(TAG, "收到命令:服务端响应入库" + jsonString);
break;
case "3":
ApronExecutionStatus.getInstance().setServerReplyDroneShut(true);
LogUtil.log(TAG, "收到命令:服务端响应关机" + jsonString);
break;
}
} else {
LogUtil.log(TAG, "收到命令:机库动作参数有误" + jsonString);
}
break;
}
}
public static final String FLAG_RESET_CLEAN_MODE = "FLAG_RESET_CLEAN_MODE";
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
}
@Override
public void connectComplete(boolean reconnect, String serverURI) {
try {
if (reconnect) {//重新订阅
LogUtil.log(TAG, "MQtt ConnectComplete:" + serverURI);
MqttManager.getInstance().mqttAndroidClient.subscribe(AMSConfig.getInstance().getMqttServer2MsdkTopic(), 1);//订阅主题:注册
// publish(topic,"注册",0);
}
} catch (Exception e) {
LogUtil.log(TAG, "MQtt ConnectException:" + e.toString());
}
}
private Handler handler = new Handler(Looper.getMainLooper());
private Runnable checkVtxRunnable;
private void checkVtxWithDelay(Runnable onVtxReady) {
if (Movement.getInstance().isVtx()) {
// 图传正常直接继续后面的流程
PreferenceUtils.getInstance().setRestartAMSTimes(0);
LogUtil.log(TAG, "图传正常,继续执行任务流程");
onVtxReady.run();
return;
}
LogUtil.log(TAG, "未检测到图传5 秒后再次确认...");
handler.postDelayed(() -> {
if (!Movement.getInstance().isVtx()) {
// 图传仍未恢复 执行重启逻辑
int times = PreferenceUtils.getInstance().getRestartAMSTimes();
if (times < 5) {
PreferenceUtils.getInstance().setRestartAMSTimes(times + 1);
LogUtil.log(TAG, "图传仍未恢复,重启 AMS 第 " + (times + 1) + "");
RestartAPPTool.INSTANCE.restartApp(ApronApp.Companion.getContext());
}
} else {
// 图传恢复 执行后续逻辑
PreferenceUtils.getInstance().setRestartAMSTimes(0);
LogUtil.log(TAG, "图传在延迟期间恢复,继续执行任务流程");
onVtxReady.run();
}
}, 5000);
}
}

View File

@ -0,0 +1,153 @@
package com.aros.apron.constant;
/**
* MQTT参数配置
*/
public class AMSConfig {
private AMSConfig() {
}
private static class MqttConfigHolder {
private static final AMSConfig INSTANCE = new AMSConfig();
}
public static AMSConfig getInstance() {
return AMSConfig.MqttConfigHolder.INSTANCE;
}
private String mqttServerUri;
private String userName;
private String password;
private String serialNumber;
private String mqttServer2MsdkTopic;
private String mqttMsdkReplyMessage2ServerTopic;
private String mqttMsdkPushMessage2ServerTopic;
private String mqttMsdkPushEvent2ServerTopic;
private String mqttPSDKPushEvent2ServerTopic;
private String alternateLandingTimes;
public String getMqttPSDKPushEvent2ServerTopic() {
return mqttPSDKPushEvent2ServerTopic;
}
public void setMqttPSDKPushEvent2ServerTopic(String mqttPSDKPushEvent2ServerTopic) {
this.mqttPSDKPushEvent2ServerTopic = mqttPSDKPushEvent2ServerTopic;
}
public String getAlternateLandingTimes() {
return alternateLandingTimes;
}
public void setAlternateLandingTimes(String alternateLandingTimes) {
this.alternateLandingTimes = alternateLandingTimes;
}
public String getMqttMsdkPushEvent2ServerTopic() {
return mqttMsdkPushEvent2ServerTopic;
}
public void setMqttMsdkPushEvent2ServerTopic(String mqttMsdkPushEvent2ServerTopic) {
this.mqttMsdkPushEvent2ServerTopic = mqttMsdkPushEvent2ServerTopic;
}
public String getMqttServer2MsdkTopic() {
return mqttServer2MsdkTopic;
}
public void setMqttServer2MsdkTopic(String mqttServer2MsdkTopic) {
this.mqttServer2MsdkTopic = mqttServer2MsdkTopic;
}
public String getMqttMsdkReplyMessage2ServerTopic() {
return mqttMsdkReplyMessage2ServerTopic;
}
public void setMqttMsdkReplyMessage2ServerTopic(String mqttMsdkReplyMessage2ServerTopic) {
this.mqttMsdkReplyMessage2ServerTopic = mqttMsdkReplyMessage2ServerTopic;
}
public String getMqttMsdkPushMessage2ServerTopic() {
return mqttMsdkPushMessage2ServerTopic;
}
public void setMqttMsdkPushMessage2ServerTopic(String mqttMsdkPushMessage2ServerTopic) {
this.mqttMsdkPushMessage2ServerTopic = mqttMsdkPushMessage2ServerTopic;
}
public String getMqttServerUri() {
return mqttServerUri;
}
public void setMqttServerUri(String mqttServerUri) {
this.mqttServerUri = mqttServerUri;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
/**
* 服务器IP地址
*/
//朋业测试
// public static String SOCKET_HOST = "tcp://212.64.64.69:1883";
// public static String USER_NAME = "admin";
// public static String USER_PASSWORD = "1qw23er45t";
//西安机库
// public static String SERIAL_NUMBER = "323RFDSVDTHBDFVSD";
//太仓单开门
// public static String SERIAL_NUMBER = "1581F5FJB229Q00A003W";
//太仓御三机库
// public static String SERIAL_NUMBER = "1581F5FJB229Q00A003Y";
//太仓御三机库2
// public static String SERIAL_NUMBER = "1581F5FJB229Q00A003A";
//太仓ARS350
// public static String SERIAL_NUMBER = "1581F5FJB229Q00A003980890809";
/**
* 接收指令
*/
// public String MQTT_SERVER_2_MSDK_TOPIC = "nest/" + serialNumber + "/uav_services";
/**
* 回复结果
*/
// public static String MQTT_MSDK_REPLY_MESSAGE_2_SERVER_TOPIC = "nest/" + SERIAL_NUMBER + "/uav_services_reply";
/**
* 推送飞行状态
*/
// public static String MQTT_MSDK_PUSH_MESSAGE_2_SERVER_TOPIC = "nest/" + SERIAL_NUMBER + "/uav_status_message";
/**
* 推送gis飞行状态GIS需要定频2S
*/
// public static String MQTT_MSDK_PUSH_GIS_MESSAGE_2_SERVER_TOPIC = "nest/" + SERIAL_NUMBER + "/uav_gis_message";
}

View File

@ -0,0 +1,57 @@
package com.aros.apron.entity;
public class ApronExecutionStatus {
private static class ApronexecutionHolder {
private static final ApronExecutionStatus INSTANCE = new ApronExecutionStatus();
}
private ApronExecutionStatus() {
}
public static final ApronExecutionStatus getInstance() {
return ApronexecutionHolder.INSTANCE;
}
//服务端响应了机库入库指令
private boolean serverReplyDockIn;
//服务端响应了飞机关机指令
private boolean serverReplyDroneShut;
//服务端是否响应了开舱门指令
private boolean serverReplyDockOpen;
//用于确认飞机此时可以关机的状态(APC流程默认)
private boolean isAircraftWaitShutDown=true;
public boolean isAircraftWaitShutDown() {
return isAircraftWaitShutDown;
}
public void setAircraftWaitShutDown(boolean aircraftWaitShutDown) {
isAircraftWaitShutDown = aircraftWaitShutDown;
}
public boolean isServerReplyDockOpen() {
return serverReplyDockOpen;
}
public void setServerReplyDockOpen(boolean serverReplyDockOpen) {
this.serverReplyDockOpen = serverReplyDockOpen;
}
public boolean isServerReplyDockIn() {
return serverReplyDockIn;
}
public void setServerReplyDockIn(boolean serverReplyDockIn) {
this.serverReplyDockIn = serverReplyDockIn;
}
public boolean isServerReplyDroneShut() {
return serverReplyDroneShut;
}
public void setServerReplyDroneShut(boolean serverReplyDroneShut) {
this.serverReplyDroneShut = serverReplyDroneShut;
}
}

View File

@ -0,0 +1,55 @@
package com.aros.apron.entity;
import org.opencv.core.Mat;
import java.util.Objects;
public class ArucoMarker {
private int id;
private Mat conner;
private float size;//二维码实际尺寸
public ArucoMarker(int id, Mat conner, float size) {
this.id = id;
this.conner = conner;
this.size = size;
}
public float getSize() {
return size;
}
public void setSize(float size) {
this.size = size;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Mat getConner() {
return conner;
}
public void setConner(Mat conner) {
this.conner = conner;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ArucoMarker)) return false;
ArucoMarker that = (ArucoMarker) o;
return getId() == that.getId() && getConner().equals(that.getConner());
}
@Override
public int hashCode() {
return Objects.hash(getId(), getConner());
}
}

View File

@ -0,0 +1,45 @@
package com.aros.apron.entity;
public enum ArucoMarkerDimensions {
ID_1(1, 0.18f),
ID_2(2, 0.18f),
ID_3(3, 0.18f),
ID_4(4, 0.18f),
ID_5(5, 0.15f),
ID_6(6, 0.24f),
ID_11(11, 0.03f),
ID_12(12, 0.03f),
ID_13(13, 0.03f),
ID_14(14, 0.03f),
ID_15(15, 0.03f),
ID_16(16, 0.03f),
ID_17(17, 0.03f),
ID_18(18, 0.03f),
ID_19(19, 0.03f);
private final int id;
private final float size;
ArucoMarkerDimensions(int id, float size) {
this.id = id;
this.size = size;
}
public int getId() {
return id;
}
public float getSize() {
return size;
}
public static float getSizeById(int id) {
for (ArucoMarkerDimensions dimension : ArucoMarkerDimensions.values()) {
if (dimension.getId() == id) {
return dimension.getSize();
}
}
throw new IllegalArgumentException("No dimension found for ID: " + id);
}
}

View File

@ -0,0 +1,44 @@
package com.aros.apron.entity;
import java.util.ArrayList;
import java.util.List;
import dji.sdk.wpmz.value.mission.WaylineExecuteWaypoint;
import dji.sdk.wpmz.value.mission.WaylineWaypoint;
public class CurrentWayline {
private static class CurrentWaylineHolder {
private static final CurrentWayline INSTANCE = new CurrentWayline();
}
private CurrentWayline() {
}
public static final CurrentWayline getInstance() {
return CurrentWaylineHolder.INSTANCE;
}
private List<WaylineExecuteWaypoint> waypoints=new ArrayList<>();
public List<WaylineExecuteWaypoint> getWaypoints() {
return waypoints;
}
public void setWaypoints(List<WaylineExecuteWaypoint> waypoints) {
this.waypoints = waypoints;
}
private List<WaylineExecuteWaypoint> routeWaypoints=new ArrayList<>();
public List<WaylineExecuteWaypoint> getRouteWaypoints() {
return routeWaypoints;
}
public void setRouteWaypoints(List<WaylineExecuteWaypoint> waypoints) {
this.routeWaypoints = waypoints;
}
}

View File

@ -0,0 +1,113 @@
package com.aros.apron.entity;
public class FileUploadResult {
private int msg_type;
private int result;
private String url;
private String buckName;
private String objectKey;
private String task_id;
private String fileName;
private int offIndex;
private int fileNum;
private Long fileSize;
private String progress;
private String msg;
public String getProgress() {
return progress;
}
public void setProgress(String progress) {
this.progress = progress;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public String getTask_id() {
return task_id;
}
public void setTask_id(String task_id) {
this.task_id = task_id;
}
public Long getFileSize() {
return fileSize;
}
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getMsg_type() {
return msg_type;
}
public void setMsg_type(int msg_type) {
this.msg_type = msg_type;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getObjectKey() {
return objectKey;
}
public void setObjectKey(String objectKey) {
this.objectKey = objectKey;
}
public String getBuckName() {
return buckName;
}
public void setBuckName(String buckName) {
this.buckName = buckName;
}
public int getOffIndex() {
return offIndex;
}
public void setOffIndex(int offIndex) {
this.offIndex = offIndex;
}
public int getFileNum() {
return fileNum;
}
public void setFileNum(int fileNum) {
this.fileNum = fileNum;
}
}

View File

@ -0,0 +1,102 @@
package com.aros.apron.entity;
import java.util.List;
public class FlightMission {
private String id;
private Integer templateId;
private Integer waylineId;
private Integer missionId;
public Integer getMissionId() {
return missionId;
}
public void setMissionId(Integer missionId) {
this.missionId = missionId;
}
public Integer getTemplateId() {
return templateId;
}
public void setTemplateId(Integer templateId) {
this.templateId = templateId;
}
private Double speed=5.0;
/**
* 安全起飞高度[1.5, 1500] 高度模式相对起飞点高度
* * 飞行器起飞后先爬升至该高度再根据飞向首航点模式的设置飞至首航点该元素仅在飞行器未起飞时生效
*/
private Float takeOffSecurityHeight;
//航线结束动作
private String finishAction;
public String getFinishAction() {
return finishAction;
}
public void setFinishAction(String finishAction) {
this.finishAction = finishAction;
}
/**
* 航点信息
* @return
*/
private List<MissionPoint> points;
public List<MissionPoint> getPoints() {
return points;
}
public void setPoints(List<MissionPoint> points) {
this.points = points;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Integer getWaylineId() {
return waylineId;
}
public void setWaylineId(Integer waylineId) {
this.waylineId = waylineId;
}
public Double getSpeed() {
return speed;
}
public void setSpeed(Double speed) {
this.speed = speed;
}
public Float getTakeOffSecurityHeight() {
return takeOffSecurityHeight;
}
public void setTakeOffSecurityHeight(Float takeOffSecurityHeight) {
this.takeOffSecurityHeight = takeOffSecurityHeight;
}
}

View File

@ -0,0 +1,699 @@
package com.aros.apron.entity;
public class MQMessage {
private int result;
private String kmz_url;
private String rtmp_push_url;
private String upload_url;
private String access_key;
private String secret_key;
private String bucketName;
private String objectKey;
//最低起飞电量
String min_takeoff_electricity;
//强制返航电量
String force_return_electricity;
private String region;
private String flight_name;
private int streamIndex=0;//0 云台视角 1FPV
private int liveStreamQuality;//设置推流分辨率 1标清 2高清 3超清
private int cameraVideoStreamSource;//相机视频流 1广角 2变焦 3红外
private int cameraMode;//设置相机拍照录像模式 0拍照 1录像
private int cameraZoomRatios;//设置变焦镜头倍率 (isContinuousH20T为true,关键倍率[2,5,10,20,40,80,160,200])
private int thermalZoomRatios;//设置红外镜头倍率 (1x 2x 4x 8x)
private int heightLimit;//限高
private int heightLimitEnabled;//限高是否启用 1启用 0不启用
private int distanceLimitEnabled;//限远是否启用 1启用 0不启用
private int distanceLimit;//限远
private String flightId;//航线id
private String task_id;//任务ID(开始推流起飞降落都推送一次)
private double zoom;//指点变焦
private boolean newRoute;//是否是空中下发航线
private int missionType;//任务类型 一键起飞航线定频推送只会推送3
private int x=0;//前后
private int y=0;//左右
private int z=0;//上下
private int r=0;//自旋
private int megaphoneVolume;//喊话器音量
private int megaphonePlayMode;//喊话器播放模式
private String megaphoneWord;//喊话器文字内容
private int cameraExposureMode;//曝光模式
private int cameraExposureCompensation;//曝光补偿数值
private int AELockEnabled;//曝光锁定
private double shootInterval;//拍照间隔时间
private int shootCount;//拍照的张数
private int msg_type;
private String alternate_lat;//设置备降点经纬度
private String alternate_lng;
private String offSitePointLat;//设置异地降落经纬度
private String offSitePointLon;
private String safe_land_height; //备降点安全起飞高度
private double zoomTargetX; //坐标x,范围0-1
private double zoomTargetY; //坐标y,范围0-1
private int cameraFocusMode; //对焦模式
private String xmpInfo;//写入exif信息
private String payloadData;//发送数据给psdk
private int cameraFocusRingValue;//设置相机对焦值
private String status;//收到机库状态的回执消息
private String flag;//后端用来区别里程(用作AI)
private int isCleanMode;//是否清洁模式
private int thermalTemperatureMeasureMode;//红外测温模式
private String metersurePointX;//点测温位置
private String metersurePointY;
private String metersureAreaX;//区域测温矩形左上角起始位置
private String metersureAreaY;
private String metersureAreaWidth;//测温矩形长度
private String metersureAreaHeight;//测温矩形宽度
private int currentView;//直播视频源
private int gimbalControlSpeed;//云台控制速度
private int failsafeAction;//设置飞行器的失控行为类型 0悬停 1降落 2返航
private int goHomeHeight;//设置飞行器的返航高度
private int lowBatteryWarningThreshold;//设置电池低电量警告的阈值该数值为百分比范围[15,50]当电池电量低于该阀值时飞行器将进行低电量报警
private int seriousLowBatteryWarningThreshold;//电池严重低电量警告的阈值该值默认为10%Matrice 30 Series不可设置当电池电量低于该阀值时飞行器将进行返航操作
private int lowBatteryRTHEnabled;//智能低电量返航功能
private int widgetValue;//设置负载控件值
private int widgetType;//设置负载控件类型
private int widgetIndex;//设置负载控件索引
private int index;//设置负载控件索引与widgetIndex相同用于兼容不同的JSON格式
private int psdk_index;//PSDK负载索引
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
private String PsdkText;
public String getPsdkText() {
return PsdkText;
}
public void setPsdkText(String psdkText) {
PsdkText = psdkText;
}
//默认让他等于0
private int gimindex=0;//云台索引 0/1
public int getGimindex() {
return gimindex;
}
public void setGimindex(int gimindex) {
this.gimindex = gimindex;
}
public int getWidgetValue() {
return widgetValue;
}
public void setWidgetValue(int widgetValue) {
this.widgetValue = widgetValue;
}
public int getWidgetType() {
return widgetType;
}
public void setWidgetType(int widgetType) {
this.widgetType = widgetType;
}
public int getWidgetIndex() {
return widgetIndex;
}
public void setWidgetIndex(int widgetIndex) {
this.widgetIndex = widgetIndex;
}
public int getPsdk_index() {
return psdk_index;
}
public void setPsdk_index(int psdk_index) {
this.psdk_index = psdk_index;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getMissionType() {
return missionType;
}
public void setMissionType(int missionType) {
this.missionType = missionType;
}
public String getMin_takeoff_electricity() {
return min_takeoff_electricity;
}
public void setMin_takeoff_electricity(String min_takeoff_electricity) {
this.min_takeoff_electricity = min_takeoff_electricity;
}
public String getForce_return_electricity() {
return force_return_electricity;
}
public void setForce_return_electricity(String force_return_electricity) {
this.force_return_electricity = force_return_electricity;
}
public String getAlternate_lat() {
return alternate_lat;
}
public void setAlternate_lat(String alternate_lat) {
this.alternate_lat = alternate_lat;
}
public String getAlternate_lng() {
return alternate_lng;
}
public void setAlternate_lng(String alternate_lng) {
this.alternate_lng = alternate_lng;
}
public String getSafe_land_height() {
return safe_land_height;
}
public void setSafe_land_height(String safe_land_height) {
this.safe_land_height = safe_land_height;
}
public String getBucketName() {
return bucketName;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
public String getObjectKey() {
return objectKey;
}
public void setObjectKey(String objectKey) {
this.objectKey = objectKey;
}
public boolean isNewRoute() {
return newRoute;
}
public void setNewRoute(boolean newRoute) {
this.newRoute = newRoute;
}
public double getZoom() {
return zoom;
}
public void setZoom(double zoom) {
this.zoom = zoom;
}
public String getTask_id() {
return task_id;
}
public void setTask_id(String task_id) {
this.task_id = task_id;
}
public int getHeightLimitEnabled() {
return heightLimitEnabled;
}
public void setHeightLimitEnabled(int heightLimitEnabled) {
this.heightLimitEnabled = heightLimitEnabled;
}
public int getFailsafeAction() {
return failsafeAction;
}
public void setFailsafeAction(int failsafeAction) {
this.failsafeAction = failsafeAction;
}
public int getGoHomeHeight() {
return goHomeHeight;
}
public void setGoHomeHeight(int goHomeHeight) {
this.goHomeHeight = goHomeHeight;
}
public int getLowBatteryWarningThreshold() {
return lowBatteryWarningThreshold;
}
public void setLowBatteryWarningThreshold(int lowBatteryWarningThreshold) {
this.lowBatteryWarningThreshold = lowBatteryWarningThreshold;
}
public int getSeriousLowBatteryWarningThreshold() {
return seriousLowBatteryWarningThreshold;
}
public void setSeriousLowBatteryWarningThreshold(int seriousLowBatteryWarningThreshold) {
this.seriousLowBatteryWarningThreshold = seriousLowBatteryWarningThreshold;
}
public int getLowBatteryRTHEnabled() {
return lowBatteryRTHEnabled;
}
public void setLowBatteryRTHEnabled(int lowBatteryRTHEnabled) {
this.lowBatteryRTHEnabled = lowBatteryRTHEnabled;
}
public int getCurrentView() {
return currentView;
}
public void setCurrentView(int currentView) {
this.currentView = currentView;
}
public String getMetersurePointX() {
return metersurePointX;
}
public void setMetersurePointX(String metersurePointX) {
this.metersurePointX = metersurePointX;
}
public String getMetersurePointY() {
return metersurePointY;
}
public void setMetersurePointY(String metersurePointY) {
this.metersurePointY = metersurePointY;
}
public String getMetersureAreaX() {
return metersureAreaX;
}
public void setMetersureAreaX(String metersureAreaX) {
this.metersureAreaX = metersureAreaX;
}
public String getMetersureAreaY() {
return metersureAreaY;
}
public void setMetersureAreaY(String metersureAreaY) {
this.metersureAreaY = metersureAreaY;
}
public String getMetersureAreaWidth() {
return metersureAreaWidth;
}
public void setMetersureAreaWidth(String metersureAreaWidth) {
this.metersureAreaWidth = metersureAreaWidth;
}
public String getMetersureAreaHeight() {
return metersureAreaHeight;
}
public void setMetersureAreaHeight(String metersureAreaHeight) {
this.metersureAreaHeight = metersureAreaHeight;
}
public int getThermalTemperatureMeasureMode() {
return thermalTemperatureMeasureMode;
}
public void setThermalTemperatureMeasureMode(int thermalTemperatureMeasureMode) {
this.thermalTemperatureMeasureMode = thermalTemperatureMeasureMode;
}
public int getIsCleanMode() {
return isCleanMode;
}
public void setIsCleanMode(int isCleanMode) {
this.isCleanMode = isCleanMode;
}
public String getOffSitePointLat() {
return offSitePointLat;
}
public void setOffSitePointLat(String offSitePointLat) {
this.offSitePointLat = offSitePointLat;
}
public String getOffSitePointLon() {
return offSitePointLon;
}
public void setOffSitePointLon(String offSitePointLon) {
this.offSitePointLon = offSitePointLon;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getXmpInfo() {
return xmpInfo;
}
public void setXmpInfo(String xmpInfo) {
this.xmpInfo = xmpInfo;
}
public String getPayloadData() {
return payloadData;
}
public void setPayloadData(String payloadData) {
this.payloadData = payloadData;
}
public int getCameraFocusRingValue() {
return cameraFocusRingValue;
}
public void setCameraFocusRingValue(int cameraFocusRingValue) {
this.cameraFocusRingValue = cameraFocusRingValue;
}
public int getCameraFocusMode() {
return cameraFocusMode;
}
public void setCameraFocusMode(int cameraFocusMode) {
this.cameraFocusMode = cameraFocusMode;
}
public double getZoomTargetX() {
return zoomTargetX;
}
public void setZoomTargetX(double zoomTargetX) {
this.zoomTargetX = zoomTargetX;
}
public double getZoomTargetY() {
return zoomTargetY;
}
public void setZoomTargetY(double zoomTargetY) {
this.zoomTargetY = zoomTargetY;
}
public double getShootInterval() {
return shootInterval;
}
public void setShootInterval(double shootInterval) {
this.shootInterval = shootInterval;
}
public int getShootCount() {
return shootCount;
}
public void setShootCount(int shootCount) {
this.shootCount = shootCount;
}
public int getAELockEnabled() {
return AELockEnabled;
}
public void setAELockEnabled(int AELockEnabled) {
this.AELockEnabled = AELockEnabled;
}
public int getCameraExposureMode() {
return cameraExposureMode;
}
public void setCameraExposureMode(int cameraExposureMode) {
this.cameraExposureMode = cameraExposureMode;
}
public int getCameraExposureCompensation() {
return cameraExposureCompensation;
}
public void setCameraExposureCompensation(int cameraExposureCompensation) {
this.cameraExposureCompensation = cameraExposureCompensation;
}
public String getMegaphoneWord() {
return megaphoneWord;
}
public void setMegaphoneWord(String megaphoneWord) {
this.megaphoneWord = megaphoneWord;
}
public int getMegaphoneVolume() {
return megaphoneVolume;
}
public void setMegaphoneVolume(int megaphoneVolume) {
this.megaphoneVolume = megaphoneVolume;
}
public int getMegaphonePlayMode() {
return megaphonePlayMode;
}
public void setMegaphonePlayMode(int megaphonePlayMode) {
this.megaphonePlayMode = megaphonePlayMode;
}
public String getFlightId() {
return flightId;
}
public void setFlightId(String flightId) {
this.flightId = flightId;
}
public int getHeightLimit() {
return heightLimit;
}
public void setHeightLimit(int heightLimit) {
this.heightLimit = heightLimit;
}
public int getDistanceLimitEnabled() {
return distanceLimitEnabled;
}
public void setDistanceLimitEnabled(int distanceLimitEnabled) {
this.distanceLimitEnabled = distanceLimitEnabled;
}
public int getDistanceLimit() {
return distanceLimit;
}
public void setDistanceLimit(int distanceLimit) {
this.distanceLimit = distanceLimit;
}
public int getCameraVideoStreamSource() {
return cameraVideoStreamSource;
}
public void setCameraVideoStreamSource(int cameraVideoStreamSource) {
this.cameraVideoStreamSource = cameraVideoStreamSource;
}
public int getThermalZoomRatios() {
return thermalZoomRatios;
}
public void setThermalZoomRatios(int thermalZoomRatios) {
this.thermalZoomRatios = thermalZoomRatios;
}
public int getCameraZoomRatios() {
return cameraZoomRatios;
}
public void setCameraZoomRatios(int cameraZoomRatios) {
this.cameraZoomRatios = cameraZoomRatios;
}
public int getCameraMode() {
return cameraMode;
}
public void setCameraMode(int cameraMode) {
this.cameraMode = cameraMode;
}
public int getLiveStreamQuality() {
return liveStreamQuality;
}
public void setLiveStreamQuality(int liveStreamQuality) {
this.liveStreamQuality = liveStreamQuality;
}
public int getStreamIndex() {
return streamIndex;
}
public void setStreamIndex(int streamIndex) {
this.streamIndex = streamIndex;
}
public String getFlight_name() {
return flight_name;
}
public void setFlight_name(String flight_name) {
this.flight_name = flight_name;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public String getUpload_url() {
return upload_url;
}
public void setUpload_url(String upload_url) {
this.upload_url = upload_url;
}
public String getAccess_key() {
return access_key;
}
public void setAccess_key(String access_key) {
this.access_key = access_key;
}
public String getSecret_key() {
return secret_key;
}
public void setSecret_key(String secret_key) {
this.secret_key = secret_key;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public int getR() {
return r;
}
public void setR(int r) {
this.r = r;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getMsg_type() {
return msg_type;
}
public void setMsg_type(int msg_type) {
this.msg_type = msg_type;
}
public String getKmz_url() {
return kmz_url;
}
public void setKmz_url(String kmz_url) {
this.kmz_url = kmz_url;
}
public String getRtmp_push_url() {
return rtmp_push_url;
}
public void setRtmp_push_url(String rtmp_push_url) {
this.rtmp_push_url = rtmp_push_url;
}
public int getGimbalControlSpeed() {
return gimbalControlSpeed;
}
public void setGimbalControlSpeed(int gimbalControlSpeed) {
this.gimbalControlSpeed = gimbalControlSpeed;
}
}

View File

@ -0,0 +1,19 @@
package com.aros.apron.entity
import com.aros.apron.models.DEFAULT_STR
import dji.sdk.keyvalue.value.product.ProductType
import dji.v5.common.register.PackageProductCategory
import dji.v5.utils.inner.SDKConfig
data class MSDKInfo(val SDKVersion: String = DEFAULT_STR) {
var buildVer: String = DEFAULT_STR
var isDebug: Boolean = false
var packageProductCategory: PackageProductCategory? = null
var productType: ProductType = ProductType.UNKNOWN
var networkInfo: String = DEFAULT_STR
var countryCode: String = DEFAULT_STR
var firmwareVer: String = DEFAULT_STR
var isLDMLicenseLoaded: String = DEFAULT_STR
var isLDMEnabled: String = DEFAULT_STR
var coreInfo: SDKConfig.CoreInfo? = null
}

View File

@ -0,0 +1,24 @@
package com.aros.apron.entity;
public class MessageApron {
private int msg_type;
private boolean open;
public int getMsg_type() {
return msg_type;
}
public void setMsg_type(int msg_type) {
this.msg_type = msg_type;
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
}

View File

@ -0,0 +1,114 @@
package com.aros.apron.entity;
public class MessageReply {
private int msg_type;
private int result;
private String msg;
private byte[] payloadData;//接收psdk数据
private String waypointActionState;//推送航点动作状态
private String waypointIndex;//推送航点index
private String aircraftTotalFlightDistance;//总体飞行距离单位飞行器断电后不会清零
private String flag;
private String task_id;
private String lat;
private String lon;
private String flyingHeight;//飞行高度
public String getFlyingHeight() {
return flyingHeight;
}
public void setFlyingHeight(String flyingHeight) {
this.flyingHeight = flyingHeight;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLon() {
return lon;
}
public void setLon(String lon) {
this.lon = lon;
}
public String getTask_id() {
return task_id;
}
public void setTask_id(String task_id) {
this.task_id = task_id;
}
public String getFlag() {
return flag;
}
public void setFlag(String flag) {
this.flag = flag;
}
public String getWaypointIndex() {
return waypointIndex;
}
public void setWaypointIndex(String waypointIndex) {
this.waypointIndex = waypointIndex;
}
public String getWaypointActionState() {
return waypointActionState;
}
public void setWaypointActionState(String waypointActionState) {
this.waypointActionState = waypointActionState;
}
public String getAircraftTotalFlightDistance() {
return aircraftTotalFlightDistance;
}
public void setAircraftTotalFlightDistance(String aircraftTotalFlightDistance) {
this.aircraftTotalFlightDistance = aircraftTotalFlightDistance;
}
public byte[] getPayloadData() {
return payloadData;
}
public void setPayloadData(byte[] payloadData) {
this.payloadData = payloadData;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getResult() {
return result;
}
public void setResult(int result) {
this.result = result;
}
public int getMsg_type() {
return msg_type;
}
public void setMsg_type(int msg_type) {
this.msg_type = msg_type;
}
}

View File

@ -0,0 +1,129 @@
package com.aros.apron.entity;
import java.util.Date;
import java.util.List;
public class MissionPoint {
private String lng;
private String lat;
private double waypointSpeed;
//航点执行高度
private double executeHeight;
// 录像0,
// 拍照1,
// 悬停2
// 停止录像3
private List<Action> actions;
//执行时间
private Date executeTime;
public double getExecuteHeight() {
return executeHeight;
}
public void setExecuteHeight(double executeHeight) {
this.executeHeight = executeHeight;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public double getSpeed() {
return waypointSpeed;
}
public void setSpeed(double speed) {
this.waypointSpeed = speed;
}
public Date getExecuteTime() {
return executeTime;
}
public void setExecuteTime(Date executeTime) {
this.executeTime = executeTime;
}
public List<Action> getActions() {
return actions;
}
public void setActions(List<Action> actions) {
this.actions = actions;
}
public static class Action{
//1 变焦 2拍照 3开始录像 4结束录像 5云台偏航角 6云台俯仰角 7飞行器偏航角 8悬停
private int type;
private int zoom;
private int gimbalYawAngle;
private int gimbalPitchAngle;
private int aircraftHeading;
private int hoverTime;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getZoom() {
return zoom;
}
public void setZoom(int zoom) {
this.zoom = zoom;
}
public int getGimbalYawAngle() {
return gimbalYawAngle;
}
public void setGimbalYawAngle(int gimbalYawAngle) {
this.gimbalYawAngle = gimbalYawAngle;
}
public int getGimbalPitchAngle() {
return gimbalPitchAngle;
}
public void setGimbalPitchAngle(int gimbalPitchAngle) {
this.gimbalPitchAngle = gimbalPitchAngle;
}
public int getAircraftHeading() {
return aircraftHeading;
}
public void setAircraftHeading(int aircraftHeading) {
this.aircraftHeading = aircraftHeading;
}
public int getHoverTime() {
return hoverTime;
}
public void setHoverTime(int hoverTime) {
this.hoverTime = hoverTime;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,66 @@
package com.aros.apron.entity;
public class PayloadInfo {
/**
* 当前负载索引类型
* LEFT_OR_MAIN 负载挂载在飞行器的左弦位置
* RIGHT 负载挂载在飞行器的右弦位置
* UP 负载挂载在飞行器的上方位置
* EXTERNAL 负载挂载在飞行器的扩展位置在M300 RTK上该位置为OSDK口在M350 RTK上该位置为E-PORT口
* PORT_1 负载挂载在飞行器的Port1位置
* PORT_2 负载挂载在飞行器的Port2位置
* PORT_3 负载挂载在飞行器的Port3位置
* PORT_4 负载挂载在飞行器的Port4位置
* PORT_5 负载挂载在飞行器的Port5位置
* PORT_6 负载挂载在飞行器的Port6位置
* PORT_7 负载挂载在飞行器的Port7位置
*/
private String payloadIndexType;
/**
* 负载产品名称
*/
private String productName;
/**
* 负载序列号
*/
private String serialNumber;
/**
* 负载固件版本
*/
private String firmwareVersion;
public String getPayloadIndexType() {
return payloadIndexType;
}
public void setPayloadIndexType(String payloadIndexType) {
this.payloadIndexType = payloadIndexType;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public String getSerialNumber() {
return serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
public String getFirmwareVersion() {
return firmwareVersion;
}
public void setFirmwareVersion(String firmwareVersion) {
this.firmwareVersion = firmwareVersion;
}
}

View File

@ -0,0 +1,34 @@
package com.aros.apron.fly;
/**
* 备降点
*/
public class AlternatePoint {
private float altitude;
private double longitude;
private double latitude;
public float getAltitude() {
return altitude;
}
public void setAltitude(float altitude) {
this.altitude = altitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
}

View File

@ -0,0 +1,306 @@
//package com.aros.apron.fly;
//
//import androidx.annotation.NonNull;
//
//import com.aros.apron.entity.Movement;
//import com.aros.apron.tools.LogUtil;
//import com.google.gson.Gson;
//
//import java.util.Timer;
//import java.util.TimerTask;
//
//import dji.sdk.keyvalue.key.FlightControllerKey;
//import dji.sdk.keyvalue.key.KeyTools;
//import dji.sdk.keyvalue.value.common.EmptyMsg;
//import dji.sdk.keyvalue.value.flightcontroller.FlightCoordinateSystem;
//import dji.sdk.keyvalue.value.flightcontroller.RollPitchControlMode;
//import dji.sdk.keyvalue.value.flightcontroller.VerticalControlMode;
//import dji.sdk.keyvalue.value.flightcontroller.VirtualStickFlightControlParam;
//import dji.sdk.keyvalue.value.flightcontroller.YawControlMode;
//import dji.v5.common.callback.CommonCallbacks;
//import dji.v5.common.error.IDJIError;
//import dji.v5.manager.KeyManager;
//import dji.v5.manager.aircraft.virtualstick.VirtualStickManager;
//
//
//public class FlyToAlternatePointManager {
// private String TAG = "FlyToAlternatePointManager";
//
// private AlternatePoint mWaypoint = new AlternatePoint();
// private float mSpeed = 3.0f;
// private double aircraftLng, aircraftLat, aircraftAlt, aircraftPich, aircraftRoll, aircraftYaw;
// //判定是否到点的误差
// private double delta = 1;
// private double heightDelta = 5;
// //任务是否开始执行
// private boolean isRunning = false;
// //航点任务是否开始执行到达第一个点后才开始
// private boolean isMissionRunning = false;
// private int currentIndex = 0;
// private Timer mSendVirtualStickDataTimer;
// private SendVirtualStickDataTask mSendVirtualStickDataTask;
// private float mPitch;
// private float mRoll;
// private float mYaw;
// private float mThrottle;
// VirtualStickFlightControlParam param;
//
// private FlyToAlternatePointManager() {
// }
//
// private static class FlyToAlternatePointHolder {
// private static final FlyToAlternatePointManager INSTANCE = new FlyToAlternatePointManager();
// }
//
// public static FlyToAlternatePointManager getInstance() {
// return FlyToAlternatePointManager.FlyToAlternatePointHolder.INSTANCE;
// }
//
// public void setAlternateCinfig(AlternatePoint waypoint, float speed) {
// mWaypoint = waypoint;
// mSpeed = speed;
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
// if (isConnect != null && isConnect) {
// if (param == null) {
// param = new VirtualStickFlightControlParam();
// param.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
// param.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
// param.setVerticalControlMode(VerticalControlMode.POSITION);
// param.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
// }
// VirtualStickManager.getInstance().sendVirtualStickAdvancedParam(param);
// }
// }
//
// /**
// * 这里开始任务
// */
// public void start() {
// currentIndex = 0;
// isRunning = true;
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
// if (isConnect != null && isConnect) {
// VirtualStickManager.getInstance().enableVirtualStick(new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// VirtualStickManager.getInstance().setVirtualStickAdvancedModeEnabled(true);
// flyToPoint(mWaypoint);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "备降点控制权获取失败:" + error.description());
// }
// });
// } else {
// LogUtil.log(TAG, "备降点控制权获取失败:飞控未连接");
// }
// }
//
// /**
// * 飞到指定点
// * @param point
// */
// private void flyToPoint(AlternatePoint point) {
// //还没启动就不管
// if (!isRunning) {
// return;
// }
// //这两个固定全程使用前进全程保持高度
// mPitch = 0;
// mThrottle = point.getAltitude();
// //还没获取到飞机当前状态时不管
// if (Double.isNaN(aircraftLng) || Double.isNaN((aircraftLat))) {
// return;
// }
// //先飞到指定高度再继续比较安全
// if (Math.abs(aircraftAlt - point.getAltitude()) > heightDelta) {
// executeVirtualStickDataTask();
// return;
// }
// double[] targetXY = GaussKruegerConverter.LngLat2XY(point.getLongitude(), point.getLatitude());
// double[] nowXY = GaussKruegerConverter.LngLat2XY(aircraftLng, aircraftLat);
// double dx = targetXY[0] - nowXY[0];
// double dy = targetXY[1] - nowXY[1];
// double d = Math.sqrt(dx * dx + dy * dy);
// //到点
// if (d < delta) {
// //这里可以判断是否飞到备降点上方
// LogUtil.log(TAG, "到达备降点上方");
// return;
// }
// //没到点继续飞
// mYaw = (float) calcDeg(nowXY, targetXY);
// mRoll = (float) calcSpeed(nowXY, targetXY);
// executeVirtualStickDataTask();
// }
//
// /***
// * 结束任务
// */
// public void stop() {
// isMissionRunning = false;
// isRunning = false;
// land();
// disableVirtualStickMode();
// }
//
// /**
// * 禁止虚拟摇杆
// */
// private void disableVirtualStickMode() {
// if (mSendVirtualStickDataTimer != null) {
// mSendVirtualStickDataTimer.cancel();
// }
// VirtualStickManager.getInstance().setVirtualStickAdvancedModeEnabled(true);
// VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// LogUtil.log(TAG, "备降点取消控制权成功");
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "备降点取消控制权失败:" + new Gson().toJson(error));
// }
// });
// }
//
// /**
// * 降落
// */
// private void land() {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
// if (isConnect != null && isConnect) {
// KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStartAutoLanding), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
// @Override
// public void onSuccess(EmptyMsg emptyMsg) {
// LogUtil.log(TAG, "备降点降落调用成功");
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "备降点降落调用失败:" + new Gson().toJson(error));
// }
// });
// } else {
// LogUtil.log(TAG, "备降点降落调用失败:飞控未连接");
// }
// }
//
//
// /**
// * 飞行到下一个点
// * 如果
// */
//// public void goNextPoint() {
//// //任务执行时或者起飞到第一个点时
//// if (isMissionRunning || currentIndex == 0) {
//// //如果是第一个点就任务开始
//// if (currentIndex == 0) {
//// isMissionRunning = true;
//// }
//// //如果是正在执行任务并且最后一个点就任务结束进入停止流程
//// if (isMissionRunning && currentIndex == mWaypointList.size() - 1) {
//// isMissionRunning = false;
//// currentIndex = -1;
//// stop();
//// }
//// }
//// }
//
// /**
// * 计算飞行速度
// *
// * @param nowXY
// * @param targetXY
// * @return
// */
// private double calcSpeed(double[] nowXY, double[] targetXY) {
// double speed = mSpeed;
// double dx = targetXY[0] - nowXY[0];
// double dy = targetXY[1] - nowXY[1];
// double d = Math.sqrt(dx * dx + dy * dy);
//
// //根据距离目标的位置计算速度快到点了速度降下来
// if (d < mSpeed * 2) {
// speed = (float) d / 2;
// }
// return speed;
// }
//
// /**
// * 计算飞行角度
// *
// * @param nowXY 当前飞机的位置
// * @param targetXY 目标位置
// * @return
// */
// private double calcDeg(double[] nowXY, double[] targetXY) {
// double deg = 0;
// double dx = targetXY[0] - nowXY[0];
// double dy = targetXY[1] - nowXY[1];
// //根据目标位置和飞机位置计算角度
// if (dy > 0) {
// deg = Math.toDegrees(Math.atan(dx / dy));
// } else if (dy == 0) {
// if (dx > 0) {
// deg = 90;
// } else if (dx == 0) {
// deg = 0;
// } else {
// deg = -90;
// }
// } else {
// if (dx > 0) {
// deg = 180 + Math.toDegrees(Math.atan((targetXY[0] - nowXY[0]) / (targetXY[1] - nowXY[1])));
// } else if (dx == 0) {
// deg = -180;
// } else {
// deg = Math.toDegrees(Math.atan((targetXY[0] - nowXY[0]) / (targetXY[1] - nowXY[1]))) - 180;
// }
// }
// return deg;
// }
//
//
// /**
// * 执行虚拟摇杆发送任务
// */
// private void executeVirtualStickDataTask() {
// if (null == mSendVirtualStickDataTimer) {
// mSendVirtualStickDataTask = new SendVirtualStickDataTask();
// mSendVirtualStickDataTimer = new Timer();
// mSendVirtualStickDataTimer.schedule(mSendVirtualStickDataTask, 100, 200);
// }
// }
//
// /**
// * 更新无人机状态
// */
// public void updateAircraftSate() {
// aircraftLng = Double.parseDouble(Movement.getInstance().getCurrentLongitude());
// aircraftLat = Double.parseDouble(Movement.getInstance().getCurrentLatitude());
// aircraftAlt = Movement.getInstance().getFlyingHeight();
// aircraftPich = Double.parseDouble(Movement.getInstance().getPitch());
// aircraftRoll = Double.parseDouble(Movement.getInstance().getRoll());
// aircraftYaw = Double.parseDouble(Movement.getInstance().getYaw());
// if (isRunning) {
// //在任务中就飞任务点
// if (isMissionRunning || currentIndex == 0) {
// flyToPoint(mWaypoint);
// }
// }
// }
//
// class SendVirtualStickDataTask extends TimerTask {
// @Override
// public void run() {
// param.setPitch((double) mPitch);//左右
// param.setRoll((double) mRoll);//前后
// param.setYaw((double) mYaw);//旋转
// param.setVerticalThrottle((double) mThrottle);//上下
// VirtualStickManager.getInstance().sendVirtualStickAdvancedParam(param);
// }
// }
//}

View File

@ -0,0 +1,69 @@
package com.aros.apron.fly;
public class GaussKruegerConverter {
static double a = 6378137;
static double b = 6356752.3142;
static double k0 = 1.0;
static double f = (a - b) / a;//扁率
static double e = Math.sqrt(2*f - Math.pow(f ,2));//第一偏心率
static double e1 = e / Math.sqrt(1 - Math.pow(e , 2));//'第二偏心率
/**
* 经纬度转平面直角坐标系
* @param lng
* @param lat
* @return
*/
public static double [] LngLat2XY(double lng,double lat)
{
int centerLongitude = (int)Math.round(lng/3.0) * 3;
double BR = lat * Math.PI / 180;//纬度弧长
double lo = (lng - centerLongitude)*Math.PI/180; //经差弧度
double N = a / Math.sqrt(1 - Math.pow((e * Math.sin(BR)) , 2)); //卯酉圈曲率半径
//求解参数s
double C = Math.pow(a , 2)/ b;
double B0 = 1 - 3 * Math.pow(e1 , 2) / 4 + 45 *Math.pow( e1 ,4) / 64 - 175 * Math.pow(e1 , 6) / 256 + 11025 * Math.pow(e1 , 8 )/ 16384;
double B2 = B0 - 1;
double B4 = 15 / 32 * Math.pow(e1 , 4) - 175 / 384 * Math.pow(e1 , 6 )+ 3675 / 8192 *Math.pow( e1 , 8);
double B6 = 0 - 35 / 96 *Math.pow( e1 , 6) + 735 / 2048 * Math.pow(e1 , 8);
double B8 = 315 / 1024 * Math.pow(e1 , 8);
double s = C * (B0 * BR + Math.sin(BR) * (B2 * Math.cos(BR) + B4 * Math.pow((Math.cos(BR)) , 3) + B6 * Math.pow((Math.cos(BR)) , 5 )+ B8 * Math.pow((Math.cos(BR)) , 7)));
double t = Math.tan(BR);
double g = e1 * Math.cos(BR);
double XR= s + Math.pow(lo , 2) / 2 * N * Math.sin(BR) * Math.cos(BR) + Math.pow(lo , 4 )* N * Math.sin(BR) * Math.pow((Math.cos(BR)) , 3) / 24 * (5 -Math.pow( t , 2 )+ 9 * Math.pow(g , 2) + 4 *Math.pow( g , 4)) + Math.pow(lo , 6) * N * Math.sin(BR) * Math.pow((Math.cos(BR)) , 5) * (61 - 58 *Math.pow( t , 2) + Math.pow(t , 4)) / 720;
double YR= lo * N * Math.cos(BR) + Math.pow(lo , 3 )* N / 6 *Math.pow( (Math.cos(BR)) , 3) * (1 - Math.pow(t , 2) + Math.pow(g , 2)) + Math.pow(lo , 5) * N / 120 * Math.pow((Math.cos(BR)) , 5) * (5 - 18 * Math.pow(t , 2) + Math.pow(t , 4) + 14 * Math.pow(g , 2) - 58 * Math.pow(g , 2) * Math.pow(t , 2));
double x=YR;
double y=XR;
return new double[]{x,y};
}
public static double[] XY2LngLat(double x,double y,int centerLongitude)
{
double El1 = (1 - Math.sqrt(1 - Math.pow(e , 2))) / (1 + Math.sqrt(1 -Math.pow( e , 2)));
double Mf = y/ k0 ;//真实坐标值
double Q = Mf / (a * (1 - Math.pow(e , 2) / 4 - 3 * Math.pow(e , 4) / 64 - 5 *Math.pow( e , 6) / 256));//角度
double Bf = Q + (3 * El1 / 2 - 27 *Math.pow( El1 , 3) / 32) * Math.sin(2 * Q) + (21 *Math.pow( El1 , 2) / 16 - 55 *Math.pow( El1 , 4 )/ 32) * Math.sin(4 * Q) + (151 *Math.pow( El1 , 3 )/ 96) * Math.sin(6 * Q) + 1097 / 512 * Math.pow(El1 , 4) * Math.sin(8 * Q);
double Rf = a * (1 -Math.pow( e , 2)) / Math.sqrt(Math.pow((1 - Math.pow((e * Math.sin(Bf)) ,2)) , 3));
double Nf = a / Math.sqrt(1 - Math.pow((e * Math.sin(Bf)) , 2));//卯酉圈曲率半径
double Tf = Math.pow((Math.tan(Bf)) , 2);
double D =x/ (k0 * Nf);
double Cf =Math.pow( e1 , 2) * Math.pow((Math.cos(Bf)) , 2);
double B = Bf - Nf * Math.tan(Bf) / Rf * (Math.pow(D , 2) / 2 - (5 + 3 * Tf + 10 * Cf - 9 * Tf * Cf - 4 *Math.pow( Cf , 2) - 9 * Math.pow(e1 , 2)) *Math.pow( D , 4) / 24 + (61 + 90 * Tf + 45 * Math.pow(Tf , 2) - 256 * Math.pow(e1 , 2) - 3 * Math.pow(Cf , 2)) *Math.pow( D , 6) / 720);
double L = centerLongitude*Math.PI/180 + 1 / Math.cos(Bf) * (D - (1 + 2 * Tf + Cf) *Math.pow( D , 3) / 6 + (5 - 2 * Cf + 28 * Tf - 3 *Math.pow( Cf , 2) + 8 * Math.pow(e1 , 2) + 24 * Math.pow(Tf , 2)) * Math.pow(D , 5 )/ 120);
double Bangle = B * 180 / Math.PI;
double Langle = L * 180 / Math.PI;
return new double[]{Langle,Bangle};
}
}

View File

@ -0,0 +1,268 @@
package com.aros.apron.manager;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.RequiresApi;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ProgressEvent;
import com.amazonaws.services.s3.model.ProgressListener;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.FileUploadResult;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.tools.LogUtil;
import java.io.File;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class AMSLogManager extends BaseManager {
private static final String TAG = "AMSLogManager";
private AMSLogManager() {
}
private static class MediaManagerHolder {
private static final AMSLogManager INSTANCE = new AMSLogManager();
}
public static AMSLogManager getInstance() {
return MediaManagerHolder.INSTANCE;
}
private int downLoadMediaFileIndex = 0;
private boolean isUploadingAMSLog;
private File[] files = new File[]{};
private int uploadFailTime = 0;
public boolean isUploadingAMSLog() {
return isUploadingAMSLog;
}
public void setUploadingAMSLog(boolean uploadingAMSLog) {
isUploadingAMSLog = uploadingAMSLog;
}
/**
* 修改添加 3 秒延迟执行
*/
public void enableLogList(MQMessage message) {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
doEnableLogList(message);
}, 3000);
}
/**
* 新增实际执行逻辑
*/
private void doEnableLogList(MQMessage message) {
downLoadMediaFileIndex = 0;
setUploadingAMSLog(true);
File logDir = new File(getLogDir());
LogUtil.log(TAG, "日志目录: " + logDir.getAbsolutePath());
if (logDir != null) {
files = logDir.listFiles();
LogUtil.log(TAG, "扫描到文件数: " + (files != null ? files.length : 0));
if (files == null || files.length == 0) {
sendMsg2Server(message, "日志文件夹暂无日志文件");
setUploadingAMSLog(false);
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
pullOriginalFile(message);
}
}
sendMsg2Server(message);
} else {
sendMsg2Server(message, "日志文件夹为空");
setUploadingAMSLog(false);
}
}
@RequiresApi(Build.VERSION_CODES.O)
public void pullOriginalFile(MQMessage message) {
if (files == null || downLoadMediaFileIndex >= files.length) {
LogUtil.log(TAG, "文件索引越界");
setUploadingAMSLog(false);
return;
}
LogUtil.log(TAG, "File size: " + files.length + ", 当前索引: " + downLoadMediaFileIndex);
File logFile = new File(getSDCardPath() + "/DJIDemo/cache/log/" + files[downLoadMediaFileIndex].getName());
if (!logFile.exists() || !logFile.canRead()) {
LogUtil.log(TAG, "文件不存在或不可读: " + logFile.getName());
skipToNext(message);
return;
}
minIOUpLoadAMSLog(message, logFile);
}
@RequiresApi(Build.VERSION_CODES.O)
private void skipToNext(MQMessage message) {
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex >= files.length) {
downLoadMediaFileIndex = 0;
setUploadingAMSLog(false);
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> pullOriginalFile(message), 500);
}
}
@RequiresApi(Build.VERSION_CODES.O)
public void minIOUpLoadAMSLog(MQMessage message, File file) {
try {
LogUtil.log(TAG, "开始上传: " + file.getName() + "" + message.getUpload_url());
AmazonS3 s3 = new AmazonS3Client(new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return message.getAccess_key();
}
@Override
public String getAWSSecretKey() {
return message.getSecret_key();
}
});
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
// 修改trim 去掉 URL 末尾空格
s3.setEndpoint(message.getUpload_url().trim());
boolean bucketExists = s3.doesBucketExist(message.getBucketName());
if (!bucketExists) {
s3.createBucket(message.getBucketName());
}
// 修改去掉开头的 /避免路径问题
String objectKey = message.getObjectKey() + "/" + file.getName();
s3.putObject(
new PutObjectRequest(
message.getBucketName(),
objectKey,
file
)
);
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(
message.getBucketName(),
objectKey
);
String url = s3.generatePresignedUrl(urlRequest).toString();
emitter.onNext(url);
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {}
@Override
public void onNext(String url) {
FileUploadResult fileUploadResult = new FileUploadResult();
fileUploadResult.setFileName(file.getName());
fileUploadResult.setResult(1);
fileUploadResult.setFileNum(files.length);
fileUploadResult.setBuckName(message.getBucketName());
fileUploadResult.setObjectKey(message.getObjectKey());
fileUploadResult.setUrl(url);
fileUploadResult.setOffIndex(downLoadMediaFileIndex);
if (files.length == (downLoadMediaFileIndex + 1)) {
fileUploadResult.setMsg("所有日志已上传完毕");
} else {
fileUploadResult.setMsg("文件:" + file.getName() + "已上传");
}
fileUploadResult.setProgress(String.valueOf(calculatePercentage(downLoadMediaFileIndex + 1, files.length)));
sendFileUploadCallback(60202, fileUploadResult);
}
@RequiresApi(Build.VERSION_CODES.O)
@Override
public void onError(Throwable e) {
LogUtil.log(TAG, "Error uploading file " + downLoadMediaFileIndex + file.getName() + ": " + e.getMessage());
e.printStackTrace();
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex >= files.length) {
downLoadMediaFileIndex = 0;
setUploadingAMSLog(false);
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> pullOriginalFile(message), 1000);
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Override
public void onComplete() {
LogUtil.log(TAG, "File " + downLoadMediaFileIndex + file.getName() + " uploaded successfully.");
sendMissionExecuteEvents("" + downLoadMediaFileIndex + "个AMS日志已上传");
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex >= files.length) {
sendMissionExecuteEvents("所有AMS日志已上传完毕");
downLoadMediaFileIndex = 0;
setUploadingAMSLog(false);
} else {
new Handler(Looper.getMainLooper()).postDelayed(() -> pullOriginalFile(message), 500);
}
}
});
} catch (Exception e) {
LogUtil.log(TAG, "Exception: " + e.getMessage());
e.printStackTrace();
skipToNext(message);
}
}
public String getLogDir() {
return getSDCardPath() + "/DJIDemo/cache/log";
}
private String getSDCardPath() {
String sdCardPathString = "";
if (checkSDCard()) {
sdCardPathString = Environment.getExternalStorageDirectory().getPath();
} else {
sdCardPathString = Environment.getExternalStorageDirectory().getParentFile().getPath();
}
return sdCardPathString;
}
private boolean checkSDCard() {
return TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
}
public int calculatePercentage(int a, int b) {
if (b == 0) {
return 0;
}
return (a * 100) / b;
}
}

View File

@ -0,0 +1,430 @@
package com.aros.apron.manager;
import static android.os.Environment.getExternalStoragePublicDirectory;
import static com.aros.apron.manager.FlightManager.FLAG_STOP_ARUCO;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.FlightMission;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.entity.MissionPoint;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.DomParserKML;
import com.aros.apron.tools.DomParserWPML;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.aros.apron.tools.ZipUtil;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.common.EmptyMsg;
import dji.sdk.keyvalue.value.flightcontroller.FlightCoordinateSystem;
import dji.sdk.keyvalue.value.flightcontroller.FlightMode;
import dji.sdk.keyvalue.value.flightcontroller.RemoteControllerFlightMode;
import dji.sdk.keyvalue.value.flightcontroller.RollPitchControlMode;
import dji.sdk.keyvalue.value.flightcontroller.VerticalControlMode;
import dji.sdk.keyvalue.value.flightcontroller.VirtualStickFlightControlParam;
import dji.sdk.keyvalue.value.flightcontroller.YawControlMode;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.aircraft.virtualstick.VirtualStickManager;
import dji.v5.manager.aircraft.waypoint3.WaypointMissionManager;
import dji.v5.manager.interfaces.IWaypointMissionManager;
/**
* 备降点
*/
public class AlternateLandingManager extends BaseManager {
Handler handler = new Handler(Looper.getMainLooper());
VirtualStickFlightControlParam param;
private boolean isRemoteControllerFlightModeChange;
private AlternateLandingManager() {
}
public static AlternateLandingManager getInstance() {
return AlternateLandingHolder.INSTANCE;
}
public void initAlterLandingInfo() {
KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode), this, new CommonCallbacks.KeyListener<RemoteControllerFlightMode>() {
@Override
public void onValueChange(@Nullable RemoteControllerFlightMode remoteControllerFlightMode, @Nullable RemoteControllerFlightMode t1) {
if (t1 != null) {
LogUtil.log(TAG, "监听到挡位切换:" + t1.name());
if (t1 != RemoteControllerFlightMode.P && t1 != RemoteControllerFlightMode.F) {
isRemoteControllerFlightModeChange = true;
PreferenceUtils.getInstance().setNeedTriggerAlterArucoLand(false);
PreferenceUtils.getInstance().setNeedTriggerApronArucoLand(false);
PreferenceUtils.getInstance().setTriggerToAlternatePoint(false);
}
}
}
});
}
public void startTaskProcess(MQMessage message) {
//飞往备降点,关闭视觉识别
EventBus.getDefault().post(FLAG_STOP_ARUCO);
if (isRemoteControllerFlightModeChange) {
LogUtil.log(TAG, "挡位切换过:不触发去备降点");
return;
}
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
Boolean areMotorOn = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyAreMotorsOn));
Boolean isFlying = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyIsFlying));
if ((areMotorOn != null && areMotorOn) && (isFlying != null && isFlying)) {
RemoteControllerFlightMode remoteControllerFlightMode = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode));
if (remoteControllerFlightMode != null && remoteControllerFlightMode == RemoteControllerFlightMode.P) {
checkDroneState(message);
} else {
if (message != null) {
sendMsg2Server(message, "挡位不正确,不触发去备降点");
}
sendMissionExecuteEvents( "挡位不正确,不触发去备降点");
LogUtil.log(TAG, "检测到挡位不正确,不触发去备降点");
}
} else {
if (message != null) {
sendMsg2Server( message, "飞机未起飞,不触发去备降点");
}
sendMissionExecuteEvents( "飞机未起飞,不触发去备降点");
}
}
}
private void checkDroneState(MQMessage message) {
FlightMode flightMode = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyFlightMode));
if (flightMode != null) {
switch (flightMode) {
case GO_HOME:
KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopGoHome), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG, "取消返航成功");
toAlternatePoint(message);
sendMissionExecuteEvents( "取消返航:去备降点");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "取消返航失败:" + new Gson().toJson(error));
toAlternatePoint(message);
sendMissionExecuteEvents( "取消返航失败:去备降点");
}
});
break;
case WAYPOINT:
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
missionManager.stopMission(TextUtils.isEmpty(Movement.getInstance().getMissionName())
? "aros" : Movement.getInstance().getMissionName(), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "终止任务成功");
sendMissionExecuteEvents( "终止任务成功:去备降点");
toAlternatePoint(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "终止任务失败:" + new Gson().toJson(error));
sendMissionExecuteEvents( "终止任务失败:去备降点");
toAlternatePoint(message);
}
});
break;
case AUTO_LANDING:
KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopAutoLanding), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG, "取消降落成功");
sendMissionExecuteEvents( "取消降落成功:去备降点");
toAlternatePoint(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "取消降落失败:" + new Gson().toJson(error));
sendMissionExecuteEvents( "取消降落失败:去备降点");
toAlternatePoint(message);
}
});
break;
case VIRTUAL_STICK:
// VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// LogUtil.log(TAG, "控制权取消成功");
toAlternatePoint(message);
// }
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "控制权取消失败:" + new Gson().toJson(error));
// toAlternatePoint();
// }
// });
break;
default:
toAlternatePoint(message);
break;
}
}
}
public void toAlternatePoint(MQMessage message) {
if (Movement.getInstance().getFlyingHeight() < 10) {
LogUtil.log(TAG, "toAlternatePoint:" + "高度低于10米,拉高");
sendMissionExecuteEvents( "正在拉高去备降点");
raisesDrone(message);
} else {
sendMissionExecuteEvents( "开始创建备降任务");
LogUtil.log(TAG, "toAlternatePoint:" + "高度高于10米,创建备降任务");
creatMissionAndUpload(message);
}
}
public void raisesDrone(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
Boolean isVirtualStickControlModeEnabled = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyVirtualStickControlModeEnabled));
if (isVirtualStickControlModeEnabled != null && isVirtualStickControlModeEnabled) {
pullUp(message);
} else {
VirtualStickManager.getInstance().enableVirtualStick(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "备降拉高,控制权获取成功");
VirtualStickManager.getInstance().setVirtualStickAdvancedModeEnabled(true);
pullUp(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "备降拉高,控制权获取失败,直接上传备降航线:" + error.description());
creatMissionAndUpload(message);
}
});
}
} else {
LogUtil.log(TAG, "备降拉高,飞控未连接");
}
}
public void pullUp(MQMessage message) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (Movement.getInstance().getFlyingHeight() < 10) {
sendVirtualStickAdvancedParam();
handler.postDelayed(this, 200);
} else {
VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "到达10米,开始上传备降点航线");
creatMissionAndUpload(message);
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "到达10米,取消虚拟摇杆控制失败:" + new Gson().toJson(idjiError));
creatMissionAndUpload(message);
}
});
handler.removeCallbacks(this);
}
}
};
// 开始循环
handler.post(runnable);
}
//飞行器虚拟摇杆
public void sendVirtualStickAdvancedParam() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
if (param == null) {
param = new VirtualStickFlightControlParam();
param.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
param.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
param.setVerticalControlMode(VerticalControlMode.VELOCITY);
param.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
}
param.setPitch(0.0);//左右
param.setRoll(0.0);//前后
param.setYaw(0.0);//旋转
param.setVerticalThrottle(4.0);//上下
VirtualStickManager.getInstance().sendVirtualStickAdvancedParam(param);
}
}
public void creatMissionAndUpload(MQMessage message) {
// 创建第一个 MissionPoint 对象
MissionPoint missionPoint = new MissionPoint();
missionPoint.setLat(Movement.getInstance().getCurrentLatitude());
missionPoint.setLng(Movement.getInstance().getCurrentLongitude());
missionPoint.setSpeed(8.0);
missionPoint.setExecuteHeight(Movement.getInstance().getFlyingHeight()
> Double.parseDouble(PreferenceUtils.getInstance().getAlternatePointSecurityHeight())
? Movement.getInstance().getFlyingHeight() :
Double.parseDouble(PreferenceUtils.getInstance().getAlternatePointSecurityHeight()));
// 创建第二个 MissionPoint 对象
MissionPoint missionPoint1 = new MissionPoint();
missionPoint1.setLat(PreferenceUtils.getInstance().getAlternatePointLat());
missionPoint1.setLng(PreferenceUtils.getInstance().getAlternatePointLon());
LogUtil.log(TAG, "备降点经纬度:" + PreferenceUtils.getInstance().getAlternatePointLat() + "/" + PreferenceUtils.getInstance().getAlternatePointLon());
missionPoint1.setSpeed(7.0);
missionPoint1.setExecuteHeight(Movement.getInstance().getFlyingHeight()
> Double.parseDouble(PreferenceUtils.getInstance().getAlternatePointSecurityHeight())
? Movement.getInstance().getFlyingHeight() - 1 :
Double.parseDouble(PreferenceUtils.getInstance().getAlternatePointSecurityHeight()));
// 创建一个 MissionPoint 列表
List<MissionPoint> missionPoints = new ArrayList<>();
missionPoints.add(missionPoint);
missionPoints.add(missionPoint1);
// 创建 FlightMission 对象并设置其属性
FlightMission flightMission = new FlightMission();
flightMission.setPoints(missionPoints);
flightMission.setMissionId(2);
flightMission.setTakeOffSecurityHeight(Float.parseFloat(PreferenceUtils.getInstance().getAlternatePointSecurityHeight()));
flightMission.setSpeed(15.0);
LogUtil.log(TAG, "当前高度:" + Movement.getInstance().getFlyingHeight()
+ "---飞往备降点高度:" + Double.parseDouble(PreferenceUtils.getInstance().getAlternatePointSecurityHeight())
+ "---航线安全起飞高度:" + Float.parseFloat(PreferenceUtils.getInstance().getAlternatePointSecurityHeight()));
sendMissionExecuteEvents( "开始生成备降点航线");
// 生成xml文件
File file1 = new File(
getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz");
if (!file1.exists()) {
if (file1.mkdirs()) {
LogUtil.log(TAG, "生成备降航线成功");
sendMissionExecuteEvents( "生成备降路线文件成功");
} else {
LogUtil.log(TAG, "生成备降航线失败");
sendMissionExecuteEvents( "生成备降航线失败");
if (message != null) {
sendMsg2Server( message, "生成备降航线失败");
}
}
}
DomParserKML domParserKML = new DomParserKML(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz",
"/template.kml");
domParserKML.createKml(flightMission);
DomParserWPML domParserWPML = new DomParserWPML(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz",
"/waylines.wpml");
domParserWPML.createWpml(flightMission);
File kmzFile = new File(getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + File.separator + "alternate.kmz");
kmzFile.getParentFile().mkdirs();
try {
ZipUtil.zip(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + "/wpmz", getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "alternate.kmz");
} catch (IOException e) {
LogUtil.log(TAG, "备降航线压缩异常:" + e.toString());
sendMissionExecuteEvents( "备降任务生成异常");
if (message != null) {
sendMsg2Server( message, "备降任务生成异常");
}
throw new RuntimeException(e);
}
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
missionManager.pushKMZFileToAircraft(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "alternate.kmz", new CommonCallbacks.CompletionCallbackWithProgress<Double>() {
@Override
public void onProgressUpdate(Double aDouble) {
LogUtil.log(TAG, "备降点航线上传进度:" + aDouble + "%");
sendMissionExecuteEvents( "备降任务上传中:" + aDouble + "%");
}
@Override
public void onSuccess() {
LogUtil.log(TAG, "备降点航线上传成功");
sendMissionExecuteEvents( "备降点航线上传成功");
if (PreferenceUtils.getInstance().getHaveRTK() && !Movement.getInstance().isRtkSign()) {
RTKManager.getInstance().enableRtk(false);
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
missionManager.startMission("alternate", new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
PreferenceUtils.getInstance().setTriggerToAlternatePoint(true);
PreferenceUtils.getInstance().setNeedTriggerAlterArucoLand(false);
PreferenceUtils.getInstance().setNeedTriggerApronArucoLand(false);
LogUtil.log(TAG, "开始飞往备降点");
sendMissionExecuteEvents( "开始飞往备降点");
//设置为未开始识别二维码状态
FlightManager.getInstance().setSendDetect(false);
EventBus.getDefault().post(FLAG_STOP_ARUCO);
if (message != null) {
sendMsg2Server( message);
}
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
PreferenceUtils.getInstance().setTriggerToAlternatePoint(false);
LogUtil.log(TAG, "飞往备降点失败:" + new Gson().toJson(idjiError));
sendMissionExecuteEvents( "飞往备降点失败");
if (message != null) {
sendMsg2Server( message, "飞往备降点失败");
}
}
});
}
}, 1000);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "备降航线上传失败:" + new Gson().toJson(error));
PreferenceUtils.getInstance().setTriggerToAlternatePoint(false);
sendMissionExecuteEvents( "备降航线上传失败");
if (message != null) {
sendMsg2Server( message, "备降航线上传失败:" + getIDJIErrorMsg(error));
}
}
});
}
private static class AlternateLandingHolder {
private static final AlternateLandingManager INSTANCE = new AlternateLandingManager();
}
}

View File

@ -0,0 +1,162 @@
package com.aros.apron.manager;
import androidx.annotation.Nullable;
import com.aros.apron.base.BaseManager;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.MessageReply;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import dji.sdk.keyvalue.key.BatteryKey;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.flightcontroller.LowBatteryRTHInfo;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.manager.KeyManager;
/**
* 电池
*/
public class BatteryManager extends BaseManager {
private BatteryManager() {
}
private static class BatteryManagerHolder {
private static final BatteryManager INSTANCE = new BatteryManager();
}
public static BatteryManager getInstance() {
return BatteryManagerHolder.INSTANCE;
}
private boolean sendLowBatteryRTHPosition2Server;
public void initBatteryInfo() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(BatteryKey.KeyConnection, 0));
if (isConnect != null && isConnect) {
LowBatteryRTHInfo lowBatteryRTHInfo = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyLowBatteryRTHInfo));
if (lowBatteryRTHInfo != null) {
Movement.getInstance().setRemainFlightTime(lowBatteryRTHInfo.getRemainingFlightTime());
Movement.getInstance().setReturnHomePower(lowBatteryRTHInfo.getBatteryPercentNeededToGoHome());
Movement.getInstance().setLandingPower(lowBatteryRTHInfo.getBatteryPercentNeededToLand());
if (lowBatteryRTHInfo != null) {
Movement.getInstance().setLowBatteryRTHState(lowBatteryRTHInfo.getLowBatteryRTHStatus().value());
}
}
KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.
KeyLowBatteryRTHInfo), this, new CommonCallbacks.KeyListener<LowBatteryRTHInfo>() {
@Override
public void onValueChange(@Nullable LowBatteryRTHInfo lowBatteryRTHInfo, @Nullable LowBatteryRTHInfo t1) {
if (t1 != null) {
Movement.getInstance().setRemainFlightTime(t1.getRemainingFlightTime());
Movement.getInstance().setReturnHomePower(t1.getBatteryPercentNeededToGoHome());
Movement.getInstance().setLandingPower(t1.getBatteryPercentNeededToLand());
if (t1.getLowBatteryRTHStatus() != null) {
Movement.getInstance().setLowBatteryRTHState(t1.getLowBatteryRTHStatus().value());
if (t1.getLowBatteryRTHStatus().value()==1&&!sendLowBatteryRTHPosition2Server){
sendLowBatteryRTHPosition2Server = true;
sendLowBatteryRTHPosition2Server();
}
}
}
}
});
/**************************************************************************************************************/
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyChargeRemainingInPercent, 0), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer oldValue, @Nullable Integer newValue) {
if (newValue != null) {
Movement.getInstance().setElectricityInfoA(newValue);
}
}
});
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyChargeRemainingInPercent, 0), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer oldValue, @Nullable Integer newValue) {
if (newValue != null) {
Movement.getInstance().setElectricityInfoA(newValue);
}
}
});
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyVoltage, 0), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer oldValue, @Nullable Integer newValue) {
if (newValue != null) {
Movement.getInstance().setVoltageInfoA(newValue);
}
}
});
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyBatteryTemperature, 0), this, new CommonCallbacks.KeyListener<Double>() {
@Override
public void onValueChange(@Nullable Double aDouble, @Nullable Double t1) {
if (t1 != null) {
Movement.getInstance().setBatteryTemperatureA(t1);
}
}
});
}
/********************************************************************************************************************/
Boolean isConnectBatteryB = KeyManager.getInstance().getValue(KeyTools.createKey(BatteryKey.KeyConnection, 1));
if (isConnectBatteryB != null && isConnectBatteryB) {
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyChargeRemainingInPercent, 1), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer oldValue, @Nullable Integer newValue) {
if (newValue != null) {
Movement.getInstance().setElectricityInfoB(newValue);
}
}
});
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyVoltage, 1), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer oldValue, @Nullable Integer newValue) {
if (newValue != null) {
Movement.getInstance().setVoltageInfoB(newValue);
}
}
});
KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.
KeyBatteryTemperature, 1), this, new CommonCallbacks.KeyListener<Double>() {
@Override
public void onValueChange(@Nullable Double aDouble, @Nullable Double t1) {
if (t1 != null) {
Movement.getInstance().setBatteryTemperatureB(t1);
}
}
});
}
}
public void releaseBatteryKey() {
KeyManager.getInstance().cancelListen(this);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,104 @@
package com.aros.apron.manager;
import android.os.Handler;
import android.os.Looper;
import com.aros.apron.base.BaseManager;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.MessageReply;
import com.aros.apron.tools.LogUtil;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.nio.charset.StandardCharsets;
public class DockCloseManager extends BaseManager {
private final int maxRetries = 2;
private int sendDockCloseSuccessTimes;
private boolean isSendDockCloseSuccess;
private DockCloseManager() {
}
private static class DockCloseHolder {
private static final DockCloseManager INSTANCE = new DockCloseManager();
}
public static DockCloseManager getInstance() {
return DockCloseHolder.INSTANCE;
}
public void sendDockCloseMsg2Server(MqttAndroidClient client) {
// if (isSendDockCloseSuccess||sendDockCloseSuccessTimes >= maxRetries) {
if (sendDockCloseSuccessTimes >= maxRetries) {
LogUtil.log(TAG, "达到最大重试次数或已发送关舱"+isSendDockCloseSuccess+sendDockCloseSuccessTimes);
return;
}
try {
if (client.isConnected()) {
sendDockCloseMessage(client);
} else {
handleNotConnected(client);
}
} catch (Exception e) {
LogUtil.log(TAG, "关舱异常:" + e.toString());
e.printStackTrace();
}
}
private void sendDockCloseMessage(MqttAndroidClient client){
MessageReply message = new MessageReply();
message.setMsg_type(60107);
message.setResult(1);
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes(StandardCharsets.UTF_8));
mqttMessage.setQos(0);
try {
client.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
LogUtil.log(TAG, "关舱发送成功60107---"+sendDockCloseSuccessTimes+"clientId:"+client.getClientId());
sendMissionExecuteEvents("AMS通知机库关舱");
isSendDockCloseSuccess = true;
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LogUtil.log(TAG, "关舱发送回调失败:" + exception.toString());
retrySend(client);
}
});
} catch (Exception e) {
LogUtil.log(TAG, "关舱发送异常:" + e.toString());
e.printStackTrace();
}
}
final Handler mainHandler = new Handler(Looper.getMainLooper());
private void retrySend(MqttAndroidClient client) {
sendDockCloseSuccessTimes++;
if (sendDockCloseSuccessTimes < maxRetries) {
mainHandler.postDelayed(() -> sendDockCloseMsg2Server(client), 2000);
} else {
LogUtil.log(TAG, "达到最大重试次数,关舱发送失败:" + sendDockCloseSuccessTimes);
}
}
private void handleNotConnected(MqttAndroidClient client) {
if (!isSendDockCloseSuccess && sendDockCloseSuccessTimes < maxRetries) {
sendDockCloseSuccessTimes++;
mainHandler.postDelayed(() -> sendDockCloseMsg2Server(client), 2000);
LogUtil.log(TAG, "关舱发送失败mqtt未连接" + "--" + sendDockCloseSuccessTimes);
} else {
LogUtil.log(TAG, "关舱发送失败:" + sendDockCloseSuccessTimes);
}
}
}

View File

@ -0,0 +1,129 @@
package com.aros.apron.manager;
import android.os.Handler;
import android.os.Looper;
import com.aros.apron.base.BaseManager;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.ApronExecutionStatus;
import com.aros.apron.entity.MessageReply;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.LogUtil;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.nio.charset.StandardCharsets;
public class DockOpenManager extends BaseManager {
private final int maxRetries = 20;
private int sendDockOpenSuccessTimes;
private boolean isSendDockOpenSuccess;
private DockOpenManager() {
}
private static class DockOpenHolder {
private static final DockOpenManager INSTANCE = new DockOpenManager();
}
public static DockOpenManager getInstance() {
return DockOpenHolder.INSTANCE;
}
public void sendDockOpenMsg2Server(MqttAndroidClient client) {
// if (isSendDockOpenSuccess||sendDockOpenSuccessTimes >= maxRetries) {
if (sendDockOpenSuccessTimes >= maxRetries) {
LogUtil.log(TAG, "达到最大重试次数或已发送开舱"+isSendDockOpenSuccess+sendDockOpenSuccessTimes);
return;
}
try {
if (client.isConnected()) {
sendDockOpenMessage(client);
} else {
handleNotConnected(client);
}
} catch (Exception e) {
LogUtil.log(TAG, "开舱发送异常:" + e.toString());
e.printStackTrace();
}
}
private void sendDockOpenMessage(MqttAndroidClient client){
try {
if (client.isConnected()) {
MessageReply message = new MessageReply();
message.setMsg_type(60108);
message.setResult(1);
message.setMsg("开门");
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes(StandardCharsets.UTF_8));
mqttMessage.setQos(0);
client.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
LogUtil.log(TAG, "开舱发送成功60108---" + sendDockOpenSuccessTimes + "clientId:" + client.getClientId());
sendMissionExecuteEvents("AMS通知机库开舱");
mainHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (ApronExecutionStatus.getInstance().isServerReplyDockOpen()) {
isSendDockOpenSuccess = true;
LogUtil.log(TAG, "已经收到服务端响应开门");
} else {
if (Movement.getInstance().isPlaneWing()&&Movement.getInstance().getFlyingHeight()>40){
LogUtil.log(TAG, "未收到收到服务端响应开门,重新发送");
retrySend(client);
}else{
LogUtil.log(TAG,"飞机状态不满足开舱门条件:"+Movement.getInstance().isPlaneWing()+"--"+Movement.getInstance().getFlyingHeight());
}
}
}
}, 2000);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LogUtil.log(TAG, "开舱发送回调失败:" + exception.toString());
retrySend(client);
}
});
} else {
LogUtil.log(TAG, "开舱发送回调失败mqtt 未连接");
}
} catch (Exception e) {
e.printStackTrace();
LogUtil.log(TAG, "开舱发送异常:" + e.toString());
}
}
final Handler mainHandler = new Handler(Looper.getMainLooper());
private void retrySend(MqttAndroidClient client) {
sendDockOpenSuccessTimes++;
if (sendDockOpenSuccessTimes < maxRetries) {
mainHandler.postDelayed(() -> sendDockOpenMsg2Server(client), 2000);
} else {
LogUtil.log(TAG, "达到最大重试次数,开舱发送失败:" + sendDockOpenSuccessTimes);
}
}
private void handleNotConnected(MqttAndroidClient client) {
if (!isSendDockOpenSuccess && sendDockOpenSuccessTimes < maxRetries) {
sendDockOpenSuccessTimes++;
mainHandler.postDelayed(() -> sendDockOpenMsg2Server(client), 2000);
LogUtil.log(TAG, "开舱发送失败mqtt未连接" + "--" + sendDockOpenSuccessTimes);
} else {
LogUtil.log(TAG, "开舱发送失败:" + sendDockOpenSuccessTimes);
}
}
}

View File

@ -0,0 +1,122 @@
//package com.aros.apron.manager;
//
//import android.os.Handler;
//import android.os.Looper;
//
//import com.aros.apron.base.BaseManager;
//import com.aros.apron.constant.AMSConfig;
//import com.aros.apron.entity.ApronExecutionStatus;
//import com.aros.apron.entity.MessageReply;
//import com.aros.apron.tools.LogUtil;
//import com.google.gson.Gson;
//import org.eclipse.paho.android.service.MqttAndroidClient;
//import org.eclipse.paho.client.mqttv3.IMqttActionListener;
//import org.eclipse.paho.client.mqttv3.IMqttToken;
//import org.eclipse.paho.client.mqttv3.MqttMessage;
//import java.nio.charset.StandardCharsets;
//
//public class DroneShutdownManager extends BaseManager {
//
// private final int maxRetries = 20;
// private int sendDroneShutDownSuccessTimes;
// private boolean isSendDroneShutDownSuccess;
//
// private DroneShutdownManager() {
// }
//
// private static class DroneShutHolder {
// private static final DroneShutdownManager INSTANCE = new DroneShutdownManager();
// }
//
// public static DroneShutdownManager getInstance() {
// return DroneShutHolder.INSTANCE;
// }
//
//
// public void sendDroneShutDownMsg2Server(MqttAndroidClient client) {
//// if (isSendDroneShutDownSuccess||sendDroneShutDownSuccessTimes >= maxRetries) {
// if (sendDroneShutDownSuccessTimes >= maxRetries) {
// LogUtil.log(TAG, "达到最大重试次数或已发送关机"+isSendDroneShutDownSuccess+sendDroneShutDownSuccessTimes);
// return;
// }
// try {
// if (client.isConnected()) {
// sendShutDownMessage(client);
// } else {
// handleNotConnected(client);
// }
// } catch (Exception e) {
// LogUtil.log(TAG, "关机发送异常:" + e.toString());
// e.printStackTrace();
// }
// }
//
// private void sendShutDownMessage(MqttAndroidClient client) {
//
//
// try {
// if (client.isConnected()){
// MessageReply message = new MessageReply();
// message.setMsg_type(60011);
// message.setResult(1);
// message.setMsg("关机");
// MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes("UTF-8"));
// mqttMessage.setQos(0);
// client.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage, null, new IMqttActionListener() {
// @Override
// public void onSuccess(IMqttToken asyncActionToken) {
// LogUtil.log(TAG, "关机发送成功60011---"+sendDroneShutDownSuccessTimes+"clientId:"+client.getClientId());
// sendMissionExecuteEvents( "AMS通知机库执行无人机关机");
// mainHandler.postDelayed(new Runnable() {
// @Override
// public void run() {
// if (ApronExecutionStatus.getInstance().isServerReplyDroneShut()) {
// isSendDroneShutDownSuccess = true;
// LogUtil.log(TAG, "已收到服务端响应飞机关机");
// } else {
// LogUtil.log(TAG, "未收到服务端响应飞机关机,重新发送");
// retrySend(client);
// }
// }
// }, 2000);
// }
//
// @Override
// public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
// LogUtil.log(TAG, "关机发送回调失败:" + exception.toString());
// retrySend(client);
// }
// });
// } else {
// LogUtil.log(TAG, "关机发送失败mqtt 未连接");
// }
//
// } catch (Exception e) {
// LogUtil.log(TAG, "关机发送异常:" + e.toString());
// e.printStackTrace();
// }
//
//
// }
// final Handler mainHandler = new Handler(Looper.getMainLooper());
//
// private void retrySend(MqttAndroidClient client) {
// sendDroneShutDownSuccessTimes++;
// if (sendDroneShutDownSuccessTimes < maxRetries) {
// mainHandler.postDelayed(() -> sendDroneShutDownMsg2Server(client), 2000);
// } else {
// LogUtil.log(TAG, "达到最大重试次数,关机发送失败:" + sendDroneShutDownSuccessTimes);
// }
// }
//
// private void handleNotConnected(MqttAndroidClient client) {
// if (!isSendDroneShutDownSuccess && sendDroneShutDownSuccessTimes < maxRetries) {
// sendDroneShutDownSuccessTimes++;
// mainHandler.postDelayed(() -> sendDroneShutDownMsg2Server(client), 2000);
// LogUtil.log(TAG, "关机发送失败mqtt未连接" + "--" + sendDroneShutDownSuccessTimes);
// } else {
// LogUtil.log(TAG, "关机发送失败:" + sendDroneShutDownSuccessTimes);
// }
// }
//
//}

View File

@ -0,0 +1,117 @@
package com.aros.apron.manager;
import android.os.Handler;
import android.os.Looper;
import com.aros.apron.base.BaseManager;
import com.aros.apron.constant.AMSConfig;
import com.aros.apron.entity.ApronExecutionStatus;
import com.aros.apron.entity.MessageReply;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import java.nio.charset.StandardCharsets;
public class DroneStorageManager extends BaseManager {
private final int maxRetries = 20;
private int sendDroneStorageSuccessTimes;
private boolean isSendDroneStorageSuccess;
private DroneStorageManager() {
}
private static class DroneStorageHolder {
private static final DroneStorageManager INSTANCE = new DroneStorageManager();
}
public static DroneStorageManager getInstance() {
return DroneStorageHolder.INSTANCE;
}
public void sendDroneStorageMsg2Server(int result) {
// if (isSendDroneStorageSuccess||sendDroneStorageSuccessTimes >= maxRetries) {
if (sendDroneStorageSuccessTimes >= maxRetries) {
LogUtil.log(TAG, "达到最大重试次数或已发送入库"+isSendDroneStorageSuccess+sendDroneStorageSuccessTimes);
return;
}
try {
if (MqttManager.getInstance().mqttAndroidClient.isConnected()) {
sendDroneStorageMessage(result);
} else {
handleNotConnected(MqttManager.getInstance().mqttAndroidClient,result);
}
} catch (Exception e) {
LogUtil.log(TAG, "入库发送异常:" + e.toString());
e.printStackTrace();
}
}
private void sendDroneStorageMessage(int result){
MessageReply message = new MessageReply();
message.setMsg_type(60010);
message.setResult(result);
MqttMessage mqttMessage = new MqttMessage(new Gson().toJson(message).getBytes(StandardCharsets.UTF_8));
mqttMessage.setQos(0);
try {
MqttManager.getInstance().mqttAndroidClient.publish(AMSConfig.getInstance().getMqttMsdkReplyMessage2ServerTopic(), mqttMessage, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
LogUtil.log(TAG, "入库已发送60010---" + sendDroneStorageSuccessTimes + "clientId:" + MqttManager.getInstance().mqttAndroidClient.getClientId());
sendMissionExecuteEvents( "AMS通知机库入库");
mainHandler.postDelayed(new Runnable() {
@Override
public void run() {
if (ApronExecutionStatus.getInstance().isServerReplyDockIn()) {
isSendDroneStorageSuccess = true;
LogUtil.log(TAG, "已经收到服务端响应入库");
} else {
LogUtil.log(TAG, "未收到服务端响应入库,重新发送");
retrySend(result);
}
}
}, 2000);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
LogUtil.log(TAG, "入库发送回调失败:" + exception.toString());
retrySend(result);
}
});
} catch (Exception e) {
LogUtil.log(TAG, "入库发送异常:" + e.toString());
e.printStackTrace();
}
}
final Handler mainHandler = new Handler(Looper.getMainLooper());
private void retrySend(int result) {
sendDroneStorageSuccessTimes++;
if (sendDroneStorageSuccessTimes < maxRetries) {
mainHandler.postDelayed(() -> DroneStorageManager.getInstance().sendDroneStorageMsg2Server(result), 2000);
} else {
LogUtil.log(TAG, "达到最大重试次数,入库发送失败:" + sendDroneStorageSuccessTimes);
}
}
private void handleNotConnected(MqttAndroidClient client,int result) {
if (!isSendDroneStorageSuccess && sendDroneStorageSuccessTimes < maxRetries) {
sendDroneStorageSuccessTimes++;
mainHandler.postDelayed(() -> DroneStorageManager.getInstance().sendDroneStorageMsg2Server(result), 2000);
LogUtil.log(TAG, "入库发送失败mqtt未连接" + "--" + sendDroneStorageSuccessTimes);
} else {
LogUtil.log(TAG, "入库发送失败:" + sendDroneStorageSuccessTimes);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,453 @@
package com.aros.apron.manager;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.ApronArucoDetect;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.PreferenceUtils;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import dji.sdk.keyvalue.key.CameraKey;
import dji.sdk.keyvalue.key.DJIKey;
import dji.sdk.keyvalue.key.DJIKeyInfo;
import dji.sdk.keyvalue.key.GimbalKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.camera.CameraType;
import dji.sdk.keyvalue.value.common.ComponentIndexType;
import dji.sdk.keyvalue.value.common.EmptyMsg;
import dji.sdk.keyvalue.value.gimbal.GimbalAngleRotation;
import dji.sdk.keyvalue.value.gimbal.GimbalAngleRotationMode;
import dji.sdk.keyvalue.value.gimbal.GimbalMode;
import dji.sdk.keyvalue.value.gimbal.GimbalResetType;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
public class GimbalManager extends BaseManager {
private GimbalManager() {
}
private static class GimbalHolder {
private static final GimbalManager INSTANCE = new GimbalManager();
}
public static GimbalManager getInstance() {
return GimbalHolder.INSTANCE;
}
public void initGimbalInfo() {
ApronArucoDetect.getInstance().setDoublePayload(PreferenceUtils.getInstance().getCameraLocationType() == 2);
}
//用相对角度模式旋转云台
public void gimbalRotateByRelativeAngle(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect && getGimbalAndCameraEnabled()) {
if (message.getX() == 0 && message.getY() == 0) {
gimbalReset();
} else {
int yaw = message.getX();
int pitch = message.getY();
GimbalAngleRotation rotation = new GimbalAngleRotation();
rotation.setMode(GimbalAngleRotationMode.RELATIVE_ANGLE);
rotation.setYaw(Double.valueOf(yaw));
rotation.setPitch(Double.valueOf(pitch));
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyRotateByAngle, ComponentIndexType.PORT_1), rotation, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
sendMsg2Server( message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"云台控制失败:"+new Gson().toJson(error));
sendMsg2Server( message, "云台控制失败:" + getIDJIErrorMsg(error));
}
}
);
}
} else {
sendMsg2Server( message, "云台未连接");
}
}
// //用绝对角度模式旋转云台
// public void gimbalRotateByAbsoluteAngle(MQMessage message) {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
// KeyConnection, ComponentIndexType.PORT_1));
// if (isConnect != null && isConnect) {
// if (message.getX() == 0 && message.getY() == 0) {
// gimbalReset();
// } else {
// int yaw = message.getX();
// int pitch = message.getY();
// GimbalAngleRotation rotation = new GimbalAngleRotation();
// rotation.setMode(GimbalAngleRotationMode.ABSOLUTE_ANGLE);
// rotation.setYaw(Double.valueOf(yaw * 10));
// rotation.setPitch(Double.valueOf(pitch * 10));
// KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyRotateByAngle, ComponentIndexType.PORT_1), rotation, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
// @Override
// public void onSuccess(EmptyMsg emptyMsg) {
// LogUtil.log(TAG, "云台控制成功:" + yaw + "---" + pitch);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "云台控制失败:" + error.description());
// }
// }
// );
// }
// } else {
// sendMsg2Server( message, "云台未连接");
// }
// }
//云台重置
public void gimbalReset() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect) {
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyGimbalReset, ComponentIndexType.PORT_1), GimbalResetType.PITCH_YAW, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG, "云台复位");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "云台复位失败:" + error.description());
}
}
);
} else {
LogUtil.log(TAG, "云台未连接");
}
}
//云台回中
public void gimbalResetWithPitchAndYaw(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect && getGimbalAndCameraEnabled()) {
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyGimbalReset, ComponentIndexType.PORT_1),
GimbalResetType.PITCH_YAW, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
sendMsg2Server(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"云台重置失败:"+new Gson().toJson(error));
sendMsg2Server(message, "云台控制失败:" + getIDJIErrorMsg(error));
}
}
);
} else {
sendMsg2Server(message, "云台重置失败:设备未连接");
}
}
//云台偏航回中
public void gimbalResetWithYaw(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect && getGimbalAndCameraEnabled()) {
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyGimbalReset, ComponentIndexType.PORT_1),
GimbalResetType.ONLY_YAW, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
sendMsg2Server(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"云台偏航回中失败:"+new Gson().toJson(error));
sendMsg2Server(message, "云台偏航回中失败:" + getIDJIErrorMsg(error));
}
}
);
} else {
sendMsg2Server(message, "云台偏航回中失败:设备未连接");
}
}
//偏航向下
public void gimbalDownWithPitch(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect && getGimbalAndCameraEnabled()) {
GimbalAngleRotation rotation = new GimbalAngleRotation();
rotation.setMode(GimbalAngleRotationMode.ABSOLUTE_ANGLE);
if (!TextUtils.isEmpty(Movement.getInstance().getGimbalYaw())){
rotation.setYaw(Double.parseDouble(Movement.getInstance().getGimbalYaw()));
}
rotation.setPitch(-90.0);
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyRotateByAngle, ComponentIndexType.PORT_1), rotation, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
sendMsg2Server(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
sendMsg2Server(message,"偏航向下失败:"+getIDJIErrorMsg(error));
}
}
);
} else {
sendMsg2Server(message, "云台偏航回中失败:设备未连接");
}
}
//云台朝下
public void gimbalDownWithPitchAndYaw(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect && getGimbalAndCameraEnabled()) {
GimbalAngleRotation rotation = new GimbalAngleRotation();
rotation.setMode(GimbalAngleRotationMode.ABSOLUTE_ANGLE);
rotation.setYaw(0.0);
rotation.setRoll(0.0);
rotation.setPitch(-90.0);
KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyRotateByAngle, ComponentIndexType.PORT_1), rotation, new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
sendMsg2Server(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
sendMsg2Server(message,"云台向下失败:"+getIDJIErrorMsg(error));
}
}
);
} else {
sendMsg2Server(message, "云台偏航回中失败:设备未连接");
}
}
//设置云台控制的最大速度[1,100]
public void setGimbalControlMaxSpeed(MQMessage
message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect!=null&&isConnect) {
DJIKey<Integer> pitchKey = KeyTools.createKey(GimbalKey.KeyPitchControlMaxSpeed, ComponentIndexType.PORT_1);
DJIKey<Integer> yawKey = KeyTools.createKey(GimbalKey.KeyYawControlMaxSpeed, ComponentIndexType.PORT_1);
if (pitchKey != null) {
setGimbalControlSpeed(message, pitchKey, "云台俯仰控制速度设置失败:");
} else {
LogUtil.log(TAG, "云台俯仰控制速度设置失败:pitchKey is null!");
}
if (yawKey != null) {
setGimbalControlSpeed( message, yawKey, "云台偏航控制速度设置失败:");
} else {
LogUtil.log(TAG, "云台偏航控制速度设置失败:yawKey is null!");
}
} else {
sendMsg2Server( message, "云台未连接");
}
}
private void setGimbalControlSpeed(MQMessage
message, DJIKey<Integer> key, String errorMessage) {
int value = message.getGimbalControlSpeed();
KeyManager.getInstance().setValue(key, value, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
sendMsg2Server( message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,errorMessage+new Gson().toJson(error));
sendMsg2Server( message, errorMessage + getIDJIErrorMsg(error));
}
});
}
//
// //恢复出厂设置
// public void setRestoreFactorySettings(MqttAndroidClient mqttAndroidClient, MQMessage
// message) {
// MQMessage.Data data = message.getData();
// if (data != null) {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
// KeyConnection, Integer.parseInt(data.getComponentIndex())));
// if (isConnect) {
// KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyRestoreFactorySettings, Integer.parseInt(data.getComponentIndex())), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
// @Override
// public void onSuccess(EmptyMsg emptyMsg) {
// sendMsg2Server( message);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// sendMsg2Server( message, "恢复出厂设置失败:" + error.description());
// }
// });
// } else {
// sendMsg2Server( message, "云台未连接");
// }
// }
//
// }
//
// //启动自动校准
// public void startGimbalCalibrate(MqttAndroidClient mqttAndroidClient, MQMessage
// message) {
// MQMessage.Data data = message.getData();
// if (data != null) {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
// KeyConnection, Integer.parseInt(data.getComponentIndex())));
// if (isConnect) {
// KeyManager.getInstance().performAction(KeyTools.createKey(GimbalKey.KeyGimbalCalibrate, Integer.parseInt(data.getComponentIndex())), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
// @Override
// public void onSuccess(EmptyMsg emptyMsg) {
// sendMsg2Server( message);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// sendMsg2Server( message, "启动校准失败:" + error.description());
// }
// });
// } else {
// sendMsg2Server( message, "云台未连接");
// }
// }
//
// }
//
// //设置云台缓启/范围[0,30]数值越大控制云台俯仰轴启动/停止转动的缓冲距离越长
// public void setSmoothingFactor(MQMessage message) {
// MQMessage.Data data = message.getData();
// if (data != null) {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
// KeyConnection, Integer.parseInt(data.getComponentIndex())));
// if (isConnect) {
// String value = data.getGimbalSmoothingFactor();
// String type = data.getGimbalSmoothingFactorType();
// KeyManager.getInstance().setValue(KeyTools.createKey(type.equals("0") ? GimbalKey.KeyPitchSmoothingFactor : GimbalKey.KeyYawSmoothingFactor, Integer.parseInt(data.getComponentIndex())), Integer.parseInt(value), new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// sendMsg2Server( message);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// sendMsg2Server( message, "云台缓启/停设置失败:" + error.description());
// }
// });
// } else {
// sendMsg2Server( message, "云台未连接");
// }
// }
//
//
// }
//
// //设置云台限位扩展
// public void setPitchRangeExtensionEnabled(MqttAndroidClient
// mqttAndroidClient, MQMessage message) {
// MQMessage.Data data = message.getData();
// if (data != null) {
// Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
// KeyConnection, Integer.parseInt(data.getComponentIndex())));
// if (isConnect) {
// String type = data.getPitchRangeExtensionEnabled();
// if (!TextUtils.isEmpty(type)) {
// KeyManager.getInstance().setValue(KeyTools.createKey(GimbalKey.KeyPitchRangeExtensionEnabled,
// Integer.parseInt(data.getComponentIndex())), type.equals("1") ? true : false, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// sendMsg2Server( message);
// }
//
// @Override
// public void onFailure(@NonNull IDJIError error) {
// sendMsg2Server( message, "设置云台俯仰扩展失败:" + error.description());
// }
// });
// } else {
// sendMsg2Server( message, "设置云台俯仰扩展参数有误");
// }
// } else {
// sendMsg2Server( message, "云台未连接");
// }
// }
//
// }
//
//设置云台模式
public void setGimbalMode(int gimbalMode) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(GimbalKey.
KeyConnection, ComponentIndexType.PORT_1));
if (isConnect != null && isConnect) {
KeyManager.getInstance().setValue(KeyTools.createKey(GimbalKey.KeyGimbalMode,
ComponentIndexType.PORT_1), GimbalMode.find(gimbalMode), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
switch (gimbalMode) {
case 0:
LogUtil.log(TAG, "设置云台自由模式成功");
gimbalReset();
break;
case 1:
LogUtil.log(TAG, "设置云台FPV模式成功");
break;
case 2:
LogUtil.log(TAG, "设置云台跟随模式成功");
break;
}
}
@Override
public void onFailure(@NonNull IDJIError error) {
switch (gimbalMode) {
case 0:
LogUtil.log(TAG, "设置云台自由模式失败:" + error.description());
break;
case 1:
LogUtil.log(TAG, "设置云台FPV模式失败:" + error.description());
break;
case 2:
LogUtil.log(TAG, "设置云台跟随模式失败:" + error.description());
break;
}
}
});
} else {
LogUtil.log(TAG, "设置云台模式失败:未连接");
}
}
public void releaseGimbalKey() {
KeyManager.getInstance().cancelListen(this);
}
}

View File

@ -0,0 +1,71 @@
package com.aros.apron.manager;
import androidx.annotation.NonNull;
import com.aros.apron.base.BaseManager;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.PreferenceUtils;
import com.google.gson.Gson;
import dji.sdk.keyvalue.key.FlightAssistantKey;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.flightassistant.AuxiliaryLightMode;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
public class LEDsSettingsManager extends BaseManager {
private LEDsSettingsManager() {
}
private static class LEDsSettingsHolder {
private static final LEDsSettingsManager INSTANCE = new LEDsSettingsManager();
}
public static LEDsSettingsManager getInstance() {
return LEDsSettingsHolder.INSTANCE;
}
public void initLEDsInfo() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
// LEDsSettings leDsSettings = new LEDsSettings();
// leDsSettings.setNavigationLEDsOn(PreferenceUtils.getInstance().getNavigationLEDsOn());
// leDsSettings.setFrontLEDsOn(true);
// leDsSettings.setRearLEDsOn(true);
// leDsSettings.setStatusIndicatorLEDsOn(true);
boolean navigationLEDsOn = PreferenceUtils.getInstance().getNavigationLEDsOn();
KeyManager.getInstance().setValue(KeyTools.createKey(FlightAssistantKey.KeyBottomAuxiliaryLightMode),
navigationLEDsOn ? AuxiliaryLightMode.ON : AuxiliaryLightMode.OFF, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "设置夜航灯使能:" + PreferenceUtils.getInstance().getNavigationLEDsOn());
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "设置夜航灯使能失败:" + new Gson().toJson(idjiError));
}
});
// KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings), leDsSettings, new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// LogUtil.log(TAG, "设置夜航灯使能:" + PreferenceUtils.getInstance().getNavigationLEDsOn());
// }
//
// @Override
// public void onFailure(@NonNull IDJIError idjiError) {
// LogUtil.log(TAG, "设置夜航灯使能失败:" + new Gson().toJson(idjiError));
// }
// });
} else {
LogUtil.log(TAG, "设置夜航灯失败");
}
}
}

View File

@ -0,0 +1,119 @@
package com.aros.apron.manager;
import android.os.Handler;
import androidx.annotation.NonNull;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.LogUtil;
import com.google.gson.Gson;
import java.util.List;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.airlink.WlmDongleInfo;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.aircraft.lte.LTEAuthenticationInfo;
import dji.v5.manager.aircraft.lte.LTEAuthenticationInfoListener;
import dji.v5.manager.aircraft.lte.LTEDongleInfoListener;
import dji.v5.manager.aircraft.lte.LTELinkInfo;
import dji.v5.manager.aircraft.lte.LTELinkInfoListener;
import dji.v5.manager.aircraft.lte.LTELinkType;
import dji.v5.manager.aircraft.lte.LTEManager;
public class MLTEManager extends BaseManager {
private MLTEManager() {
}
private static class LTEHolder {
private static final MLTEManager INSTANCE = new MLTEManager();
}
public static MLTEManager getInstance() {
return LTEHolder.INSTANCE;
}
public void initLTEManager() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
LTEManager.getInstance().addLTELinkInfoListener(new LTELinkInfoListener() {
@Override
public void onLTELinkInfoUpdate(LTELinkInfo info) {
if (info != null&&info.getLTELinkType()!=null) {
Movement.getInstance().setLTELinkType(info.getLTELinkType().name());
LogUtil.log(TAG, "当前图传类型:" + info.getLTELinkType().name());
}
}
});
// LTEManager.getInstance().addLTEDongleInfoListener(new LTEDongleInfoListener() {
// @Override
// public void onLTEAircraftDongleInfoUpdate(@NonNull List<WlmDongleInfo> aircraftDongleInfos) {
// if (!aircraftDongleInfos.isEmpty()) {
// LogUtil.log(TAG, "aircraft DongleInfo:" + new Gson().toJson(aircraftDongleInfos.get(0)));
// }
//
// }
//
// @Override
// public void onLTERemoteControllerDongleInfoUpdate(@NonNull List<WlmDongleInfo> remoteControllerDongleInfos) {
// LogUtil.log(TAG, "remote DongleInfo:" + new Gson().toJson(remoteControllerDongleInfos.get(0)));
//
// }
// });
// LTEManager.getInstance().addLTEAuthenticationInfoListener(new LTEAuthenticationInfoListener() {
// @Override
// public void onLTEAuthenticationInfoUpdate(LTEAuthenticationInfo info) {
// if (info != null) {
// LogUtil.log(TAG, "LTEAuthenticationInfo:" + new Gson().toJson(info));
// }
// }
// });
}
}
private int setLTEEnhancedTransmissionTypeTimes;
private boolean isLTEEnhancedTransmissionLte;
public void setLTEEnhancedTransmissionType() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
LTEManager.getInstance().setLTEEnhancedTransmissionType(LTELinkType.OCU_SYNC_LTE, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
isLTEEnhancedTransmissionLte=true;
LogUtil.log(TAG, "设置增强图传成功");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "设置增强图传第" + setLTEEnhancedTransmissionTypeTimes + "次开启失败:" + new Gson().toJson(idjiError));
if (!isLTEEnhancedTransmissionLte){
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (setLTEEnhancedTransmissionTypeTimes < 20) {
setLTEEnhancedTransmissionTypeTimes++;
setLTEEnhancedTransmissionType();
}
}
}, 3000);
}
}
});
}
}
}

View File

@ -0,0 +1,585 @@
package com.aros.apron.manager;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.ProgressEvent;
import com.amazonaws.services.s3.model.ProgressListener;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.ApronExecutionStatus;
import com.aros.apron.entity.FileUploadResult;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.PreferenceUtils;
import com.autonavi.base.amap.mapcore.FileUtil;
import com.google.gson.Gson;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.camera.MediaFileType;
import dji.sdk.keyvalue.value.common.ComponentIndexType;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.datacenter.MediaDataCenter;
import dji.v5.manager.datacenter.media.MediaFile;
import dji.v5.manager.datacenter.media.MediaFileDownloadListener;
import dji.v5.manager.datacenter.media.MediaFileListDataSource;
import dji.v5.manager.datacenter.media.MediaFileListState;
import dji.v5.manager.datacenter.media.MediaFileListStateListener;
import dji.v5.manager.datacenter.media.PullMediaFileListParam;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableEmitter;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
public class MediaManager extends BaseManager {
private final String TAG = "MediaManager";
private final String mediaFileDir = "/apronPic";
private MediaFileListState mState = null;
private List<MediaFile> mediaFiles = new ArrayList<>();
/* ===== ① 新增:已上传文件名集合(本次任务内有效) ===== */
private final Set<String> uploadedFileNames = new HashSet<>();
private int updatingRetryCount = 0;
private static final int MAX_UPDATING_RETRY = 50; // 最多重试50次
private int mediaRestartCount = 0;
private static final int MAX_MEDIA_RESTART = 1; // 最多重启3次
private MediaManager() {
}
private static class MediaManagerHolder {
private static final MediaManager INSTANCE = new MediaManager();
}
public static MediaManager getInstance() {
return MediaManager.MediaManagerHolder.INSTANCE;
}
public void init() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
MediaFileListDataSource source = new MediaFileListDataSource.Builder().setIndexType(ComponentIndexType.PORT_1).build();
MediaDataCenter.getInstance().getMediaManager().setMediaFileDataSource(source);
MediaDataCenter.getInstance().getMediaManager().addMediaFileListStateListener(new MediaFileListStateListener() {
@Override
public void onUpdate(MediaFileListState mediaFileListState) {
mState = mediaFileListState;
LogUtil.log(TAG, "当前媒体文件状态:" + mediaFileListState.name());
}
});
}
}
private int enterPlayBackFailTimes;
private boolean isEnablePlayback;
public void enablePlayback() {
updatingRetryCount = 0;
MediaDataCenter.getInstance().getMediaManager().enable(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "进入媒体模式成功");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
MediaFileListDataSource source = new MediaFileListDataSource.Builder().setIndexType(ComponentIndexType.PORT_1).build();
MediaDataCenter.getInstance().getMediaManager().setMediaFileDataSource(source);
MediaDataCenter.getInstance().getMediaManager().pullMediaFileListFromCamera(new PullMediaFileListParam.Builder().count(-1).build(), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG,"拉取成功");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG,"拉取失败");
}
});
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
pullMediaFileListFromCamera();
isEnablePlayback=true;
}
}, 5000);
isEnablePlayback=true;
}
},2000);
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, ""+enterPlayBackFailTimes+"次进入媒体模式失败:"+new Gson().toJson(idjiError));
if (!isEnablePlayback){
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (enterPlayBackFailTimes < 10) {
enterPlayBackFailTimes++;
enablePlayback();
}else{
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
sendMissionExecuteEvents( "媒体模式进入失败:关机");
}
}
}, 1500);
}
}
});
}
private int pullMediaFileListFromCameraFailTimes;
private boolean isPullMediaFileListFromCameraSuccess;
private void pullMediaFileListFromCamera(){
mState=MediaDataCenter.getInstance().getMediaManager().getMediaFileListState();
if (mState == MediaFileListState.UPDATING) {
updatingRetryCount++;
LogUtil.log(TAG, "状态为" + mState + ",第" + updatingRetryCount + "次重试");
if (updatingRetryCount >= MAX_UPDATING_RETRY) {
if (mediaRestartCount >= MAX_MEDIA_RESTART) {
LogUtil.log(TAG, "媒体模块重启" + MAX_MEDIA_RESTART + "次仍失败,强制关机");
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
sendMissionExecuteEvents("媒体模块故障,强制关机");
return;
}
mediaRestartCount++;
LogUtil.log(TAG, "媒体模块卡死,第" + mediaRestartCount + "次重启");
// 先退出媒体模式
MediaDataCenter.getInstance().getMediaManager().disable(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
// 延迟2秒后重新进入
new Handler().postDelayed(() -> {
enablePlayback(); // 重新走 enable -> pull 流程
}, 2000);
}
@Override
public void onFailure(@NonNull IDJIError error) {
// 退不出也强制关机
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
}
});
return;
}
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
pullMediaFileListFromCamera();
}
}, 3000);
return;
}
MediaDataCenter.getInstance().getMediaManager().pullMediaFileListFromCamera(new PullMediaFileListParam.Builder().count(-1).build(), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
isPullMediaFileListFromCameraSuccess=true;
// 成功时重置计数器
updatingRetryCount = 0;
// 成功后重置重启计数器为下次任务做准备
mediaRestartCount = 0;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// 二次检查状态防止延迟期间状态变化
if (mState == MediaFileListState.UP_TO_DATE) {
List<MediaFile> rawList =
MediaDataCenter.getInstance().getMediaManager().getMediaFileListData().getData();
/* ===== ② 过滤已上传文件 ===== */
mediaFiles = new ArrayList<>();
for (MediaFile mf : rawList) {
if (!uploadedFileNames.contains(mf.getFileName())) {
mediaFiles.add(mf);
} else {
LogUtil.log(TAG, "跳过已上传文件: " + mf.getFileName());
}
}
if (mediaFiles.isEmpty()) {
LogUtil.log(TAG, "所有文件均已上传,直接清理");
downLoadMediaFileIndex = 0;
removeAllFiles();
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
pullOriginalMediaFileFromCamera();
}
} else {
LogUtil.log(TAG, "延迟后状态变为:" + mState + ",重新等待");
// 状态变化时重试而不是直接失败
if (pullMediaFileListFromCameraFailTimes < 10) {
pullMediaFileListFromCameraFailTimes++;
pullMediaFileListFromCamera();
} else {
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
sendMissionExecuteEvents("拉取媒体文件失败:" + mState);
LogUtil.log(TAG, "拉取媒体文件失败,当前状态:" + mState);
disablePlayback();
LogUtil.log(TAG, "发送关闭无人机");
}
}
}
},2000);
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, ""+pullMediaFileListFromCameraFailTimes+"拉取媒体文件失败:"+new Gson().toJson(idjiError));
if (!isPullMediaFileListFromCameraSuccess){
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (pullMediaFileListFromCameraFailTimes < 10) {
pullMediaFileListFromCameraFailTimes++;
pullMediaFileListFromCamera();
}else{
LogUtil.log(TAG, "拉取媒体文件失败:" + new Gson().toJson(idjiError));
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
sendMissionExecuteEvents("拉取媒体文件失败");
disablePlayback();
LogUtil.log(TAG, "发送关闭无人机");
}
}
}, 1500);
}
}
}
);
}
@RequiresApi(Build.VERSION_CODES.O)
public void pullOriginalMediaFileFromCamera() {
final MediaFile mediaFile = mediaFiles.get(downLoadMediaFileIndex);
if ((!PreferenceUtils.getInstance().getNeedUpLoadVideo() && mediaFile.getFileType() == MediaFileType.MP4)
|| !mediaFile.getFileName().contains(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")))) {
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex == mediaFiles.size()) {
// This refers to when all files have been downloaded or failed. Clear SD card, cache, exit media mode, and shut down the drone
downLoadMediaFileIndex = 0;
removeAllFiles();
} else {
LogUtil.log(TAG, "Skipping file download: " + mediaFile.getFileName());
pullOriginalMediaFileFromCamera();
}
return;
}
LogUtil.log(TAG, "File size: " + mediaFile.getFileSize());
File dirs = new File(getSDCardPath() + mediaFileDir);
if (!dirs.exists()) {
dirs.mkdir();
}
String filePath = getSDCardPath() + mediaFileDir + "/" + mediaFile.getFileName();
File file = new File(filePath);
long offset = 0L;
if (file.exists()) {
offset = file.length();
}
try {
FileOutputStream outputStream = new FileOutputStream(file, true);
long beginTime = System.currentTimeMillis();
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
mediaFile.pullOriginalMediaFileFromCamera(0L, new MediaFileDownloadListener() {
@Override
public void onStart() {
// No action needed for start
}
@Override
public void onProgress(long total, long current) {
int tmpProgress = (int) ((1.0 * current / total) * 100);
Log.e(TAG, "File " + downLoadMediaFileIndex + ": " + mediaFile.getFileName() + " Download Progress: " + tmpProgress + "%");
}
@Override
public void onRealtimeDataUpdate(byte[] data, long position) {
try {
bos.write(data);
bos.flush();
} catch (IOException e) {
Log.e(TAG, "Write error: " + e.getMessage());
}
}
@Override
public void onFinish() {
LogUtil.log(TAG, "File:" + downLoadMediaFileIndex+"fileName:"+mediaFile.getFileName() + " downloaded successfully.");
minIOUpLoad(file, mediaFile);
try {
outputStream.close();
bos.close();
} catch (IOException error) {
LogUtil.log(TAG, "File " + downLoadMediaFileIndex + " error: " + error.getMessage());
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
}
}
@Override
public void onFailure(IDJIError error) {
LogUtil.log(TAG, "File " + downLoadMediaFileIndex + ": " + mediaFile.getFileName() + " download failed: " + new Gson().toJson(error));
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
sendMissionExecuteEvents( "" + downLoadMediaFileIndex + "个文件下载失败");
downLoadMediaFileIndex = 0;
}
});
} catch (IOException e) {
Log.e(TAG, "Error opening file: " + e.getMessage());
}
}
private AmazonS3 s3 = new AmazonS3Client(new AWSCredentials() {
@Override
public String getAWSAccessKeyId() {
return PreferenceUtils.getInstance().getAccessKey(); // minio的key
}
@Override
public String getAWSSecretKey() {
return PreferenceUtils.getInstance().getSecretKey(); // minio的密钥
}
}, Region.getRegion(Regions.US_EAST_1), new ClientConfiguration());
@RequiresApi(Build.VERSION_CODES.O)
public void minIOUpLoad(final File file, final MediaFile mediaFile) {
LogUtil.log(TAG, "文件路径=" + file.getAbsolutePath() + ", 文件大小=" + file.length());
Observable.create(new ObservableOnSubscribe<String>() {
@Override
public void subscribe(ObservableEmitter<String> emitter) throws Exception {
// 服务器地址
s3.setEndpoint(PreferenceUtils.getInstance().getUploadUrl()); // http://ip:端口号
boolean bucketExists = s3.doesBucketExist(PreferenceUtils.getInstance().getBucketName());
if (!bucketExists) {
s3.createBucket(PreferenceUtils.getInstance().getBucketName());
}
// 上传文件到网关MINIO存储服务
s3.putObject(
new PutObjectRequest(
PreferenceUtils.getInstance().getBucketName(),
"/" + PreferenceUtils.getInstance().getObjectKey() + "/" +
PreferenceUtils.getInstance().getTaskId() + "/" + mediaFile.getFileName(),
file
).withProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressEvent progressEvent) {
switch (progressEvent.getEventCode()) {
case ProgressEvent.PREPARING_EVENT_CODE:
LogUtil.log(TAG, "Preparing to upload file " + downLoadMediaFileIndex);
break;
case ProgressEvent.STARTED_EVENT_CODE:
long bytesTransferred = progressEvent.getBytesTransferred();
int percentage = (int) ((bytesTransferred * 100) / file.length());
LogUtil.log(TAG, "Upload started for file " + downLoadMediaFileIndex + ": " +
percentage + "% (" + bytesTransferred + " out of " + file.length() + " bytes)");
break;
case ProgressEvent.COMPLETED_EVENT_CODE:
LogUtil.log(TAG, "Upload completed for file " + downLoadMediaFileIndex);
break;
case ProgressEvent.FAILED_EVENT_CODE:
LogUtil.log(TAG, "Upload failed for file " + downLoadMediaFileIndex);
break;
case ProgressEvent.RESET_EVENT_CODE:
LogUtil.log(TAG, "Upload reset for file " + downLoadMediaFileIndex);
break;
}
}
})
);
// 获取文件上传后访问地址url
GeneratePresignedUrlRequest urlRequest = new GeneratePresignedUrlRequest(
PreferenceUtils.getInstance().getBucketName(),
"/" + PreferenceUtils.getInstance().getObjectKey() + "/"
+ PreferenceUtils.getInstance().getTaskId() + "/"+ mediaFile.getFileName()
);
String url = s3.generatePresignedUrl(urlRequest).toString();
// 文件上传后访问地址url
emitter.onNext(url);
emitter.onComplete();
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<String>() {
@Override
public void onSubscribe(Disposable d) {
// Handle on subscribe (optional)
}
@Override
public void onNext(String url) {
FileUploadResult fileUploadResult = new FileUploadResult();
fileUploadResult.setResult(1);
fileUploadResult.setFileName(mediaFile.getFileName());
fileUploadResult.setFileSize(mediaFile.getFileSize());
fileUploadResult.setFileNum(mediaFiles.size());
fileUploadResult.setBuckName(PreferenceUtils.getInstance().getBucketName());
fileUploadResult.setObjectKey(PreferenceUtils.getInstance().getObjectKey());
fileUploadResult.setTask_id(PreferenceUtils.getInstance().getTaskId());
fileUploadResult.setUrl(PreferenceUtils.getInstance().getUploadUrl());
fileUploadResult.setOffIndex(downLoadMediaFileIndex);
sendFileUploadCallback(60102, fileUploadResult);
}
@RequiresApi(Build.VERSION_CODES.O)
@Override
public void onError(Throwable e) {
// 每上传失败一张就清除缓存
FileUtil.deleteFile(file);
LogUtil.log(TAG, "Error uploading file " + downLoadMediaFileIndex + ": " + e.getMessage());
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex == mediaFiles.size()) {
// 所有文件已经下载完成或失败清空SD卡缓存退出媒体模式发送无人机关机
downLoadMediaFileIndex = 0;
removeAllFiles();
} else {
pullOriginalMediaFileFromCamera();
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Override
public void onComplete() {
/* ===== ③ 上传成功时记入 Set ===== */
uploadedFileNames.add(mediaFile.getFileName());
FileUtil.deleteFile(file);
LogUtil.log(TAG, "File " + downLoadMediaFileIndex + " uploaded successfully.");
sendMissionExecuteEvents( "" + downLoadMediaFileIndex + "个文件已上传");
downLoadMediaFileIndex++;
if (downLoadMediaFileIndex == mediaFiles.size()) {
// 所有文件已上传完成清空SD卡缓存退出媒体模式发送无人机关机
sendMissionExecuteEvents( "媒体文件已上传完毕");
removeAllFiles();
downLoadMediaFileIndex = 0;
} else {
pullOriginalMediaFileFromCamera();
}
}
});
}
public void removeAllFiles() {
MediaDataCenter.getInstance().getMediaManager().deleteMediaFiles(mediaFiles, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
LogUtil.log(TAG, "清除文件成功 ");
sendMissionExecuteEvents("媒体文件已清除");
disablePlayback();
LogUtil.log(TAG, "发送关闭无人机");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
ApronExecutionStatus.getInstance().setAircraftWaitShutDown(true);
LogUtil.log(TAG, "清除文件失败: "+new Gson().toJson(idjiError));
sendMissionExecuteEvents( "媒体文件清除失败");
LogUtil.log(TAG, "发送关闭无人机");
}
});
}
//退出媒体模式
public void disablePlayback() {
MediaDataCenter.getInstance().getMediaManager().disable(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "退出媒体模式成功");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "退出媒体模式失败:"+new Gson().toJson(idjiError));
}
});
}
private int downLoadMediaFileIndex = 0;
private String getSDCardPath(){
if (checkSDCard()) {
return Environment.getExternalStorageDirectory()
.getPath();
} else {
return Environment.getExternalStorageDirectory()
.getParentFile().getPath();
}
}
private boolean checkSDCard() {
return TextUtils.equals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
}
// 写入 exif 信息
public void setMediaFileXMPCustomInfo( final MQMessage message) {
MediaDataCenter.getInstance().getMediaManager().setMediaFileXMPCustomInfo(
message.getXmpInfo(),
new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
sendMsg2Server(message);
sendMissionExecuteEvents( "设置文件XMP:" + message.getXmpInfo());
}
@Override
public void onFailure(IDJIError error) {
sendMsg2Server(message, "写入exif失败: " + getIDJIErrorMsg(error));
LogUtil.log(TAG, "写入exif失败:"+new Gson().toJson(error));
}
}
);
}
}

View File

@ -0,0 +1,175 @@
package com.aros.apron.manager;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.os.Handler;
import androidx.annotation.NonNull;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.tools.LogUtil;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import java.nio.charset.StandardCharsets;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.aircraft.megaphone.FileInfo;
import dji.v5.manager.aircraft.megaphone.MegaphoneIndex;
import dji.v5.manager.aircraft.megaphone.PlayMode;
import dji.v5.manager.aircraft.megaphone.UploadType;
import dji.v5.manager.aircraft.megaphone.WorkMode;
import dji.v5.manager.interfaces.IMegaphoneManager;
public class MegaphoneManager extends BaseManager {
private MegaphoneManager() {
}
private static class MegaphoneHolder {
private static final MegaphoneManager INSTANCE = new MegaphoneManager();
}
public static MegaphoneManager getInstance() {
return MegaphoneHolder.INSTANCE;
}
//设置喊话器音量/播放模式
public void startMegaphonePlay(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IMegaphoneManager iMegaphoneManager = dji.v5.manager.aircraft.megaphone.MegaphoneManager.getInstance();
iMegaphoneManager.setMegaphoneIndex(MegaphoneIndex.PORT_2, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "喊话器位置设置成功");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "喊话器位置设置失败:" + idjiError.description());
}
});
iMegaphoneManager.setVolume(message.getMegaphoneVolume(), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
sendMsg2Server(message, "设置喊话器音量成功");
LogUtil.log(TAG, "喊话器音量设置成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"设置喊话器音量失败:" +new Gson().toJson(error));
sendMsg2Server(message, "设置喊话器音量失败:" + getIDJIErrorMsg(error));
}
});
iMegaphoneManager.setPlayMode(message.getMegaphonePlayMode() == 1 ? PlayMode.SINGLE : PlayMode.LOOP, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "设置喊话器播放模式成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"设置喊话器播放模式失败:" +new Gson().toJson(error));
sendMsg2Server(message, "设置喊话器播放模式失败:" + getIDJIErrorMsg(error));
}
});
iMegaphoneManager.setWorkMode(WorkMode.TTS, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
sendMsg2Server(message);
LogUtil.log(TAG, "喊话器工作模式设置成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"喊话器工作模式设置失败:" +new Gson().toJson(error));
sendMsg2Server(message, "喊话器工作模式设置失败:" + getIDJIErrorMsg(error));
}
});
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
iMegaphoneManager.startPushingFileToMegaphone(new FileInfo(UploadType.TTS_DATA, null,
message.getMegaphoneWord().getBytes(StandardCharsets.UTF_8)),
new CommonCallbacks.CompletionCallbackWithProgress<Integer>() {
@Override
public void onProgressUpdate(Integer integer) {
LogUtil.log(TAG, "喊话器内容上传进度:" + integer + "%");
}
@Override
public void onSuccess() {
LogUtil.log(TAG, "喊话器内容上传成功");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
startPlay(message);
}
}, 200);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"喊话器内容上传失败:" +new Gson().toJson(error));
sendMsg2Server(message, "喊话器内容上传失败:" + getIDJIErrorMsg(error));
}
});
}
}, 200);
} else {
sendMsg2Server(message, "飞控未连接");
LogUtil.log(TAG, "飞控未连接");
}
}
//播放
public void startPlay(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IMegaphoneManager iMegaphoneManager = dji.v5.manager.aircraft.megaphone.MegaphoneManager.getInstance();
iMegaphoneManager.startPlay(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "喊话器播放成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"喊话器播放失败:" +new Gson().toJson(error));
sendMsg2Server(message, "喊话器播放失败:" + getIDJIErrorMsg(error));
}
});
} else {
sendMsg2Server(message, "飞控未连接");
}
}
//停止播放
public void stopPlay(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IMegaphoneManager iMegaphoneManager = dji.v5.manager.aircraft.megaphone.MegaphoneManager.getInstance();
iMegaphoneManager.stopPlay(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
sendMsg2Server(message);
LogUtil.log(TAG, "喊话器停止播放成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG,"喊话器停止播放失败:" +new Gson().toJson(error));
sendMsg2Server(message, "喊话器停止播放失败:" + getIDJIErrorMsg(error));
}
});
} else {
LogUtil.log(TAG, "喊话器停止播放失败");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
//package com.aros.apron.manager;
//
//import com.dji.wpmzsdk.common.data.Template;
//import com.dji.wpmzsdk.interfaces.IWPMZManager;
//import com.dji.wpmzsdk.manager.WPMZManager;
//
//import dji.sdk.wpmz.value.mission.WaylineMission;
//import dji.sdk.wpmz.value.mission.WaylineMissionConfig;
//import dji.sdk.wpmz.value.mission.WaylineTemplateWaypointInfo;
//import dji.sdk.wpmz.value.mission.WaylineWaypoint;
//
//public class MissionTest {
// public void test(){
// WaylineMission waylineMission=new WaylineMission();
// WaylineMissionConfig waylineMissionConfig=new WaylineMissionConfig();
// Template template=new Template();
// template.setWaypointInfo();
// WaylineTemplateWaypointInfo waylineTemplateWaypointInfo=new WaylineTemplateWaypointInfo();
// waylineTemplateWaypointInfo.setWaypoints();
// WaylineWaypoint waylineWaypoint=new WaylineWaypoint();
// waylineWaypoint.se
// IWPMZManager iwpmzManager= WPMZManager.getInstance();
// iwpmzManager.generateKMZFile("",);
// }
//}

View File

@ -0,0 +1,94 @@
package com.aros.apron.manager;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import static dji.sdk.keyvalue.key.KeyTools.createKey;
import android.os.Handler;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.PreferenceUtils;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.flightcontroller.NavigationSatelliteSystem;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
public class NavigationSatelliteSystemManager extends BaseManager {
private NavigationSatelliteSystemManager() {
}
private static class NavigationSatelliteHolder {
private static final NavigationSatelliteSystemManager INSTANCE = new NavigationSatelliteSystemManager();
}
public static NavigationSatelliteSystemManager getInstance() {
return NavigationSatelliteHolder.INSTANCE;
}
public void initNavigationSatelliteSystem() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
KeyManager.getInstance().listen(createKey(FlightControllerKey.KeyNavigationSatelliteSystemSource),
this, new CommonCallbacks.KeyListener<NavigationSatelliteSystem>() {
@Override
public void onValueChange(@Nullable NavigationSatelliteSystem navigationSatelliteSystem,
@Nullable NavigationSatelliteSystem t1) {
if (t1 != null) {
LogUtil.log(TAG, "监听卫星导航系统:" + t1.name());
Movement.getInstance().setNavigationSatelliteSystem(t1.value());
}
}
});
}
}
private int setLTEEnhancedTransmissionTypeTimes;
private boolean isLTEEnhancedTransmissionLte;
public void setNavigationSatelliteSystem() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyNavigationSatelliteSystemSource),
PreferenceUtils.getInstance().getSatelliteSystem() == 1 ?
NavigationSatelliteSystem.GPS_GLONASS : NavigationSatelliteSystem.BEIDOU,
new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
isLTEEnhancedTransmissionLte = true;
LogUtil.log(TAG, "设置卫星系统" + setLTEEnhancedTransmissionTypeTimes + "次成功");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "设置卫星系统第" + setLTEEnhancedTransmissionTypeTimes + "次失败:" + getIDJIErrorMsg(error));
if (!isLTEEnhancedTransmissionLte) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (setLTEEnhancedTransmissionTypeTimes < 20) {
setLTEEnhancedTransmissionTypeTimes++;
setNavigationSatelliteSystem();
}
}
}, 3000);
}
}
});
}
}
}

View File

@ -0,0 +1,423 @@
package com.aros.apron.manager;
import static android.os.Environment.getExternalStoragePublicDirectory;
import static com.aros.apron.manager.FlightManager.FLAG_STOP_ARUCO;
import static com.aros.apron.tools.Utils.getIDJIErrorMsg;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.aros.apron.base.BaseManager;
import com.aros.apron.entity.FlightMission;
import com.aros.apron.entity.MQMessage;
import com.aros.apron.entity.MissionPoint;
import com.aros.apron.entity.Movement;
import com.aros.apron.tools.DomParserKML;
import com.aros.apron.tools.DomParserWPML;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.MqttManager;
import com.aros.apron.tools.PreferenceUtils;
import com.aros.apron.tools.ZipUtil;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import org.greenrobot.eventbus.EventBus;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.sdk.keyvalue.key.KeyTools;
import dji.sdk.keyvalue.value.common.EmptyMsg;
import dji.sdk.keyvalue.value.flightcontroller.FlightCoordinateSystem;
import dji.sdk.keyvalue.value.flightcontroller.FlightMode;
import dji.sdk.keyvalue.value.flightcontroller.RemoteControllerFlightMode;
import dji.sdk.keyvalue.value.flightcontroller.RollPitchControlMode;
import dji.sdk.keyvalue.value.flightcontroller.VerticalControlMode;
import dji.sdk.keyvalue.value.flightcontroller.VirtualStickFlightControlParam;
import dji.sdk.keyvalue.value.flightcontroller.YawControlMode;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.aircraft.virtualstick.VirtualStickManager;
import dji.v5.manager.aircraft.waypoint3.WaypointMissionManager;
import dji.v5.manager.interfaces.IWaypointMissionManager;
/**
* 异地降落
*/
public class OffSiteLandingManager extends BaseManager {
private int goHomeHeight;
private OffSiteLandingManager() {
}
private static class OffSiteLandingHolder {
private static final OffSiteLandingManager INSTANCE = new OffSiteLandingManager();
}
public static OffSiteLandingManager getInstance() {
return OffSiteLandingHolder.INSTANCE;
}
public void initOffSiteLandingInfo() {
KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyGoHomeHeight), this, new CommonCallbacks.KeyListener<Integer>() {
@Override
public void onValueChange(@Nullable Integer integer, @Nullable Integer t1) {
if (t1 != null&&t1>=0) {
goHomeHeight = t1;
LogUtil.log(TAG,"返航高度:"+goHomeHeight);
Movement.getInstance().setGoHomeHeight(goHomeHeight);
}else{
goHomeHeight=80;
LogUtil.log(TAG,"返航高度监听失败:"+goHomeHeight);
}
}
});
}
public void startTaskProcess(MQMessage message) {
if (TextUtils.isEmpty(message.getOffSitePointLat())||TextUtils.isEmpty(message.getOffSitePointLon())){
sendMissionExecuteEvents( "异地降落点经纬度有误");
LogUtil.log(TAG, "异地降落点经纬度有误,不触发异地降落");
return;
}
PerceptionManager.getInstance().setPerceptionEnable(false);
DockOpenManager.getInstance().sendDockOpenMsg2Server( MqttManager.getInstance().mqttAndroidClient);
//飞往异地降落点,关闭视觉识别
EventBus.getDefault().post(FLAG_STOP_ARUCO);
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.
KeyConnection));
if (isConnect != null && isConnect) {
Boolean areMotorOn = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyAreMotorsOn));
Boolean isFlying = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyIsFlying));
if ((areMotorOn != null && areMotorOn) && (isFlying != null && isFlying)) {
RemoteControllerFlightMode remoteControllerFlightMode = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyRemoteControllerFlightMode));
if (remoteControllerFlightMode != null && remoteControllerFlightMode == RemoteControllerFlightMode.P) {
checkDroneState(message);
} else {
if (message != null) {
sendMsg2Server(message, "挡位不正确,不触发异地降落");
}
sendMissionExecuteEvents( "挡位不正确,不触发异地降落");
LogUtil.log(TAG, "检测到挡位不正确,不触发异地降落");
}
} else {
if (message != null) {
sendMsg2Server(message, "飞机未起飞,不触发异地降落");
}
sendMissionExecuteEvents( "飞机未起飞,不触发异地降落");
}
}
}
private void checkDroneState(MQMessage message) {
FlightMode flightMode = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyFlightMode));
if (flightMode != null) {
switch (flightMode) {
case GO_HOME:
KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopGoHome), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG, "取消返航成功");
toOffsitePoint(message);
sendMissionExecuteEvents( "取消返航:触发异地降落");
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "取消返航失败:" + new Gson().toJson(error));
toOffsitePoint(message);
sendMissionExecuteEvents( "取消返航失败:不触发异地降落");
}
});
break;
case WAYPOINT:
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
missionManager.stopMission(TextUtils.isEmpty(Movement.getInstance().getMissionName())
? "aros" : Movement.getInstance().getMissionName(), new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "终止任务成功");
sendMissionExecuteEvents( "终止任务成功:去异地降落");
toOffsitePoint(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "终止任务失败:" + new Gson().toJson(error));
sendMissionExecuteEvents( "终止任务失败:去异地降落");
toOffsitePoint(message);
}
});
break;
case AUTO_LANDING:
KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopAutoLanding), new CommonCallbacks.CompletionCallbackWithParam<EmptyMsg>() {
@Override
public void onSuccess(EmptyMsg emptyMsg) {
LogUtil.log(TAG, "取消降落成功");
sendMissionExecuteEvents( "取消降落成功:去异地降落");
toOffsitePoint(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "取消降落失败:" + new Gson().toJson(error));
sendMissionExecuteEvents( "取消降落失败:去异地降落");
toOffsitePoint(message);
}
});
break;
case VIRTUAL_STICK:
// VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
// @Override
// public void onSuccess() {
// LogUtil.log(TAG, "控制权取消成功");
toOffsitePoint(message);
// }
// @Override
// public void onFailure(@NonNull IDJIError error) {
// LogUtil.log(TAG, "控制权取消失败:" + new Gson().toJson(error));
// toOffsitePoint();
// }
// });
break;
default:
toOffsitePoint(message);
break;
}
}
}
public void toOffsitePoint(MQMessage message) {
if (Movement.getInstance().getFlyingHeight() < 10) {
LogUtil.log(TAG, "高度低于10米,拉高");
sendMissionExecuteEvents( "拉高去异地降落点...");
raisesDrone(message);
} else {
sendMissionExecuteEvents( "开始创建异地降落任务");
LogUtil.log(TAG, "高度高于10米,创建异地降落任务");
creatMissionAndUpload(message);
}
}
public void raisesDrone(MQMessage message) {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
Boolean isVirtualStickControlModeEnabled = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyVirtualStickControlModeEnabled));
if (isVirtualStickControlModeEnabled != null && isVirtualStickControlModeEnabled) {
pullUp(message);
} else {
VirtualStickManager.getInstance().enableVirtualStick(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "异地降落拉高,控制权获取成功");
VirtualStickManager.getInstance().setVirtualStickAdvancedModeEnabled(true);
pullUp(message);
}
@Override
public void onFailure(@NonNull IDJIError error) {
LogUtil.log(TAG, "异地降落拉高,控制权获取失败,直接上传异地降落航线:" + error.description());
creatMissionAndUpload(message);
}
});
}
} else {
LogUtil.log(TAG, "异地降落拉高,飞控未连接");
}
}
Handler handler = new Handler(Looper.getMainLooper());
public void pullUp(MQMessage message) {
Runnable runnable = new Runnable() {
@Override
public void run() {
if (Movement.getInstance().getFlyingHeight() < 10) {
sendVirtualStickAdvancedParam();
handler.postDelayed(this, 200);
} else {
VirtualStickManager.getInstance().disableVirtualStick(new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "到达10米,开始上传异地降落航线");
creatMissionAndUpload(message);
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "到达10米,取消虚拟摇杆控制失败:" + new Gson().toJson(idjiError));
creatMissionAndUpload(message);
}
});
handler.removeCallbacks(this);
}
}
};
// 开始循环
handler.post(runnable);
}
VirtualStickFlightControlParam param;
//飞行器虚拟摇杆
public void sendVirtualStickAdvancedParam() {
Boolean isConnect = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
if (param == null) {
param = new VirtualStickFlightControlParam();
param.setRollPitchControlMode(RollPitchControlMode.VELOCITY);
param.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
param.setVerticalControlMode(VerticalControlMode.VELOCITY);
param.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
}
param.setPitch(0.0);//左右
param.setRoll(0.0);//前后
param.setYaw(0.0);//旋转
param.setVerticalThrottle(4.0);//上下
VirtualStickManager.getInstance().sendVirtualStickAdvancedParam(param);
}
}
public void creatMissionAndUpload(MQMessage message) {
// 创建第一个 MissionPoint 对象
MissionPoint missionPoint = new MissionPoint();
missionPoint.setLat(Movement.getInstance().getCurrentLatitude());
missionPoint.setLng(Movement.getInstance().getCurrentLongitude());
missionPoint.setSpeed(8.0);
missionPoint.setExecuteHeight(Movement.getInstance().getFlyingHeight()
> goHomeHeight
? Movement.getInstance().getFlyingHeight()-1 :
goHomeHeight);
// 创建第二个 MissionPoint 对象
MissionPoint missionPoint1 = new MissionPoint();
missionPoint1.setLat(message.getOffSitePointLat());
missionPoint1.setLng(message.getOffSitePointLon());
missionPoint1.setSpeed(7.0);
missionPoint1.setExecuteHeight(Movement.getInstance().getFlyingHeight()
> goHomeHeight
? Movement.getInstance().getFlyingHeight() -1 :
goHomeHeight);
// 创建一个 MissionPoint 列表
List<MissionPoint> missionPoints = new ArrayList<>();
missionPoints.add(missionPoint);
missionPoints.add(missionPoint1);
// 创建 FlightMission 对象并设置其属性
FlightMission flightMission = new FlightMission();
flightMission.setPoints(missionPoints);
flightMission.setMissionId(2);
flightMission.setTakeOffSecurityHeight(Float.parseFloat(PreferenceUtils.getInstance().getAlternatePointSecurityHeight()));
flightMission.setSpeed(15.0);
sendMissionExecuteEvents( "开始生成异地降落航线");
// 生成xml文件
File file1 = new File(
getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz");
if (!file1.exists()) {
if (file1.mkdirs()) {
LogUtil.log(TAG, "生成异地降落航线成功");
sendMissionExecuteEvents( "生成异地降落路线文件成功");
} else {
LogUtil.log(TAG, "生成异地降落航线失败");
sendMissionExecuteEvents( "生成异地降落航线失败");
if (message != null) {
sendMsg2Server(message, "生成异地降落航线失败");
}
}
}
DomParserKML domParserKML = new DomParserKML(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz",
"/template.kml");
domParserKML.createKml(flightMission);
DomParserWPML domParserWPML = new DomParserWPML(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "wpmz",
"/waylines.wpml");
domParserWPML.createWpml(flightMission);
File kmzFile = new File(getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS) + File.separator + "offsite.kmz");
kmzFile.getParentFile().mkdirs();
try {
ZipUtil.zip(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + "/wpmz", getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "offsite.kmz");
} catch (IOException e) {
LogUtil.log(TAG, "异地降落航线压缩异常:" + e.toString());
sendMissionExecuteEvents( "异地降落任务生成异常");
if (message != null) {
sendMsg2Server(message, "异地降落任务生成异常");
}
throw new RuntimeException(e);
}
IWaypointMissionManager missionManager = WaypointMissionManager.getInstance();
missionManager.pushKMZFileToAircraft(getExternalStoragePublicDirectory("KMZ").getAbsolutePath() + File.separator + "offsite.kmz", new CommonCallbacks.CompletionCallbackWithProgress<Double>() {
@Override
public void onProgressUpdate(Double aDouble) {
LogUtil.log(TAG, "异地降落航线上传进度:" + aDouble + "%");
sendMissionExecuteEvents( "异地降落任务上传中:" + aDouble + "%");
}
@Override
public void onSuccess() {
LogUtil.log(TAG, "异地降落航线上传成功");
sendMissionExecuteEvents( "异地降落航线上传成功");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
missionManager.startMission("offsite", new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "开始异地降落航线");
sendMissionExecuteEvents( "开始异地降落航线");
//设置为未开始识别二维码状态
FlightManager.getInstance().setSendDetect(false);
EventBus.getDefault().post(FLAG_STOP_ARUCO);
if (message != null) {
sendMsg2Server(message);
}
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "飞往异地降落点失败:" + new Gson().toJson(idjiError));
sendMissionExecuteEvents( "飞往异地降落点失败");
if (message != null) {
sendMsg2Server(message, "飞往异地降落点失败");
}
}
});
}
}, 1000);
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "异地降落航线上传失败:" + new Gson().toJson(idjiError));
sendMissionExecuteEvents( "异地降落航线上传失败");
if (message != null) {
sendMsg2Server(message, "异地降落航线上传失败:" + getIDJIErrorMsg(idjiError));
}
}
});
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
package com.aros.apron.manager;//package com.aros.apron.manager;
import static dji.sdk.keyvalue.key.KeyTools.createKey;
import android.os.Handler;
import androidx.annotation.NonNull;
import com.aros.apron.base.BaseManager;
import com.aros.apron.tools.LogUtil;
import com.aros.apron.tools.PreferenceUtils;
import com.google.gson.Gson;
import org.eclipse.paho.android.service.MqttAndroidClient;
import dji.sdk.keyvalue.key.FlightControllerKey;
import dji.v5.common.callback.CommonCallbacks;
import dji.v5.common.error.IDJIError;
import dji.v5.manager.KeyManager;
import dji.v5.manager.aircraft.perception.data.ObstacleAvoidanceType;
import dji.v5.manager.aircraft.perception.data.PerceptionDirection;
import dji.v5.manager.aircraft.perception.data.PerceptionInfo;
import dji.v5.manager.aircraft.perception.listener.PerceptionInformationListener;
import dji.v5.manager.interfaces.IPerceptionManager;
public class PerceptionManager extends BaseManager {
private PerceptionManager() {
}
private static class PerceptionManagerHolder {
private static final PerceptionManager INSTANCE = new PerceptionManager();
}
public static PerceptionManager getInstance() {
return PerceptionManagerHolder.INSTANCE;
}
private int closePerceptionTimes;
private boolean closePerceptionSuccess;
public void init(){
IPerceptionManager perceptionManager = dji.v5.manager.aircraft.perception.PerceptionManager.getInstance();
perceptionManager.addPerceptionInformationListener(new PerceptionInformationListener() {
@Override
public void onUpdate(@NonNull PerceptionInfo information) {
if(information!=null){
if (Boolean.TRUE.equals(information.getDownwardObstacleAvoidanceWorking())){
setObstacleAvoidancedownEnabled();
LogUtil.log(TAG,"监听然后关闭下避障");
}
}
}
});
}
public void setPerceptionEnable(boolean perceptionEnable) {
if (PreferenceUtils.getInstance().getCloseObsEnable() && perceptionEnable) {
LogUtil.log(TAG, "全局避障关闭,不开启避障");
return;
}
Boolean isConnect = KeyManager.getInstance().getValue(createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IPerceptionManager perceptionManager = dji.v5.manager.aircraft.perception.PerceptionManager.getInstance();
perceptionManager.setObstacleAvoidanceType(perceptionEnable ? ObstacleAvoidanceType.BRAKE : ObstacleAvoidanceType.CLOSE, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
if (perceptionEnable) {
LogUtil.log(TAG, "避障开启");
} else {
closePerceptionSuccess = true;
LogUtil.log(TAG, "避障关闭");
}
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
if (perceptionEnable) {
LogUtil.log(TAG, "避障开启失败:" + new Gson().toJson(idjiError));
} else {
LogUtil.log(TAG, "" + closePerceptionTimes + "次关闭避障失败:" + new Gson().toJson(idjiError));
if (!closePerceptionSuccess) {
if (closePerceptionTimes <= 5) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
closePerceptionTimes++;
setPerceptionEnable(false);
}
}, 2000);
} else {
LogUtil.log(TAG, "避障关闭" + closePerceptionTimes + "次失败");
}
}
}
}
});
}
}
public void setObstacleAvoidancedownEnabled(){
Boolean isConnect = KeyManager.getInstance().getValue(createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IPerceptionManager perceptionManager = dji.v5.manager.aircraft.perception.PerceptionManager.getInstance();
perceptionManager.setObstacleAvoidanceEnabled(false, PerceptionDirection.DOWNWARD, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "关闭下避障");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "关闭下避障:"+new Gson().toJson(idjiError));
}
});
}
}
//开启水平避障
public void setObstacleAvoidanceHorizontalEnabled() {
if (PreferenceUtils.getInstance().getCloseObsEnable()) {
LogUtil.log(TAG, "全局避障关闭,不开启避障");
return;
}
Boolean isConnect = KeyManager.getInstance().getValue(createKey(FlightControllerKey.KeyConnection));
if (isConnect != null && isConnect) {
IPerceptionManager perceptionManager = dji.v5.manager.aircraft.perception.PerceptionManager.getInstance();
perceptionManager.setObstacleAvoidanceEnabled(true, PerceptionDirection.HORIZONTAL, new CommonCallbacks.CompletionCallback() {
@Override
public void onSuccess() {
LogUtil.log(TAG, "开启水平避障");
}
@Override
public void onFailure(@NonNull IDJIError idjiError) {
LogUtil.log(TAG, "开启水平避障:"+new Gson().toJson(idjiError));
}
});
}
}
}

Some files were not shown because too many files have changed in this diff Show More