本文介绍了如何使用IOS DJI-SDK以编程方式从无人机下载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一些问题,将无人机中的图像直接下载到应用程序中.尝试下载图像时,出现"系统繁忙,请稍后重试.(代码:-1004)"的错误信息.找不到解决此问题的任何方法.

I've been having some issues downloaded images from my drone directly to my application. I keep getting a "System is busy, please retry later.(code:-1004)" error message when attempting to download the image, I have checked the DJI forum and other questions here on stackoverflow and have not been able to find any solution to this problem.

我已经看过这个问题,但我已经在使用该答案中建议的技术.

I've already taken a look at this question, but i'm already using the technique suggested from that answer.

这是我编写的用于下载图像的功能:

Here is the function I've written to download the images:

func downloadFilesFromDrone(){

    // get current product
    guard let drone = DJISDKManager.product() else {
        Logger.logError("Product is connected but DJISDKManager.product is nil when attempting to download media")
        return
    }


    // Get camera on drone
    guard  let camera: DJICamera = drone.camera else {
        Logger.logError("Unable to detect Camera in downloadFilesFromDrone()")
        // make recursive call until we are able to detect the camera
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            Logger.logH1("Trying to detect Camera again")
            self.downloadFilesFromDrone()
        }
        return
    }

    Logger.logH1("Successfully detected the camera")

    // check if we can download images with the product
     if !camera.isMediaDownloadModeSupported() {
        Logger.logError("Product does not support media download mode")
        return
    }


    // switch camera mode to allow for media downloads
    camera.setMode( .mediaDownload, withCompletion: {(error) in
        if error != nil {
            print("\(error!.localizedDescription)")
        }
        else {

            // get the media manager from the drone to gain access to the files
            let manager = camera.mediaManager!
            manager.refreshFileList(completion: { (error) in

                if error != nil {
                    print("State: \(manager.fileListState.rawValue)")
                    print("Error refreshing list: \(error!.localizedDescription)")
                }
                else {
                    Logger.logH1("Refreshed file list")
                    print("State: \(manager.fileListState.rawValue)")


                    guard let files = manager.fileListSnapshot() else {
                        Logger.logError("No files to download")
                        return
                    }

                    Logger.logH1("There are files to download")

                    var images: [UIImage] = []

                    for file in files {

                        if file.mediaType == .JPEG {

                            print("Time created: \(file.timeCreated)")

                            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {

                                file.fetchData(withOffset: 0, update: DispatchQueue.main, update: {(_ data: Data?, _ isComplete: Bool, _ error: Error?) -> Void in

                                    if error != nil {
                                        print("State: \(manager.fileListState.rawValue)")
                                        print("Error downloading photo: \(error!)")
                                    }
                                    else {
                                        // unwrap downloaded data and create image
                                        if let data = data, let downloadedImage = UIImage(data: data) {
                                            print("Image was downloaded!")
                                            images.append( downloadedImage )
                                        }
                                    }

                                }) // end of filedata fetch

                            }

                        }

                    } // end of loop


                }
            }) // end of file-refresh block

        }

    })// end of camera setMode block

}

这是在用无人机测试时此功能的输出:

And here is the output of this function when testing with my drone:

*** Product Connected ***
*** Unable to detect Camera in downloadFilesFromDrone() ***
*** Firmware package version is: Unknown ***
--> Trying to detect Camera again
--> Successfully detected the camera
--> Refreshed file list
State: 0
--> There are files to download
Time created: 2017-09-01 15:17:04
Time created: 2017-09-01 15:17:16
Time created: 2017-09-01 15:17:26
Time created: 2017-09-01 15:17:36
Time created: 2017-09-01 15:19:06
State: 0
Error downloading photo: System is busy, please retry later.(code:-1004)
State: 0
Error downloading photo: System is busy, please retry later.(code:-1004)
State: 0
Error downloading photo: System is busy, please retry later.(code:-1004)
State: 0
Error downloading photo: System is busy, please retry later.(code:-1004)

下面是我用来从无人机下载图像的代码.

/**
 * This function downloads the N latest images from the drone and passes them to the completionhandler once all images have completed downloading
 */
