v5.x版本的功能與v4.x基本相同,都是獲取飛機的姿態信息、獲取無人機多媒體文件、操作多媒體文件、航線規劃等。不過在上一章節中也大致說了一些兩個版本的中API的差別,下面是根據一些API使用所完成的一些功能,因為項目原因只能提供部分代碼供參考,后續如果有這方面需求的小伙伴可以對其進行開發指導。
1
1、KeyManager調用
KeyManager類提供了一組方法來訪問硬件模塊的參數和控制硬件模塊的行為,包括DJIKey的Value設置,Value獲取,Value監聽和Action執行。通過KeyTools類提供的createKey方法可以更加方便的創建DJIKey實例。
下圖展示了使用KeyManager的接口判斷飛控正常連接并且GPS信號等級大于等于2級,然后給飛行器設置返航點,最后執行返航操作的調用流程。
此處是示例的操作方式,后面有在項目中使用的過程。
2、示例
//獲取飛機信息、云臺信息
????private?void?get3DLocation()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyAircraftLocation3D),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?LocationCoordinate3D?oldValue,?@Nullable?LocationCoordinate3D?newValue)?{
????????????????if?(newValue!=null){
????????????????????lat?=?newValue.latitude;
????????????????????lon?=?newValue.longitude;
????????????????????high?=?newValue.altitude;
????????????????}
????????????}
????????});
????}
????private?void?getAttitude()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyAircraftAttitude),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Attitude?oldValue,?@Nullable?Attitude?newValue)?{
????????????????if?(newValue!=null){
????????????????????pitch?=?newValue.pitch;
????????????????????roll?=?newValue.roll;
????????????????????yaw?=?newValue.yaw;
????????????????}
????????????}
????????});
????}
????private?void?getVelocity()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyAircraftVelocity),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Velocity3D?oldValue,?@Nullable?Velocity3D?newValue)?{
????????????????if?(newValue!=null){
????????????????????velocity_X?=?newValue.x;
????????????????????velocity_Y?=?newValue.y;
????????????????????velocity_Z?=?newValue.z;
????????????????}
????????????}
????????});
????}
????private?void?getIsFly(){
????????KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyIsFlying),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Boolean?oldValue,?@Nullable?Boolean?newValue)?{
????????????????if?(newValue!=null){
????????????????????isFlying?=?newValue;
????????????????}
????????????}
????????});
????}
????private?void?getGimbalAttitude()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(GimbalKey.KeyGimbalAttitude),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Attitude?oldValue,?@Nullable?Attitude?newValue)?{
????????????????if?(newValue!=null){
????????????????????g_pitch?=?newValue.pitch;
????????????????????g_roll?=?newValue.roll;
????????????????????g_yaw?=?newValue.yaw;
????????????????}
????????????}
????????});
????}
????private?void?getPower()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.KeyChargeRemainingInPercent),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Integer?oldValue,?@Nullable?Integer?newValue)?{
????????????????power?=?newValue;
????????????}
????????});
????}
????private?void?getTemperature()?{
????????KeyManager.getInstance().listen(KeyTools.createKey(BatteryKey.KeyBatteryTemperature),?this,?new?CommonCallbacks.KeyListener()?{
????????????@Override
????????????public?void?onValueChange(@Nullable?Double?oldValue,?@Nullable?Double?newValue)?{
????????????????temperature?=?newValue;
????????????}
????????});
????}
onValueChange()方法為1秒執行10次,這個可以根據后續要求進行獲取;
2
1、Sample介紹
拍照、錄像是無人機的重要功能,對拍攝的照片、視頻等多媒體文件進行管理也就必不可少。多媒體文件的管理包括訪問飛機存儲空間內的多媒體文件資源、獲取多媒體文件列表與列表狀態、視頻文件播放等。
下圖為完整的接口展示以及接口調用流程示例。
多媒體文件管理調用流程
視頻文件播放調用流程

