IoT+WEBのためのホームサーバ計画の5、とりあえずWebSocketを動かしましょう的な話
2020-02-10
ちょっと後回しになりましたが、WebSocketです。
もちろんMQTTがどうしたとか、そういうのもいいのですが、
とりあえず、WebSocketをテストしますね。
ってことで、
pip3 install websocket-server
pip3 install websocket-client
あたりで準備して、サーバとクライアントで、とは言え最初は同一マシンでやってみます。
今回は動けばいいってことと、どのレベルで外部から呼べるかみたいなことを考えるだけなので、
サンプルは、ぐでぐでですが。(o^^o)
サーバ側
from websocket_server import WebsocketServer
import logging
import time
import multiprocessing
import threading
import socket
import json
#---------------------------------------------------------------
class hiraWsServer():
clAR = [] # {"client":****,"data":****},のARRAY。DATA部分はカスタム
dolly = None
#---------------------------------------
# idからクライアントを特定する
#---------------------------------------
def searchClient(self, id):
n = len(self.clAR)
for w in range(n):
if self.clAR[w]['client']['id'] == id:
return self.clAR[w]['client']
return None
#---------------------------------------
# idからクライアントリストから削除する
#---------------------------------------
def deleteClient(self, id):
n = len(self.clAR)
for w in range(n):
if self.clAR[w]['client']['id'] == id:
del self.clAR[w]
print("delete client list @ ",id,"->" ,len(self.clAR))
#---------------------------------------
def __init__(self, host, port, funcs = None):
# self.server = WebsocketServer(port, host=host, loglevel=logging.DEBUG)
self.server = WebsocketServer(port, host=host)
self.dolly = funcs
#---------------------------------------
# クライアント接続時に呼ばれる関数
#---------------------------------------
def new_client(self, client, server):
print("new client connected and was given id {}".format(client['id']))
# 全クライアントにメッセージを送信
self.server.send_message_to_all("hey all, a new client has joined us")
#self.client = client
print("cl:",client)
print("sv:",server)
o = {"client":client,"data":{}}
self.clAR.append(o)
#---------------------------------------
# クライアント切断時に呼ばれる関数
#---------------------------------------
def client_left(self, client, server):
print("client({}) disconnected".format(client['id']))
id = client['id']
self.deleteClient(id)
#---------------------------------------
# クライアントからメッセージを受信したときに呼ばれる関数
#---------------------------------------
def message_received(self, client, server, message):
# print("client({}) said: {}".format(client['id'], message.encode('utf-8')))
print("client({}) said: {}".format(client['id'], message))
#J = json.loads(message)
#print(J)
self.server.send_message_to_all(message.encode('utf-8')) # 全クライアント送信
#---------------------------------------
# サーバーを起動する
#---------------------------------------
def run(self):
self.server.set_fn_new_client(self.new_client) # クライアント接続時CALLBACK
self.server.set_fn_client_left(self.client_left) # クライアント切断時CALLBACK
self.server.set_fn_message_received(self.message_received) # メッセージ受信時CALLBACK
self.server.run_forever()
#---------------------------------------
def exec(adr,port,funcs=None):
print("address:",adr," port:",port)
ws_server = hiraWsServer(adr,port,None)
if callable(funcs):
funcs(ws_server)
ws_server.run()
#---------------------------------------
#---------------------------------------------------------------
class hiraWsServerAdmin():
def setWsServer(self,inst):
self.server = inst # hiraWsServerInstance
print("regit 2 admin.")
def test(self):
t = threading.Thread(target=self.testlocal)
t.start()
def testlocal(self):
time.sleep(10)
cl = self.server.searchClient(1)
if cl:
self.server.server.send_message(cl,"message from server だよーー".encode('utf-8'));
#---------------------------------------------------------------
if __name__ == '__main__':
A = hiraWsServerAdmin()
A.test() # threadだから戻ってくる
laddress = socket.gethostbyname(socket.gethostname())
IP_ADDR = laddress
PORT = 9001 # ポート
hiraWsServer.exec(IP_ADDR, PORT, A.setWsServer)
クライアント側
import websocket
import threading
import time
import socket
import json
#------------------------------------------------------------
class hiraWsClient():
def __init__(self, host_addr):
websocket.enableTrace(True) # デバックログ
self.ws = websocket.WebSocketApp(
host_addr
,on_message = lambda ws, msg: self.on_message(ws, msg)
,on_error = lambda ws, msg: self.on_error(ws, msg)
,on_close = lambda ws: self.on_close(ws))
self.ws.on_open = lambda ws: self.on_open(ws)
self.ws.keep_running = True
def on_message(self, ws, message): # 受信
print("receive : {}".format(message))
def on_error(self, ws, error): # エラー時
print(error)
def on_close(self, ws): # サーバーから切断時
print("## closed ##")
def on_open(self, ws): # サーバーから接続時
t = threading.Thread(target=self.run)
t.start()
def run(self): # サーバーから接続時にスレッドで起動
while True:
time.sleep(0.1)
input_data = input("send data:")
self.ws.send(input_data.encode('utf-8'))
self.ws.close()
print("thread terminating...")
def run_forever(self): # websocketクライアント起動
self.ws.run_forever()
def exec(adr,port,funcs=None):
print("address:",adr," port:",port)
HOST_ADDR = "ws://" + adr + ":" + str(port) + "/"
ws_client = hiraWsClient(HOST_ADDR)
if callable(funcs):
funcs(ws_client)
ws_client.run_forever()
#---------------------------------------
#---------------------------------------------------------------
class hiraWsClientAdmin():
def setWsClient(self,inst):
self.client = inst # hiraWsClientInstance
print("regit 2 admin.")
def test(self):
t = threading.Thread(target=self.testlocal)
t.start()
def testlocal(self):
time.sleep(15)
self.client.ws.send("message from CLIENT ですです。".encode('utf-8'))
# J = '{"name":"ひらひら"}'
# jstr = json.dumps(J,separators=(',', ':'))
# self.client.ws.send(jstr)
#---------------------------------------------------------------
#------------------------------------------------------------
if __name__ == '__main__':
A = hiraWsClientAdmin()
A.test() # threadだから戻ってくる
port = 9001
laddress = socket.gethostbyname(socket.gethostname())
hiraWsClient.exec(laddress,port,A.setWsClient)
あまりにテキトーなのでなんですが、とりあえず動くので、あとでちゃんとします。