【Swift】TelloとUDP通信③ - UDPServerを立てて通信を行う-

#概要

[前回](https://qiita.com/eito_2/items/7ab3156cd1ad7b22679c)まではTelloにコマンドを送っていましたが、
今回は 、端末側でUSPServerをたて、Telloのステータス情報とカメラ情報を取得していきます。

ステータス情報とカメラ情報は以下のように設定することで、情報を取得できるようになります。

ステータス情報
Tello IP: 192.168.10.1 PORT:8890　->> PC/Mac/Mobile UDP Server: 0.0.0.0 UDP PORT:8890

カメラ情報
Tello IP: 192.168.10.1 PORT:8889　->> PC/Mac/Mobile UDP Server: 0.0.0.0 UDP PORT:11111


```
private func startListener() {
     
     //UDPサーバーのポートを指定
     let listener = try! NWListener(using: .udp, on: 11111)
        
     listener.newConnectionHandler = {(newConnection) in
          self.receive(on: newConnection, text: "")
          newConnection.start(queue: DispatchQueue.global())
     }
        
     listener.stateUpdateHandler = { state in
                   
          switch state {
               case .ready:
                    //受信が可能な状態
                    //Telloからのデータを受信する
                    let connection = NWConnection(host: "192.168.10.1", port: 8889, using: NWParameters.udp)
                    self.receive(on: connection, text: "")
                    connection.start(queue: DispatchQueue.global())
                    
               case .waiting(_):
                    ()
               case .failed(_):
                    ()
               case .setup:
                    ()
               case .cancelled:
                    ()
               @unknown default:
                    fatalError()
          }
     }

     //開始
     listener.start(queue: DispatchQueue.global())
}
    

```



#ステータス情報　Server: 0.0.0.0 UDP PORT:8890
PORT：8890のUDPサーバーを立てることでTelloのステータス情報を取得できます。
ステータス情報はまとまったデータで送られてきます。

```
//UDPサーバーのポートを指定
let listener = try! NWListener(using: .udp, on: 11111)

//Telloからのデータを受信する
let connection = NWConnection(host: "192.168.10.1", port: 8890, using: NWParameters.udp)
```
現在のTelloのステータス情報を取得してくれます。

```
pitch:%d;roll:%d;yaw:%d;vgx:%d;vgy%d;vgz:%d;templ:%d;temph:%d;tof:%d;h:%d;bat:%d;baro:%.2f; time:%d;agx:%.2f;agy:%.2f;agz:%.2f;
```


|ステータス  |説明  |
|---|---|
| pitch  |姿勢ピッチ  |
| roll | 態度ロール|
| yaw  | 姿勢ヨー  |
| vgx  | スピードx  |
| vgy  | スピードy  |
| vgz  | スピードz |
| templ | 最低気温 |
| temph | 最高気温 |
| tof | TOF距離(cm) |
| h | 高さ(cm) |
| bat | バッテリー(%) |
| baro | バロメーター測定(cm) |
| time | 飛行時間　|
| agx | 加速x |
| agy | 加速y |
| agz | 加速z |


#カメラ情報　Server: 0.0.0.0 UDP PORT:11111

PORT：11111のUDPサーバーからTelloのカメラ情報を取得できます。
ステータス情報とは違い、事前にstreamonコマンドの実行、TelloのPORT:8889でデータを受信させる必要があります。

```
//UDPサーバーのポートを指定
let listener = try! NWListener(using: .udp, on: 11111)

//Telloからのデータを受信する
let connection = NWConnection(host: "192.168.10.1", port: 8889, using: NWParameters.udp)
```



Telloのカメラ情報を取得する際には、H.264でエンコードされたデータが複数回に分けて送られるため、
一定のデータサイズになった時にデコード処理をしてカメラ情報を取得させる必要があります。

```
var currentImg: [UInt8] = []

let img_data = data
self.currentImg = self.currentImg + img_data!

//一定のサイズ以下のデータを受信した場合にデコードさせる
if img_data!.count < 1460 && self.currentImg.count > 40 {
     self.frameDecoder.interpretRawFrameData(&self.currentImg)
     self.currentImg = []
}
```

デコーダは、下記を参考にしました。
https://github.com/Kayakflo/TelloEdu-Swift-VideoStream

#参考
https://tellopilots.com

[TelloSDK](https://terra-1-g.djicdn.com/2d4dce68897a46b19fc717f3576b7c6a/Tello%20编程相关/For%20Tello/Tello%20SDK%20Documentation%20EN_1.3_1122.pdf)