2、示例
private?void?getFileList(int?index)?{
????????if?(MediaManager.getInstance()?!=?null)?{
//????????????if?(mMediaFileListState?==?MediaFileListState.UPDATING)?{
//????????????????DJILog.e(TAG,?"媒體管理器正忙.");
//????????????}?else?if?(mMediaFileListState?==?MediaFileListState.IDLE){
????????????????MediaManager.getInstance().pullMediaFileListFromCamera((new?PullMediaFileListParam.Builder()).build(),?new?CommonCallbacks.CompletionCallback()?{
????????????????????@Override
????????????????????public?void?onSuccess()?{
????????????????????????hideProgressDialog();
????????????????????????if?(mMediaFileListState?!=?MediaFileListState.UP_TO_DATE)?{
//????????????????????????????List.clear();
????????????????????????????mediaFileList.clear();
????????????????????????????lastClickViewIndex?=?-1;
????????????????????????}
????????????????????????List?=???MediaManager.getInstance().getMediaFileListData().getData();
????????????????????????switch?(index)?{
????????????????????????????case?0:
????????????????????????????????for?(int?i?=?0;?i?????????????????????????????????????mediaFileList.add(List.get(i));
????????????????????????????????}
????????????????????????????????break;
????????????????????????????case?1:
????????????????????????????????for?(int?i?=?0;?i?????????????????????????????????????if?(List.get(i).getFileType()==?MediaFileType.JPEG)?{
????????????????????????????????????????mediaFileList.add(List.get(i));
????????????????????????????????????????MyLog.d("圖片名稱:"+List.get(i).getFileName());
????????????????????????????????????}
????????????????????????????????}
????????????????????????????????break;
????????????????????????????case?2:
????????????????????????????????for?(int?i?=?0;?i?????????????????????????????????????if?((List.get(i).getFileType()?==?MediaFileType.MOV)?||?(List.get(i).getFileType()?==?MediaFileType.MP4))?{
????????????????????????????????????????mediaFileList.add(List.get(i));
????????????????????????????????????????MyLog.d("視頻名稱:"+List.get(i).getFileName());
????????????????????????????????????}
????????????????????????????????}
????????????????????????????????break;
????????????????????????}
????????????????????????if?(mediaFileList?!=?null)?{
????????????????????????????Collections.sort(mediaFileList,?(lhs,?rhs)?->?{
????????????????????????????????if?(getDate(lhs.getDate())?????????????????????????????????????return?1;
????????????????????????????????}?else?if?(getDate(lhs.getDate())?>?getDate(rhs.getDate()))?{
????????????????????????????????????return?-1;
????????????????????????????????}
????????????????????????????????return?0;
????????????????????????????});
????????????????????????}
????????????????????????runOnUiThread(new?Runnable()?{
????????????????????????????@Override
????????????????????????????public?void?run()?{
????????????????????????????????mListAdapter.notifyDataSetChanged();
????????????????????????????}
????????????????????????});
????????????????????????//????????????????????????scheduler.resume(error?->?{
????????????????????????//????????????????????????????if?(error?==?null)?{
????????????????????????//
????????????????????????//????????????????????????????}
????????????????????????//????????????????????????});
????????????????????????getThumbnails();
????????????????????}
????????????????????@Override
????????????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????????????????hideProgressDialog();
????????????????????????showToasts("獲取媒體文件列表失敗:"?+?error.description());
????????????????????}
????????????????});
//????????????}
????????}
????}
????private?void?getThumbnails()?{
????????if?(mediaFileList.size()?<=?0)?{
????????????showToasts("沒有用于下載縮略圖的文件信息");
????????????return;
????????}
????????for?(int?i?=?0;?i?????????????getThumbnailByIndex(i);
????????}
????}
????private?void?getThumbnailByIndex(final?int?index)?{
????????mediaFileList.get(index).pullThumbnailFromCamera(new?CommonCallbacks.CompletionCallbackWithParam()?{
????????????@Override
????????????public?void?onSuccess(Bitmap?bitmap)?{
????????????}
????????????@Override
????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????}
????????});
????}
?????private?void?deleteFileByIndex(final?int?index)?{
????????ArrayList?fileToDelete?=?new?ArrayList();
????????if?(mediaFileList.size()?>?index)?{
????????????fileToDelete.add(mediaFileList.get(index));
????????????MediaManager.getInstance().deleteMediaFiles(fileToDelete,?new?CommonCallbacks.CompletionCallback()?{
????????????????@Override
????????????????public?void?onSuccess()?{
????????????????????mediaFileList.remove(index);
????????????????????//Reset?select?view
????????????????????lastClickViewIndex?=?-1;
????????????????????lastClickView?=?null;
????????????????????//Update?recyclerView
????????????????????mListAdapter.notifyDataSetChanged();
????????????????}
????????????????@Override
????????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????????????showToasts("刪除失敗");
????????????????}
????????????});
????????}
????}
????private?void?downloadFileByIndex(final?int?index)?{
????????if?((mediaFileList.get(index).getFileType()?==?MediaFileType.MOV)?||?(mediaFileList.get(index).getFileType()?==?MediaFileType.MP4))?{
????????????SavePath?=?MyStatic.FLY_FILE_VIDEO;
????????}?else?if?(mediaFileList.get(index).getFileType()?==?MediaFileType.JPEG)?{
????????????SavePath?=?MyStatic.FLY_FILE_PHOTO;
????????}
????????File?destDir?=?new?File(FileUtil.checkDirPath(SavePath));
????????String?path?=?SavePath?+?"/"?+?mediaFileList.get(index).getFileName();
????????File?destPath?=?new?File(path);
????????try?{
????????????outputStream?=?new?FileOutputStream(destPath);
????????}?catch?(FileNotFoundException?e)?{
????????????e.printStackTrace();
????????}
????????bos?=?new?BufferedOutputStream(outputStream);
????????mediaFileList.get(index).pullOriginalMediaFileFromCamera(0,?new?MediaFileDownloadListener()?{
????????????@Override
????????????public?void?onStart()?{
????????????????currentProgress?=?-1;
????????????????ShowDownloadProgressDialog();
????????????}
????????????@Override
????????????public?void?onProgress(long?total,?long?current)?{
????????????????int?tmpProgress?=?(int)?(1.0?*?current?/?total?*?100);
????????????????if?(tmpProgress?!=?currentProgress)?{
????????????????????mDownloadDialog.setProgress(tmpProgress);
????????????????????currentProgress?=?tmpProgress;
????????????????}
????????????}
????????????@Override
????????????public?void?onRealtimeDataUpdate(byte[]?data,?long?position)?{
????????????????try?{
????????????????????bos.write(data,?0,?data.length);
????????????????????bos.flush();
????????????????}?catch?(IOException?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????}
????????????@Override
????????????public?void?onFinish()?{
????????????????HideDownloadProgressDialog();
????????????????currentProgress?=?-1;
????????????????try?{
????????????????????outputStream.close();
????????????????????bos.close();
????????????????}?catch?(Exception?e)?{
????????????????????e.printStackTrace();
????????????????}
????????????}
????????????@Override
????????????public?void?onFailure(IDJIError?error)?{
????????????}
????????});
????}
?private?void?playVideo()?{
????????mImageView.setVisibility(View.INVISIBLE);
????????MediaFile?selectedMediaFile?=?mediaFileList.get(lastClickViewIndex);
????????if?((selectedMediaFile.getFileType()?==?MediaFileType.MOV)?||?(selectedMediaFile.getFileType()?==?MediaFileType.MP4))?{
????????????MediaManager.getInstance().playVideo(selectedMediaFile,?new?CommonCallbacks.CompletionCallbackWithParam()?{
????????????????@Override
????????????????public?void?onSuccess(IVideoFrame?iVideoFrame)?{
????????????????????videoDecoder.queueInFrame(iVideoFrame);
????????????????????DJILog.e(TAG,?"播放成功");
????????????????????runOnUiThread(new?Runnable()?{
????????????????????????@Override
????????????????????????public?void?run()?{
????????????????????????????mImageViewVideoPlay.setEnabled(false);
????????????????????????????mImageViewVideoPause.setEnabled(true);
????????????????????????}
????????????????????});
????????????????}
????????????????@Override
????????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????????????showToasts("播放失敗?"?+?error.description());
????????????????}
????????????});
????????}
????}
3
1、Sample介紹
直播功能是Mobile SDK重要的功能,可支持聲網、RTMP、RTSP、GB28181 四種直播模式。在安防,公共安全,巡檢等場景都需要有直播模塊。
下圖為完整的接口展示以及接口調用流程示例。詳細的使用方法請查看Mobile SDK API 文檔中的直播管理類 ILiveStreamManager。直播管理類用于直播的參數設置和直播的開啟和停止等功能。

