2017-09-07 5 views
0

無人機から自分のアプリケーションに直接画像をダウンロードする際に問題が発生しました。 「システムがビジー状態です。後で再試行してください。(コード:-1004)」画像をダウンロードしようとすると、DJIフォーラムやその他の質問がstackoverflowでチェックされていますが見つかりませんでしたこの問題に対する任意の解決策。IOS DJI-SDKを使用して無人機から画像をプログラムでダウンロードする方法

私は既にthis questionを見てきましたが、私はすでにその答えから提案されているテクニックを使用しています。ここで

は、私が画像をダウンロードするために書いた関数である:私のドローンをテストするとき

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 

} 

そして、ここでは、この関数の出力です:

*** 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 
+0

完全版の機能版をアップロードできますか? – IanTimmis

+0

@IanTimmis私が使用したソリューションで質問を更新しました。ちなみに、ファンクションが最初のコールでカメラを検出しない場合、カメラが検出される前に複数のコールを試す必要があります。 –

答えて

1

あなたはここでは2つの問題を持っています。まず、すべてのデータが1回の呼び出しで処理されると仮定しているため、あなたのupdateBlockは不十分です。 fetchDataのドキュメントをもっと慎重に見てください。

updateBlockの定義に注意してください。「ファイルデータを受信するブロック。複数回呼び出され、毎回最後の呼び出し以降に受信したデータが返されます。

は、だからあなたupdateBlockはこのような何かをする必要があります。

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

第二の問題は、あなたが同時にすべてのファイルの非同期ダウンロードを要求していることです。一度に1つのファイルのみをダウンロードし、前のファイルが完了した後で次のファイルを開始する必要があります。例:

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

    // then, initiate next download 
    downloadFilesFromDrone() 
} 
+0

物事を明確にしてくれてありがとう!私の2番目の問題に関しては、一度に1つのイメージしかダウンロードできないようにするにはどうすればいいですか?私はまずDispatchQueueブロックの外でfetchData()関数を使用する必要があると理解していますが、そこからどこに行くべきかはわかりません(fetchData()関数は非同期関数のように見えます) –

+0

@NathanOrtega最も簡単なのは、おそらくダウンロードファイルが完成したときにupdateBlockから次のダウンロードを開始することでしょう。 – biomiker

+0

@ NathanOrtegaあなたはこれを考え出したかもしれませんが、downloadFilesFromDrone()を何度も呼び出してはいけません。そのコードのほとんどを、initDownload()という別のメソッドに移動する必要があります。これは、すべての設定を行うために一度だけ呼び出されます。その後、downloadFilesFromDroneを複数回呼び出す必要があります。リストの次のファイルでfetchData()を呼び出します。 – biomiker

関連する問題