IoT+WEBのためのホームサーバ計画の2、IoTコントローラからホームサーバへUDPで自分のIPを通知する
2020-02-07
前回、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)
ってことです。