2、示例
項目中使用到了其中的一種方式 ,使用RTMP方式進行推流直播。代碼如下:
private?void?startLiveShow()?{
????????LiveStreamSettings.Builder?settings?=?new?LiveStreamSettings.Builder();
????????settings.setLiveStreamType(LiveStreamType.RTMP);
????????RtmpSettings.Builder?rtmpSetting?=?new?RtmpSettings.Builder();
????????rtmpSetting.setUrl(liveShowUrl);
????????settings.setRtmpSettings(rtmpSetting.build());
????????MediaDataCenter.getInstance().getLiveStreamManager().setLiveStreamSettings(settings.build());
????????MediaDataCenter.getInstance().getLiveStreamManager().startStream(new?CommonCallbacks.CompletionCallback()?{
????????????@Override
????????????public?void?onSuccess()?{
????????????????Log.i("LiveStreamManager","LiveStreamManager開始直播");
????????????????boolean?isStream?=??MediaDataCenter.getInstance().getLiveStreamManager().isStreaming();
????????????????Log.i("LiveStreamManager","LiveStreamManager開始直播:"+isStream);
????????????????Log.i("LiveStreamManager","LiveStreamManager直播參數:"+MediaDataCenter.getInstance().getLiveStreamManager().getLiveStreamSettings());
????????????????Log.i("LiveStreamManager","LiveStreamManager視頻質量:"+MediaDataCenter.getInstance().getLiveStreamManager().getLiveStreamQuality());
????????????????Log.i("LiveStreamManager","LiveStreamManager直播碼率:"+MediaDataCenter.getInstance().getLiveStreamManager().getLiveVideoBitrate());
????????????????Log.i("LiveStreamManager","LiveStreamManager碼流通道:"+MediaDataCenter.getInstance().getLiveStreamManager().getVideoChannelType());
????????????????Log.i("LiveStreamManager","LiveStreamManager碼率模式:"+MediaDataCenter.getInstance().getLiveStreamManager().getLiveVideoBitrateMode());
????????????}
????????????@Override
????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????????Log.i("LiveStreamManager"?,"LiveStreamManager直播錯誤:"?+?error.description());
????????????}
????????});
????}
????private?void?stopLiveShow()?{
????????AlertDialog.Builder?Builder?=?new?AlertDialog.Builder(MainActivity.this);
????????Builder.setTitle("提示");
????????Builder.setMessage("是否結束推流?");
????????Builder.setIcon(android.R.drawable.ic_dialog_alert);
????????Builder.setPositiveButton("確定",?new?DialogInterface.OnClickListener()?{
????????????@Override
????????????public?void?onClick(DialogInterface?dialog,?int?which)?{
????????????????if?(!isLiveStreamManagerOn())?{
????????????????????return;
????????????????}
????????????????LiveStreamManager.getInstance().stopStream(new?CommonCallbacks.CompletionCallback()?{
????????????????????@Override
????????????????????public?void?onSuccess()?{
????????????????????????runOnUiThread(new?Runnable()?{
????????????????????????????@Override
????????????????????????????public?void?run()?{
????????????????????????????????//????????????????????????LiveModule?module?=?new?LiveModule("liveStreamStateChanged","plane",planeId,false,trajectoryId+"");
????????????????????????????????mapData.put("type",?"liveStreamStateChanged");
????????????????????????????????mapData.put("sender",?"plane");
????????????????????????????????mapData.put("planeId",?planeId?+?"");
????????????????????????????????mapData.put("liveStreamOpen",?"false");
????????????????????????????????mapData.put("liveStreamUrl",?trajectoryId?+?"");
????????????????????????????????params.put("message",?GsonUtil.GsonString(mapData));
????????????????????????????????http.getHttp(POST_LIVE_STATE,?"GET",?params);
????????????????????????????}
????????????????????????});
????????????????????????showToast("結束推流");
????????????????????}
????????????????????@Override
????????????????????public?void?onFailure(@NonNull?IDJIError?error)?{
????????????????????}
????????????????});
????????????}
????????});
????????Builder.setNegativeButton("取消",?null);
????????Builder.show();
????}
4
1、Sample介紹
航線任務管理是用于無人機自主作業的重要功能,通過MSDK提供的接口可以實現對航線任務的上傳、執行、暫停、恢復以及對航線任務執行狀態與航線信息的監聽等。
我們將航點任務定義在航線文件中,該文件遵循 DJI 自定義的航線文件格式標準(WPML)。航線文件實際為“.kmz”結尾的壓縮文件,文件結構如下:
waypoints_name.kmz
└──?wpmz
??├──?res
??├──?template.kml
??└──?waylines.wpml
其中,template.kml文件為“模板文件”,waylines.wpml文件為“執行文件”,res為資源文件。詳細的介紹請閱讀航線文件格式標準。航線文件格式標準的文檔中有對template.kml文件與waylines.wpml文件的編寫說明。
2、接口調用流程
MSDK提供的航線功能相關接口較為簡單,調用方式如下圖。詳細的使用方法請查看Mobile SDK API文檔中的航線任務管理類 IWaypointMissionManager。圖中虛線框內容為可選接口。
5
以上內容為v5.x版本中使用到的一些內容,當然還有一些API沒有在項目中使用到,后續給大家也更新到整個專欄內容中,希望喜歡的小伙伴可以進行訂閱,如果后續有共同開發的同道中人可以聯系我幫你解決一些問題?,F階段v5.x還在持續更新中,為了適配更多的飛機它的一些功能也是在不斷的完善。
往期推薦LabVIEW圖像特征與機器視覺概念(理論篇—4)
如何使用ESD二極管,設計運算放大器電壓保護?
LabVIEW易拉罐外型合格檢測
二維碼掃碼登錄是什么原理?
單片機如何高效使用平均值采樣法提高數據準確性?
DS18B20溫度傳感器的特性、原理、驅動(華大半導體HC32L136、ESP32驅動)
