2017-09-07 6 views
0

무인 항공기에서 내 응용 프로그램으로 직접 이미지를 다운로드하는 데 문제가 발생했습니다. 이미지를 다운로드 할 때 "시스템이 사용 중입니다. 잠시 후 다시 시도하십시오. (코드 : -1004)"오류 메시지가 나타나며 DJI 포럼 및 기타 질문을 stackoverflow에서 확인하고 찾을 수 없습니다. 이 문제에 대한 해결책.IOS DJI-SDK를 사용하여 무인 항공기에서 이미지를 프로그래밍 방식으로 다운로드하는 방법

나는 이미 this question을 살펴 봤지만 이미 그 대답에서 제안 된 기술을 사용하고 있습니다.

*** 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) 

편집 :

내 무인 항공기와이 함수의 출력을 테스트하고 여기

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 

} 

그리고 다음은

내가 이미지를 다운로드하기 위해 작성한 기능입니다

다음은 무인기에서 이미지를 다운로드하는 데 사용 된 코드입니다. 여기

/** 
* 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

. 첫째, updateBlock은 모든 데이터가 단일 호출로 전달되기 때문에 부적절합니다. fetchData()에 대한 설명서를 더 자세히 살펴보십시오.

updateBlock의 정의에 유의하십시오. "파일 데이터 수신 차단. 여러 번 호출되며 매번 마지막 호출 이후에 수신 된 데이터가 반환됩니다."

그래서 당신 updateBlock은 같은 것을 할 필요가있다 :

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

두 번째 문제는 동시에 모든 파일의 비동기 다운로드를 요청하는 것입니다. 한 번에 하나의 파일 만 다운로드해야하며 이전 파일이 완료된 후에 다음 파일 만 시작해야합니다. 예 :

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

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

문제를 명확히 해 주셔서 감사합니다! 내 두 번째 문제와 관련하여 한 번에 하나의 이미지 만 다운로드하도록하려면 어떻게해야합니까? 먼저 DispatchQueue 블록 외부에서 fetchData() 함수를 사용할 필요가 있다는 것을 이해하지만 fetchData() 함수가 비동기 함수처럼 보일 때 어디로 가야할지 모르겠습니다. –

+0

@NathanOrtega 예제를 업데이트했습니다. 가장 쉬운 방법은 다운로드 파일이 완료되면 updateBlock에서 다음 다운로드를 시작하는 것입니다. – biomiker

+0

@ NathanOrtega 당신은 아마 이것을 알아 냈을 것입니다. 그러나 downloadFilesFromDrone()를 여러 번 호출해서는 안됩니다. 대부분의 코드를 initDownload()라는 다른 메서드로 옮겨야합니다.이 메서드는 모든 설정을 수행하는 데 한 번만 호출됩니다. 그런 다음 downloadFilesFromDrone을 여러 번 호출하여 목록의 다음 파일에서 fetchData()를 호출해야합니다. – biomiker