IoT+WEBのためのホームサーバ計画の5、とりあえずWebSocketを動かしましょう的な話

ちょっと後回しになりましたが、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)

あまりにテキトーなのでなんですが、とりあえず動くので、あとでちゃんとします。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です