UMEHOSHI ITA TOP PAGE COMPUTER SHIEN LAB
Raspberry PI Zeroをスマフォの代わりに使って、PCやAndroidの 「umehoshiアプリ」で遠隔操作を可能とする作品
『
ABS樹脂ケース(蝶番式・中) 112−TS(P-00277)』
に穴などの加工をして、
それに、
Camera を付けた[Raspberry PI Zero WH]と[UMEHOSHI ITA ]をUSBで繋いだ構成を IoT機器対応モバイルバッテリー(5000mAh)と共に詰め込んでいます。
この組み立て過程をこのページで紹介しています。
モバイルバッテリーから[Raspberry PI Zero W]に電源が供給され、[Raspberry PI Zero WH]からUSB接続で[UMEHOSHI ITA]に供給される構成です。
([Raspberry PI Zero WH]と[UMEHOSHI ITA ]のUSB接続は通信も兼ねて、[Raspberry PI Zero W]から[UMEHOSHI ITA]を制御します)
そしてモータ用の電源は、下部に配置した単3×4の電池で[UMEHOSHI ITA]のDCジャックより供給しています。
(Raspberry 用のシャットダウン用スイッチも追加しました)
(下記画像のクリックでイメージが変わります。)
このClickでYoutube 紹介動画へ移動できます。
[Raspberry PI Zero WH]はこのページでセットアップをしたものを
使って組み立てています
このセットアップにより、[Raspberry PI Zero WH]をWifiで接続する方法は次の2通りです。
(両者ともSSHのクライアントを使って[Raspberry PI]を操作します。(「pi」のIDで[abc123]のパスワードで接続)
Are you sure you want to continue connecting (yes/no/[fingerprint])?でyesを入力します。
Host key verification failed.のエラーであれば「ssh-keygen -R IPアドレス」入力で、該当のIPアドレス情報を消して再接続します。)
(1)
[Raspberry PI]を192.168.0.1のアクセスポイントに接続して、
同一ネットワーク内のPCから[Raspberry PI]にSSHで接続する方法です。
PC側の端末で、[Raspberry PI]の「ssh pi@192.168.0.123」で接続してできます。
Wifi環境のアクセスポイントがない所ではできませんが、[Raspberry PI]でインターネットも使える設定が可能です。
(アクセスポイントに合わせて[Raspberry PI]のセットアップを変更してください。)
(2) [Raspberry PI]自身をWifiのアクセスポイントにする方法です。 操作するPCやAndroidでは、[Raspberry PI]のSSID:pizero、パスプレーズ:abcd1234のWifiアクセスポイントに接続します。 この場合に[Raspberry PI]へのアクセスは、「ssh pi@192.168.100.1」で接続します。
以上どちらかのWifiを介して次のような遠隔操作できる環境を作ります
[Raspberry PI]の自作TCPサーバで、次のよう基本的な動作ができるように作ります。
遠隔操作用の指示ファイル(.umhファイル)をTCPで受信
[Raspberry PI]は受信した.umhファイル内の(UME専用Hexコマンド)をUSBを介して[UMEHOSHI ITA]に送信して動作させます。
UME専用Hexコマンドを受信してその処理を行った[UMEHOSHI ITA]は、その応答メッセージをUSBを介して[Raspberry PI]に送信します。
[Raspberry PI]側でTCPサーバでは、USBを介して受信した応答メッセージをTCPクライアントに送信します。
つまり自作TCPサーバは、umehoshiアプリのサーバ側の処理に近い機能を盛り込んだものと言えます。
また、自作TCPサーバでは、[Raspberry PI]ロボットモータなどの制御プログラムを[Raspberry PI]を起動時に埋め込む機能を付加します。
(この[UMEHOSHI ITA]側のプログラム情報はこのページにあります。)
それによって起動後は、遠隔操作用の「.umh」の転送だけでロボットを制御できるようにします。
この主要なコマンド(プログラムを入れたファイル名)は次のようになります。
前進 | uGoForward.umh |
後進 | uGoBack.umh |
左回転 | uGoLeft.umh |
右回転 | uGoRight.umh |
以上を実現するために、次のpythonのコードを作りました。
ソース名 | 概要 |
---|---|
umeusb.py | USBで[UMEHOSHI ITA]と通信する以下の関数群と変数を定義しています。 usb:このグローバル変数が指し示す接続相手とUSB通信するためのオブジェクト imort時にオープンされて、下記各関数はそれを利用する。 init_sub(): SUBのSerial初期化 check_sum(s:str) -> bool: check sum エラーでFalseを返す usb_send(s, endstr=b"\n",quantity=2):sを送信して、受信したバイナリを返す。タイムアウト時は""を返す endstrがquantity個受信した時点でリターンする。(コマンドの応答が2行であることが前提) send_cmd( ss, cmdchar="SRG"): usb_sendを利用してコマンド文字列群を引数で指定可能(S R G以外の先頭行文字列は無視) send_cmdfile(filepath, cmdchar="SRG"): send_cmdを利用して、filepathの「UME専用Hexコマンド」をUSB先の[UMEHOSHI ITA]に送信 usb_receive_func: 利用時に変更するusb受信で処理する関数を、記憶する変数 単体の実行で、キー入力したhexコマンドをUSBで[UMEHOSHI ITA]に送信可能 |
umetcp.py | TCPで[UMEHOSHI ITA]と通信する以下の関数群を定義しています。(他にカメラを参照する変数も初期化) imort時にオープンされて、下記各関数はそれを利用する。 send_file(sock, filename): filenameのファイルをsockの相手に送信する。 send_message(sock,msg): msgの1行の文字列をsockの相手に送信する。 recieve_file(sock): sockからの受信ファイルでそのファイルを保存する。 recieve_message(sock): sockからの受信した文字列を表示する。 receiveData(sock): sockからの1つの受信処理で、上記の各受信処理を呼び出して作られる 単体の実行で、Wifiを介して「umehoshiアプリからのメッセージ受信、ファイル受信、カメラ撮影と送信が可能 |
umehoshi.py | TCPサーバとして起動して、受信したコマンドで[UMEHOSHI ITA]と通信するメインの処理を行っています。 上記モジュール(umeusb.py、umetcp.py)をimportして利用してTCP受信でUSBへコマンド送り制御します。 my_usb_receive_func(bin):usb受信に対する処理で、umeusbのデフォルトを置き換え、TCP接続相手へ応答メッセージを送出する my_tcp_receive_file_func(file): 受信したumehoshiアプリ用「.umh」のファイルより、E専用Hex文字列をusbへ出力する |
umehoshi.pyをサービスとして、電源投入時に、実行させる設定を行います。
この自動起動には、Systemdを使った方法でを使います。
Systemdはサービスとして、起動、シャットダウン、再起動などをコマンドで操作ができるのようになります。
個々のサービスなどの設定を行うファイル「 Unitファイル」を次のように作ります。
ユーザ作成のUnitファイルの置き場は、「/etc/systemd/system」と決まって、次のファイルを使います。
「/etc/systemd/system/umehoshi.service」をsudoの編集操作で操作します。
[Unit] Description = umehoshiserver. [Service] ExecStart= /home/pi/umehoshi/umehoshi.py Type=simple [Install] WantedBy=multi-user.target
(基本的には、「Description」にサービス名、「ExecStart」に実行したいプログラムを記載しています。)
サービス制御用のコマンドの表を以下に示します。
コマンド操作 | 意味 | |
---|---|---|
(1) | sudo systemctl start umehoshi.service | サービスを開始(自動実行の登録前の検証時の実行で使う) |
(2) | sudo systemctl stop umehoshi.service | サービスを停止 |
(3) | sudo systemctl enable umehoshi.service | サービスの自動起動を有効化します |
(4) | sudo systemctl status umehoshi.service | サービスの動作状況を確認します。 |
(5) | sudo systemctl disable umehoshi.service | サービスの自動起動を無効化します。 |
下記Systemdの設定は、後述しているumeusb.py、umetcp.py、umehoshi.pyの各動作確認ができてから行った方が良いでしょう。
手順(1): 「sudo systemctl start umehoshi.service」実行して60秒後にumehoshi.pyの動作をumeclient.pyで確認します。
手順(2): (1)が動作できたら、「sudo systemctl enable umehoshi.service」で起動の登録を行い、[Raspberry PI]をシャットダウンさせて電源を差し込み直します。
以上で 「umehoshiアプリ」からの遠隔操作が可能となるはずです。
(「umehoshiアプリ」で、pizeroのアクセスポイントに接続して、192.168.100.1に接続して使います。可能な操作はメッセージを送る。
「.umh」や「.hex」ファイル(S R のhexコマンド群)を転送して実行させる。写真を撮る操作です。)
なおこのumehoshiserverのサービスが実行中の場合は、tcpやUSBのポートが使用中の状態になります。
よって、後述しているumeusb.py、umetcp.py、umehoshi.pyを別途コマンドで起動することができなくなります。
これらをコマンド操作で実行させる場合は、「sudo systemctl stop umehoshi.service」でサービスを停止して操作する必要があります。
以前に紹介したPythonのUSB通信プログラムを変更して作ったもので、単独実行でキー入力した「UME専用Hexコマンド」を
[UMEHOSHI ITA ]にプログラムを転送して制御できるコードです。
(usb = serial.Serial(port = '/dev/ttyACM0', baudrate = 115200)のport設定は、[Raspberry PI]のUSB位置で変更する必要があるかもしれません)
send_cmdfileで、「.umh」と「.hex」のファイル両方に対応して、「UME専用Hexコマンド」だけをusbに送信しています。
import serial import threading import sys import time def defalut_usb_receive_func(bin): 'usb受信のイベントで実行するデフォルト処理' print( bin.decode('utf-8') ,end="") # USBより受信したデータを表示 usb_receive_func = defalut_usb_receive_func # usb受信で実行する処理 # 上記を変更することで、USB受信に対する振る舞いを変更できる。 "usb:このグローバル変数が指し示す接続相手とUSB通信するためのオブジェクト" "imort時にオープンされて、下記各関数はそれを利用する。" usb = None def init_sub(): global usb try: usb = serial.Serial(port = '/dev/ttyACM0', baudrate = 115200) #usb = serial.Serial(port = 'COM8', baudrate = 115200,timeout = 10) except Exception as e: print(e) sys.exit(1) print( usb ) # USB のシリアルオブジェクト表示 def check_sum(s): ''' b = check_sum("G10800090000067") ''' ck = 0 n = len(s) if n == 0: return for i in range(n-2): ck += ord(s[i]) # print(ck) # print(s[i] , end ="") # print(' ',s[-2:] , end ="") ck += int(s[-2:] , 16) ck &= 0x0f if ck != 0 : print("check sum error", ck) return False return True def usb_send(s, endstr=b"\n",quantity=2): ''' b = usb_send("G10800090000067", endstr=b"\n",quantity=1): sを送信して、受信したバイナリを返す。タイムアウト時は""を返す endstrがquantity個受信した時点でリターンする。 quantity=2のデフォルト値は、送信した1行に対するエコー文字列の1行と 応答文字列の1行を意味します。 ''' if check_sum(s) == False: return b"" usb.write(s.encode('utf-8')) usb.write(b'\r\n') rtnval=b"" while True: if quantity <= 0: return rtnval # 受信したバイナリーを返す。 b=usb.readline() if b == "": return "" rtnval+=b n=b.count(endstr) quantity-=n def send_cmd( ss, cmdchar="SRG"):# sの例[S048000800000FFAF000086] a = ss.split('\n') for s in a: s=s.strip() if s == "" or not s[0] in cmdchar : continue # S R G 以外のコマンドを無視 b = usb_send(s) # デフォルトで2行のudb応答文字列の受信を含むコマンド出力 usb_receive_func( b ) # USB受信で得られたbで行う処理 def send_cmdfile(filepath, cmdchar="SRG"): with open(filepath , "r", encoding="utf-8") as f: ss = f.readlines() if filepath.endswith(".umh") : ss = ss[1:] # 先頭のボタン仕様行を除去 ss="".join(ss) #print(ss) send_cmd( ss, cmdchar) # USB受信スレット例(b'end\r\n'受信まで繰り返す) def read_loop(): while True: try: b=usb.readline() # binary if(b == b'end\r\n'): print("recieve 'end'") break usb_receive_func( b ) # USB受信の処理 except Exception as e: #print(e) break # print("end read_loop()") if __name__ == "__main__x": # 「UME専用Hexコマンド」ファイルの送信テスト用 init_sub() send_cmdfile("app_pwm.c.hex") if __name__ == "__main__": # キー入力した「UME専用Hexコマンド」を送信して[UMEHOSHI ITA]を制御するテスト用 # スレッドに read_loop 関数を渡して実行を始める init_sub() t_id = threading.Thread(target=read_loop) t_id.start() while True: s = input("USBへ送信する文字列>")# 例[G10800090000067] if s == "": break usb_send( s, quantity=0 ) time.sleep(0.1) usb.close() print("Ended !")上記ファイルの単独実行例を示します。(キー入力した「UME専用Hexコマンド」の文字列を[UMEHOSHI ITA]に送って、その応答メッセージを表示)
pi@raspberrypi:~/umehoshi $ python3 umeusb.py Serial<id=0xb6890c30, open=True>(port='/dev/ttyACM0', baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False) USBへ送信する文字列>G10800090000067 G10800090000067 :108000900000CF0ABCECC71A6C23291CA1A32139A8A223 USBへ送信する文字列> Ended !
TCPで[UMEHOSHI ITA]と通信する以下の関数群を定義しています。(他にカメラを参照する変数も初期化)
umehoshiアプリTCP送受信メッセージの仕様に従って、
その1部であるM f T から始まる文字列に対する処理を定義しています。
それぞれの先頭文字は、[メッセージ文字列受信]、[ファイル受信]、[写真を撮ってファイルを要求]
の意味になっており、
receiveData関数でこの分岐処理をしています。
import os import sys path_datas = "datas" # 受信したhexファイルの記憶ディレクトリ path_pics = "pictures" # 撮影したファイルの記憶ディレクトリ if os.path.isdir(path_datas) == False: os.mkdir(path_datas) if os.path.isdir(path_pics) == False: os.mkdir(path_pics) try: import picamera # ★ raspberry Pi用 camera = picamera.PiCamera() # ★ except: pass def defalut_tcp_recieve_file(filename): 'tcpでファイルを受信した直後の処理' filesize = os.path.getsize(path_datas + "/" + filename) # 受信したファイル名とサイズを表示 print( "recieve file:{},size:{}".format(filename, filesize)) tcp_receive_file_func = defalut_tcp_recieve_file # tcpファイル受信で実行する処理 def defalut_tcp_recieve_message(msg): print( msg ) tcp_receive_message_func = defalut_tcp_recieve_message # tcpメッセージ受信で実行する処理 def send_file(sock, filepath): filesize = os.path.getsize(filepath) filename = os.path.basename(filepath) s = "f{} {}".format(filename, filesize) bin=(s+"\r\n").encode("utf-8")#binaryへ変換 print(bin, end=" ") sock.sendall(bin) #filename filesize 送信 with open(filepath, "rb") as f: bin = f.read(filesize) # print("送信data:" , bin ) sock.sendall(bin) # ファイル内容一括送信 print("送信byte:" , len(bin) ) def send_message(sock,msg): bin=('M'+msg+"\r\n").encode("utf-8")#binaryへ変換 sock.sendall(bin)#一括送信 def recieve_file(sock): buf=b"" while True: bin = sock.recv(1)#1byte受信 if len(bin) != 1: break buf += bin if buf[-2:] == b"\r\n":# 1行の文字列受信終了? s = buf[0:-2].decode('utf-8')#バイナリから #print(s) a=s.split(' ') filename, filesize = a[0], int(a[1]) print(filename, filesize) # 受信ファイルとサイズ確定 #bin = sock.recv(filesize) # ファイルの一括受信 bin=b"" while len(bin) < filesize: bin += sock.recv(filesize-len(bin)) # ファイルの受信 #print( bin ) with open( path_datas + "/" + filename, "wb") as f: f.write(bin) tcp_receive_file_func(filename) break def recieve_message(sock): buf=b"" while True: bin = sock.recv(1)#1byte受信 if len(bin) != 1: break buf += bin #print("----", buf) if buf[-2:] == b"\r\n":# 1行の文字列受信終了? s = buf[0:-2].decode('utf-8')#バイナリから tcp_receive_message_func(s) # 受信文字列の対処 break def receiveData(sock): print( "start receiveData" ) while True: bin = sock.recv(1)#1byte受信 if len(bin) != 1: break if bin == b"f" : recieve_file(sock) elif bin == b"M" : recieve_message(sock) elif bin == b"T" : sock.recv(1)#'\r'受信 sock.recv(1)#'\n'受信 pic_file_name="serverpicture.jpg" if 'camera' in globals(): camera.capture(path_pics + "/" + pic_file_name) # ★写真撮影 print("写真撮影") send_file(sock,path_pics + "/" + pic_file_name) print("送信ファイル:" + pic_file_name) else: print(bin , end="") # print( "receiveData ended." ) if __name__ == "__main__": import socket portnumber=59154 ip = "192.168.100.1" ip = "192.168.0.123" #[Raspberry PI Zero WH]の設定に合わせてください server_addr =(ip, portnumber) print("Serverの情報:",server_addr) serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversock.bind(server_addr) # IPとポート番号を指定します print("接続要求を待つ") serversock.listen() sock, address = serversock.accept()#サーバの接続受け入れ try: receiveData( sock ) # 命令を受信して処理するループ except: pass sock.close() serversock.close()
上記ファイルの確認用実行例を示します。
sshで「192.168.0.123」に接続した後、PC側のpythonが動作するコマンドプロンプトで「python umeclient.py]
サーバ側IPアドレス(192.168.0.123)は[Raspberry PI]の設定に合わせて変更して使ってください。
[Raspberry PI]をアクセスポイントしてWifi環境がない所でも使う最終設定は192.168.100.1ですが、
ここでは、既存アクセスポイントを介して[Raspberry PI]の192.168.0.123に接続している状態の例です。
なお、右下では「umehoshiアプリ」の代わりにその一部を実現するumeclient.pyを使って検証しています。
(写真表示の警告や終了時のエラーは無視してください)
[Raspberry PI]に接続中のssh内容 | PC側の操作用コマンドプロンプト |
---|---|
pi@raspberrypi:~/umehoshi $ python3 umetcp.py Serverの情報: ('192.168.0.123', 59154) 接続要求を待つ start receiveData hello uGoForward.umh 24 recieve file:uGoForward.umh,size:24 写真撮影 b'fserverpicture.jpg 250169\r\n' 送信byte: 250169 送信ファイル:serverpicture.jpg pi@raspberrypi:~/umehoshi $ |
D:\raspi_zero\umehoshi>python umeclient.py IP (defualt:192.168.0.123)Address>192.168.0.123 接続成功 start receiveData 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>M 送信したい文字列入力>hello 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>w b'fuGoForward.umh 24\r\n' 送信byte: 24 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>T serverpicture.jpg 250169 recieve file:serverpicture.jpg,size:250169 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>quit |
TCPサーバとして起動させて、受信したコマンドで[UMEHOSHI ITA]と通信するメインの処理を行っています。
上記モジュール(umeusb.py、umetcp.py)をimportして利用してTCP受信でUSBへコマンド送り制御します。
[Raspberry PI Zero WH]に合わせたIPアドレスでTCPサーバをバインドしていますが、[Raspberry PI Zero WH]の設定に合わせてください。
以下では、192.168.100.1にしている最終設定例です。
(これは、のSystemdを使った自動的な起動に合わせた設定です。デバックなどの確認時は192.168.0.123で動作を確認すると良いでしょう)
起動自に、app_pwm_pizero.c.hexのファイルを読み取って、[UMEHOSHI ITA]を初期化しています。
このソース(app_pwm_pizero.c)はこのページにあります。
これをビルドして作っており、これを置き換えることで、起動時の[UMEHOSHI ITA]プログラムが変更できます。
#!/usr/bin/python3 # -*- coding: utf-8 -*- # サーバ側「sudo python3 umehosi.py」で動かす import os import umetcp from umetcp import send_file, send_message, recieve_file, recieve_message, \ receiveData , path_datas import socket import umeusb import sys import time sock = None # クライアント側のソケット os.chdir("/home/pi/umehoshi/") # ip = "192.168.0.123" #[Raspberry PI Zero WH]の設定に合わせてください ip = "192.168.100.1" if ip == "192.168.100.1": time.sleep(60) # 60秒待機 args=sys.argv umeusb.init_sub() start_path = path_datas + "/" + "app_pwm_pizero.c.hex" if os.path.isfile( start_path ) == True: umeusb.send_cmdfile(start_path) umeusb.send_cmd("R00800050000061") def my_usb_receive_func(bin): 'usb受信のイベントで実行するデフォルト処理' global sock #print("-----------",bin) ss = bin.decode('utf-8') a=ss.split('\n') for s in a: s = s.strip() if sock != None: send_message(sock, s) # [UMEHOSHI ITA]からの応答メッセージをTCPで返す else: print( s ) umeusb.usb_receive_func = my_usb_receive_func # USB受信データの処理を置き換える。 def my_tcp_receive_file_func(filename): ''' 受信したumehoshiアプリ用「.umh」のファイルより、 「UME専用Hexコマンド」の文字列をusbへ出力する''' name,ext = os.path.splitext(filename) if not ext == ".umh" : return with open(path_datas + "/" + filename) as f: ss=f.readlines() ss="".join(ss) #print(ss) umeusb.send_cmd(ss) # TCPで受信した 「.umh」データを[UMEHOSHI ITA]へ送る umetcp.tcp_receive_file_func = my_tcp_receive_file_func # tcp受信データの処理を置き換え portnumber=59154 hostname=socket.gethostname() if len(args) >= 2: ip = args[1] # 引数でIPアドレス指定があれば使う server_addr =(ip, portnumber) print("Serverの情報:",hostname, server_addr) serversock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversock.bind(server_addr) # IPとポート番号を指定します print("接続要求を待つ") serversock.listen() while True: print("接続を待って、接続してきたら許可") sock, address = serversock.accept()#サーバの接続受け入れ print("接続相手:",address) try: receiveData( sock ) # 受信ループ except Exception as e: print(e, "相手が閉じた?") sock.close()
実行例を示します。
[Raspberry PI Zero WH]のアクセスポイント(ssid:pizero)に接続してから、192.168.100.1のsshターミナルでRaspberry PIを操作します。
[Raspberry PI Zero WH]のアクセスポイント(ssid:pizero)が有効になるまでに時間がかかる
ことに合わせて、60秒ほど経過してから
各種の初期化が行われるようにしています。
よって、左下のpython3 umehoshi.py実行後、60秒間は何も表示しない状況があることに注意してください。
その後、"app_pwm_pizero.c.hex"を[UMEHOSHI IT]に転送する画面へと続きます。
この転送が終わってから、pythonが動作するPC側のコマンドプロンプトで「python umeclient.py]で遠隔操作をしている例です。
「192.168.100.1」で接続している例です。(接続で左側では「接続相手: ('192.168.100.5', 52442)」が追加表示されています)
PC側ではその後、「M」を入力して " hello"の文字列を送り、
次に「w」を入力して [uGoForward.umh]のファイル転送でモータを正転させて、
次に「T」を入力して 写真撮影とそのファイル転送をさせた後、quit入力で終了させています。
(写真表示の警告や終了時のエラーは無視してください)
[Raspberry PI]に接続中のssh内容 | PC側の操作用コマンドプロンプト |
---|---|
pi@raspberrypi:~/umehoshi $ python3 umehoshi.py Serial |
【Raspberry PIの初期化が終わるまで60秒待ちます】 D:\raspi_zero\umehoshi>python umeclient.py IP (defualt:192.168.0.123)Address>192.168.100.1 接続成功 start receiveData 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>M 送信したい文字列入力> hello 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>w b'fuGoForward.umh 24\r\n' 送信byte: 24 R0080005200005F START:80005200 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>T serverpicture.jpg 126136 recieve file:serverpicture.jpg,size:126136 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T> quit |
Raspberry PI側では、PCの接続が終わると、「接続を待って、接続してきたら許可」の表示が出て、次の接続が可能になっています。
以上の確認ができてから、Systemdによる自動起動の設定をすると良いでしょう。
上記の[UMEHOSHI ITA]で実行させるumehoshi.pyに対するクライアントプログラムで、実験的なコードです。
上記のサーバ側IPアドレス(192.168.100.1 or 192.168.0.123)に合わせて変更して使ってください。
[Raspberry PI]をアクセスポイントしてWifi環境がない所でも使う最終設定では192.168.100.1にして使います。
#!/usr/bin/python3 # -*- coding: utf-8 -*- # クライアント側 「sudo python3 umeclient.py」で動かす import socket from umetcp import send_file, send_message, recieve_file, recieve_message,receiveData,path_datas import os import sys import time import threading import umetcp import numpy as np from PIL import Image import matplotlib matplotlib.use('TkAgg') #うまくいかなければ MacOSX Qt5Agg Qt4Agg Gtk3Agg GTK3Cairo TkAgg WxAgg Agg Cairo の中から選ぶ import matplotlib.pyplot as plt def my_tcp_recieve_file(filename): 'tcpでファイルを受信した直後の処理' filepath = path_datas + "/" + filename filesize = os.path.getsize(filepath) # 受信したファイル名とサイズを表示 print( "recieve file:{},size:{}".format(filename, filesize)) if filename == 'serverpicture.jpg': img = Image.open(filepath) # 元となる画像の読み込み np_img = np.array( img ) plt.imshow( np_img ) # 各OSの標準ビューアが開く。 plt.show( ) #block= False ) umetcp.tcp_receive_file_func = my_tcp_recieve_file portnumber=59154 # ip="192.168.0.123" #[Raspberry PI Zero WH]の設定に合わせてください ip="192.168.100.1" s = input("IP (defualt:{})Address>".format(ip)) if s != "": ip = s sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, portnumber)) print("接続成功") t_id = threading.Thread(target=receiveData, args=(sock,) ) t_id.start() loopFlag = True cmd="" while loopFlag: s = input("送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>") if s != "": cmd = s if cmd == 'M': msg = input("送信したい文字列入力>") send_message(sock,msg) elif cmd == 'f': print(os.listdir(path_datas)) filename = input("送信したいファイル名入力>") if not os.path.isfile(path_datas + "/" + filename): print( filename, "no exist") countine send_file(sock, path_datas + "/" + filename) elif cmd == 'quit': loopFlag=False elif cmd == 'w': send_file(sock, path_datas + "/" + "uGoForward.umh") elif cmd == 'x': send_file(sock, path_datas + "/" + "uGoBack.umh") elif cmd == 'a': send_file(sock, path_datas + "/" + "uGoLeft.umh") elif cmd == 'd': send_file(sock, path_datas + "/" + "uGoRight.umh") elif cmd == 'Q': send_file(sock, path_datas + "/" + "uLeftUp.umh") elif cmd == 'Z': send_file(sock, path_datas + "/" + "uLeftDown.umh") elif cmd == 'E': send_file(sock, path_datas + "/" + "uRightUp.umh") elif cmd == 'C': send_file(sock, path_datas + "/" + "uRightDown.umh") elif cmd == 'T': sock.sendall( ('T'+"\r\n").encode("utf-8") )# 写真を撮って、そのファイルを要求 # time.sleep(0.5) sock.close() sys.exit(0)
「umehoshi.service」のサービス実行中であれば 「umehoshiアプリ」の代わりに、このファイルで動作が確認できます。
このロボットの電源投入後2分経過(実測値は1分43秒)してから、
[Raspberry PI Zero WH]のアクセスポイント(ssid:pizero)に接続し、
pythonが動作するPC側のコマンドプロンプトで「python umeclient.py]で遠隔操作をしている例です。
D:\raspi_zero\umehoshi>python umeclient.py IP (defualt:192.168.0.123)Address>192.168.100.1 接続成功 start receiveData 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>M 送信したい文字列入力> hello 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>w b'fuGoForward.umh 24\r\n' 送信byte: 24 R0080005200005F START:80005200 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T>T serverpicture.jpg 126136 recieve file:serverpicture.jpg,size:126136 送信したい情報を選択入力'M'/'f'/'quit'/w/x/a/d/Q/Z/E/C/T> quit