func downloadImages( files: [DJIMediaFile], howMany: Int, maxErrors: Int, completion: @escaping ([UIImage]) -> Void){

    Logger.logH1("Queueing \(howMany) image(s) to be downloaded")

    func downloadNextImage( files: [DJIMediaFile], fileCount: Int, index: Int = 0, downloadedFiles: [UIImage] = [], errorCount: Int = 0) {

        // stop when we reach the end of the list
        if index == fileCount {
            completion(downloadedFiles)
            return
        }
        else {
            var imageData: Data?
            let file = files[index]

            file.fetchData(withOffset: 0, update: DispatchQueue.main, update: {(_ data: Data?, _ isComplete: Bool, _ error: Error?) -> Void in

                if let error = error {
                    Logger.logError("\(error)")

                    if errorCount < maxErrors {
                        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                            Logger.logH1("Attempting to download: \(file.fileName) again")
                            downloadNextImage(files: files, fileCount: fileCount, index: index, downloadedFiles: downloadedFiles, errorCount: errorCount + 1)
                        }

                    }
                    else {
                        Logger.logError("Too many errors downloading the images, try downloading again")
                    }


                }
                else {
                    // if image is done downloading
                    if isComplete {

                        // get full image data
                        if let imageData = imageData, let image = UIImage(data: imageData) {
                            Logger.logH1("Downloaded: \(file.fileName)")

                            // now that the image is done downloading, move onto the next image
                            downloadNextImage(files: files, fileCount: fileCount, index: (index + 1), downloadedFiles: downloadedFiles + [image], errorCount: 0)
                        }
                    }
                        // else, download the file
                    else {

                        // If image exists, append the data
                        if let _ = imageData, let data = data {
                            imageData?.append(data)
                        }
                            // initialize the image data
                        else {
                            imageData = data
                        }

                    }
                }


            }) // end of filedata fetch


        }   // end of else statement
    }

    // bounds checking
    let available = files.count
    let n = howMany > available ? available : howMany

    // grab the N latest images taken by the drone
    let filesToDownload : [DJIMediaFile] = Array ( files.suffix(n) )


    // start the recursive function
    downloadNextImage(files: filesToDownload, fileCount: filesToDownload.count)
}

这是怎么称呼它:

  // get current product
    guard let drone = DJISDKManager.product() else {
        Logger.logError("Product is connected but DJISDKManager.product is nil when attempting to download media")
        return
    }


    // Get camera on drone
    guard  let camera: DJICamera = drone.camera else {
        Logger.logError("Unable to detect Camera in initDownload()")
        return
    }

    Logger.logH1("Successfully detected the camera")

    // check if we can download images with the product
    if !camera.isMediaDownloadModeSupported() {
        Logger.logError("Product does not support media download mode")
        return
    }

    // switch camera mode to allow for media downloads
    camera.setMode( .mediaDownload, withCompletion: {(error) in
        if error != nil {
            print("\(error!.localizedDescription)")
        }
        else {

            // get the media manager from the drone to gain access to the files
            let manager = camera.mediaManager!
            manager.refreshFileList(completion: { (error) in

                if error != nil {
                    print("State: \(manager.fileListState.rawValue)")
                    print("Error refreshing list: \(error!.localizedDescription)")
                }
                else {
                    Logger.logH1("Refreshed file list")
                    print("State: \(manager.fileListState.rawValue)")

                    // get list of files
                    guard let files = manager.fileListSnapshot() else {
                        Logger.logError("No files to download")
                        return
                    }

                    Logger.logH1("There are files to download.. Beginning Download")
                    self.downloadImages(files: files, howMany: waypoints, maxErrors: 4, completion: { images in
                        Logger.logH1("Finished downloading: \(images.count) image(s)")
                        // do something with the images here
                    })



                }
            }) // end of file-refresh block

        }

    })// end of camera setMode block

推荐答案

您在这里遇到了两个问题.首先,您的updateBlock不足,因为它假设所有数据都将在一个调用中出现.请更仔细地查看 fetchData 的文档 a>()

You've got two problems here. Firstly, your updateBlock is inadequate because it's assuming that all the data will come in a single call. Look more carefully at the documentation for fetchData()

请注意updateBlock的定义:阻止接收文件数据.将被多次调用,每次将返回自上次调用以来接收到的数据."

Note the definition of updateBlock: "Block to receive file data. It will be called multiple times and each time will return the data received since the last call."

因此,您的updateBlock需要执行以下操作:

So your updateBlock needs to do something like this:

imageData.append(data)
if isComplete {
    image = UIImage(data: imageData)
    // handle image as desired
}

第二个问题是您正在同时请求所有文件的异步下载.您一次只需要下载一个文件,并且仅在上一个文件完成后才开始下一个文件.例如:

The second problem is that you are requesting the asynchronous download of all the files simultaneously. You need to download only one file at a time, and only start the next one after the previous one is complete. For example:

imageData.append(data)
if isComplete {
    image = UIImage(data: imageData)
    // handle image as desired

    // then, initiate next download
    downloadFilesFromDrone()
}

这篇关于如何使用IOS DJI-SDK以编程方式从无人机下载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!