Telloプログラミング：data, server = sock.recvfrom(1518)のdataの中身を覗いてみた


Telloプログラミングの中で、TelloとMacbookとの通信経路を確立する部分の定番コードは、次のようなものです。

```python3:
data, server = sock.recvfrom(1518)
```

ここで、返り値を受け止める__*data*__変数に、どのような値が入るのか、興味を持ちました。
この変数の中身を、Terminalに出力して確認してみました。

__[前回の記事](https://qiita.com/electronics_diy721/items/df5235c692a84867cd60)__を改良してみました。ソースコードの全体は、この記事の最後に掲載してあります。

###コード改編部分

>以下を追加（2021/7/28)
>dataはバイト列（例：b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
>received_data = data.decode('utf-8')
>print("Telloからの返り値：　" + received_data)

```python3:コード該当箇所１
def recv():
    count = 0
    while True: 
        try:
            data, server = sock.recvfrom(1518)
            #以下を追加（2021/7/28)
            #dataはバイト列（例：b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
            received_data = data.decode('utf-8')
            print("Telloからの返り値：　" + received_data)
        except Exception:
            print ('\nExit . . .\n')
            break

#recvThread create
recvThread = threading.Thread(target=recv)
recvThread.start()
```

以下の２つが入り乱れてTerminalに表示されないように、time.sleep(1)を間にはさむ。

- 操作コマンドの入力待ち受けプロンプト（の表示）
- 前の指令コマンドの返り値（の表示）


>前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
> time.sleep(2)

```python3:コード該当箇所２
while True: 
    # 最初に入力が必要な"command"命令は、ユーザが打ち込まなくて良いようにスクリプト側でTelloに送出する
    msg = str("command").encode(encoding="utf-8") 
    sent = sock.sendto(msg, tello_address)
    # "takeoff"以降の命令をユーザ入力から受け取る
    try:
    # 前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
        time.sleep(2)
        msg = input("Telloに送る指示コマンドを入力してください。：  ")
        if not msg:
            break  

```



###検証画面と、その結果分かったこと

####__送出した操作コマンドと対応する返り値__

- Tello SDKで定義されている正しい操作コマンド：__「OK」という返り値__が戻される
- 未定義の操作コマンド （引数のみが未定義の場合を含む）： __「unknown command」という返り値__が戻される
- （同上） ：__「out of range」という返り値__が戻される

####__その他__

- __「error No valid imu」という返り値__が戻される

```bash:Terminal
electron@diynoMacBook-Pro Tello % python3 tello_python_rev2.py
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  takeoff
Telloからの返り値：　ok
kefTelloに送る指示コマンドを入力してください。：  t 50
Telloからの返り値：　unknown command: keft
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  Telloからの返り値：　ok
right 50
Telloからの返り値：　ok
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  up 100
Telloからの返り値：　ok
Telloからの返り値：　error No valid imu
Telloに送る指示コマンドを入力してください。：  up x
Telloからの返り値：　out of range
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  upp
Telloからの返り値：　unknown command: upp
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  upppppp
Telloからの返り値：　unknown command: upppppp
Telloからの返り値：　ok
Telloに送る指示コマンドを入力してください。：  ^C  
Exit . . .

electron@diynoMacBook-Pro Tello % 
```

###ソースコード全文


```python3:tello_python_rev2.py
import threading 
import socket
import sys
import time

host = ''
port = 9000
locaddr = (host, port) 

# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tello_address = ('192.168.10.1', 8889)

sock.bind(locaddr)

def recv():
    count = 0
    while True: 
        try:
            data, server = sock.recvfrom(1518)
            #以下を追加（2021/7/28)
            #dataはバイト列（例：b'\x 16指数表記データ')だから、str型に変換するにはdecodeが必要
            received_data = data.decode('utf-8')
            print("Telloからの返り値：　" + received_data)
        except Exception:
            print ('\nExit . . .\n')
            break

#recvThread create
recvThread = threading.Thread(target=recv)
recvThread.start()

while True: 
    # 最初に入力が必要な"command"命令は、ユーザが打ち込まなくて良いようにスクリプト側でTelloに送出する
    msg = str("command").encode(encoding="utf-8") 
    sent = sock.sendto(msg, tello_address)
    # "takeoff"以降の命令をユーザ入力から受け取る
    try:
    # 前に入力したコマンドに対するTelloからの返り値をprint出力するrecv()メソッドの処理が終わるまで、2秒待機する
        time.sleep(2)
        msg = input("Telloに送る指示コマンドを入力してください。：  ")
        if not msg:
            break  
            
        # Send data
        # Tello SDK v2.0 https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf
        if msg == "land":
            order_command = "battery?"
            battery_volume = sock.sendto(order_command.encode(encoding="utf-8") , tello_address)
            order_command = "time?"
            flight_time = sock.sendto(order_command.encode(encoding="utf-8") , tello_address)            
            print("着陸します。")
            message = "累積飛行時間：　{0} \nバッテリ残量（%）：　{1}".format(str(flight_time), str(battery_volume))
            print(message)
            sock.close()  
            break
        elif msg == "battery?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("バッテリ残量（%）：　" + str(sent))
        elif msg == "speed?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("現在の速度：　" + str(sent))
        elif msg == "time?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("累積飛行時間：　" + str(sent))
        elif msg == "sdk?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("この機体のSDK Ver.：　" + str(sent))
        elif msg == "sn?":
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
            print("この機体のシリアル番号：　" + str(sent))
        else:
            msg = msg.encode(encoding="utf-8") 
            sent = sock.sendto(msg, tello_address)
         
    except KeyboardInterrupt:
        sock.close()  
        break

```