IoT+WEBのためのホームサーバ計画の2、IoTコントローラからホームサーバへUDPで自分のIPを通知する

前回、IoT+WEBのためのホームサーバ計画というものの概要でした。
プログラムをつくるときは、詳細から入るときと、全体から入るとき、
さらに両方から攻めるときとあります。

今回は詳細の方ですね。
詳細から入る意味は、技術検討的に
『これでいいのか?』
というのを含むときとかはですね。

技術検討で不可能だった場合には、そもそも全体に影響するわけなので。
ということで、今回は検討するほどの話でも無いし、
別の言語ではちょくちょくやったりしたことなので、心配はないのですが、
まぁPythonではやったことがなかったので、とりあえずテストを兼ねてやってみます。

で、ですね、、
ホームサーバはIoTコントローラのIPを知らないし、
IoTコントローラ はホームサーバのIPを知らないので、
IoTコントローラからUDPでブロードキャストするって方法をとります。

で実際のコードを見てみましょ。

サーバ側

import socket
import struct
from contextlib import closing
import threading
#--------------------------------------
class	hiraUdpSv:
	def	__init__(self,address='239.255.255.250',port=60011):
		self.address	= address;
		self.port		= port;
	#--------------------------
	def __enter__(self):
		#print("前処理")
		return self		#必須
	#--------------------------
	def __exit__(self, exc_type, exc_value, traceback):
		#print("後処理")
		self.tmp = 0
	#--------------------------
	def	exec(self):
		t = threading.Thread(target=self.execlocal)
		t.start()
	def execlocal(self):
		local_address	= '0.0.0.0'
		multicast_group	= self.address
		port			= self.port
		bufsize = 4096
		print("#-------------------------")
		print("  m_cast_group; {}".format(multicast_group))
		print("  port; {}".format(port))
		print("#-------------------------")

		with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as sock:
			sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
			sock.bind(('', port))
			sock.setsockopt(	socket.IPPROTO_IP,
								socket.IP_ADD_MEMBERSHIP,
								socket.inet_aton(multicast_group) + socket.inet_aton(local_address))
			while True:
				data,address = sock.recvfrom(1024)
				print("from; {}  data:{}".format(address[0],data))
				if data == b"FINRED_BROADING":
					print("Registing IoT client")
#--------------------------------------
if __name__ == '__main__':
	U = hiraUdpSv()
	U.exec()

IoTコントローラ(クライアント)側

import socket
import time
from contextlib import closing
#--------------------------------------
class	hiraUdpCl:
	def	__init__(self,address='239.255.255.250',port=60011):
		self.address	= address;
		self.port		= port;
	#--------------------------
	def __enter__(self):
		#print("前処理")
		return self		#必須
	#--------------------------
	def __exit__(self, exc_type, exc_value, traceback):
		#print("後処理")
		self.tmp = 0
	#--------------------------
	def	exec(self,message):
		local_address	= '0.0.0.0'
		multicast_group = self.address
		port			= self.port
		with closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as sock:
			sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(local_address))
			sock.sendto(message.encode('utf-8'), (multicast_group, port))
	#--------------------------
#--------------------------------------
if __name__ == '__main__':
	C = hiraUdpCl()
	C.exec("FINRED_BROADING")

こんな感じです。
UDPの場合でブロードキャストするようなときは、
ソケットのOPTIONとか間違えると、うんともすんとも言わないとかありますよね。
だからって言って、そのな頻繁に色んなパラメータでプログラム書く機会も無いので、
ちょくちょく忘れちゃううんですよね。
今回も、動くまで、何回か書き直しました。

で、サーバ側の実行画面

#-------------------------
  m_cast_group; 239.255.255.250
  port; 60011
#-------------------------
from; 192.168.43.113  data:b'FINRED_BROADING'
Registing IoT client

サーバ側は、
b”FINRED_BROADING”
がきたら、登録するって感じです。
登録するとこは書いてませんけど。

あとは、ホームサーバ側は、常にいろんなリクエストを待ってることになるので、
そこは全体としての設計をしながらってことになります。
まぁ早い話、
スレッドとプロセスをどうしよーか(o^^o)
ってことです。

コメントする

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