ラズパイ側でコマンドを作って送信、Windowsにいろいろやってもらう…..シリーズでは音声認識でコマンドを送っていましたが今回は単純にPythonからsocketでコマンドを1対1で送るだけです。
何をやるかというと、Windows側でEtehreumのマイニングをやってもらいます。
赤線
ラズパイからWin10にマイニングをお願い
青線
Win10からマイニングの状況をラズパイへ通知
ラズパイから制御
CURL JSON-RPC APIを使って、8545ポートで直接Windows10側IPアドレスに通信することはできません(着信拒否されます)。
socketを使います。
ラズパイ(Python) ->socket ->Windows(Python)
Pythonコード
【送信側】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#!/usr/bin/env python3 # -*- coding: utf8 -*- import socket #Windows10側IPアドレス例 HOST = '192.168.0.23' PORT = 61000 def com_send(mess): while True: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) sock.send(mess.encode('utf-8')) sock.close() break except: print ('retry: ' + mess) if __name__ == "__main__": request = "miner_start" json_txt = '{"ethereum":"' + request +'"}' com_send(json_txt) |
【受信側】
CURL JSON-RPC API経由でGethのコマンドを使ってみます。
Pythonから直接JSON-RPCを実行する場合
Windowsではpyinstallerで実行形式にしておきます(PythonファイルはUTF-8 BOM無しで保存)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
#!/usr/bin/env python3 # -*- coding: utf8 -*- import socket import threading import json import subprocess PORT = 61000 MAX_MESSAGE = 2048 NUM_THREAD = 4 def miner(job): if(job == "miner_start"): com = "{\"jsonrpc\":\"2.0\",\"method\":\"miner_start\",\"params\":[1],\"id\":10}" elif(job == "miner_stop"): com = "{\"jsonrpc\":\"2.0\",\"method\":\"miner_stop\",\"params\":[],\"id\":10}" #子プロセスのウインドウを表示しないよう、subprocess.Popenに以下のようなstartupinfoを渡します。 startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW startupinfo.wShowWindow = subprocess.SW_HIDE subprocess.Popen([ 'curl', '-H', "Content-Type: application/json", '--data', com, 'http://localhost:8545' ], startupinfo=startupinfo) def operation(reception): obj = json.loads(reception) try: eth_txt = obj['ethereum'] except: eth_txt = "" if(eth_txt != ""): miner(eth_txt) def com_receive(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip_info = socket.gethostbyname_ex(socket.gethostname()) ip_list = ip_info[2] for x in ip_list: ip = x octet_list = ip.split(".") if(int(octet_list[2]) == 0): local_address = ip break sock.bind ((local_address, PORT)) sock.listen (NUM_THREAD) print('receiver ready, NUM_THREAD = ' + str(NUM_THREAD)) while True: try: conn,addr = sock.accept() mess = conn.recv(MAX_MESSAGE).decode('utf-8') conn.close() operation(mess) except: print('Error') sock.close() def com_start(): th=threading.Thread(target=com_receive) th.start() if __name__ == "__main__": com_start() |
やってみます
WindowsでGeth起動->ラズパイでGeth起動->static-nodes.jsonで相互接続->ラズパイからwindowsへマイニングを依頼->Windowsでマイニングを実行
同期の状況
3つを比べて観ると、同じ番号(1211)のブロック生成でラズパイの方が表示が早いように見えますが、時計を確認してみるとラズパイは両方ともWindowsより約2秒遅れていました。辻褄はあっています。つまりWindowsでマイニングした結果がラズパイに渡されています(^^)。なぜラズパイの時計がずれるのかというとラズパイはハードウエア時計(RTC)を持っていないからだそうです。
Windowsのログ
ラズパイBの画面
ラズパイB+の画面
WindowsでGethを使っている場合
miner.start()をやってもマイニングが実行されないという現象が起こりました。
原因は不明なのですが、対策としてこんなことをやってみました。
これでいいのかな?
Next
Ethereumのスマートコントラクトでなんかやってみます。
Leave a Reply