add broadcast device discovery
This commit is contained in:
parent
f74ce76369
commit
9747010caf
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -3,5 +3,5 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.12 (autopicture-v3)" />
|
<option name="sdkName" value="Python 3.12 (autopicture-v3)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (autopicture-v3)" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
||||||
@ -7,4 +7,5 @@ if [ "$API" = true ]; then
|
|||||||
sleep 1
|
sleep 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
python3.12 main.py
|
python3.12 start_discovery_server.py &
|
||||||
|
python3.12 main.py
|
||||||
|
|||||||
@ -1,54 +1,75 @@
|
|||||||
from time import sleep
|
# https://github.com/jholtmann/ip_discovery
|
||||||
import socket
|
|
||||||
import FindMyIP
|
|
||||||
import ipaddress
|
|
||||||
import threading
|
|
||||||
import requests
|
|
||||||
import os
|
import os
|
||||||
|
import FindMyIP
|
||||||
|
from socket import *
|
||||||
|
from helpers import get_unix_time
|
||||||
|
|
||||||
DEBUG = True if os.environ.get('DEBUG') is not None else False
|
DEBUG = True if os.environ.get('DEBUG') is not None else False
|
||||||
max_threads = 50
|
DISCOVERY_ACK = 'IP_DISCOVERY_ACK'.encode() # ACK for broadcast
|
||||||
port = 8000
|
DISCOVERY_RSP_GTW = 'IP_DISCOVERY_RSP_GTW'.encode() # RSP for gateway
|
||||||
final = {}
|
DISCOVERY_RSP_MSH = 'IP_DISCOVERY_RSP_MSH'.encode() # RSP for mesh
|
||||||
|
DISCOVERY_TIMEOUT = 20
|
||||||
|
SOCKET_TIMEOUT = 5
|
||||||
|
PORT_SERVER = 9434
|
||||||
|
PORT_CLIENT = 9435
|
||||||
|
|
||||||
|
|
||||||
def check_port(ip, port):
|
def start_discovery_server():
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
|
server_address = ('', PORT_SERVER)
|
||||||
|
local_ip = FindMyIP.internal()
|
||||||
try:
|
try:
|
||||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP
|
sock.bind(server_address)
|
||||||
# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
|
print("Started discovery socket")
|
||||||
socket.setdefaulttimeout(2.0) # seconds (float)
|
while True:
|
||||||
result = sock.connect_ex((ip, port))
|
data, addr = sock.recvfrom(4096)
|
||||||
if result == 0: final[ip] = True
|
print(f"Received a packet from {addr}")
|
||||||
else: final[ip] = False
|
print(f"{addr[0]} | {local_ip}")
|
||||||
|
print(f"{data} | {DISCOVERY_ACK}")
|
||||||
|
|
||||||
|
if data == DISCOVERY_ACK:
|
||||||
|
print("ACK accepted")
|
||||||
|
if str(addr[0]) == str(local_ip): continue
|
||||||
|
print("IP accepted")
|
||||||
|
sock.sendto(DISCOVERY_RSP_GTW, (addr[0], PORT_CLIENT))
|
||||||
|
print(f"Send ACK to {addr}")
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
def start_discovery_client():
|
||||||
def scan_for_gateways():
|
print("Started discovery client")
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
|
sock.settimeout(SOCKET_TIMEOUT)
|
||||||
|
server_address = ('255.255.255.255', PORT_SERVER)
|
||||||
local_ip = FindMyIP.internal()
|
local_ip = FindMyIP.internal()
|
||||||
local_ip = local_ip.split('.')[:-1]
|
start_time_stamp = get_unix_time()
|
||||||
local_ip.append("0")
|
delta = round(get_unix_time() - start_time_stamp, 2)
|
||||||
local_ip = '.'.join(local_ip)
|
discovered_devices = []
|
||||||
print(f"Scan on {local_ip}/24 for port {port}") if DEBUG else {}
|
|
||||||
|
|
||||||
for ip in ipaddress.IPv4Network(f'{local_ip}/24'):
|
try:
|
||||||
threading.Thread(target=check_port, args=[str(ip), port]).start()
|
sock.bind(('', PORT_CLIENT))
|
||||||
# limit the number of threads.
|
while True:
|
||||||
while threading.active_count() > max_threads: sleep(1)
|
delta = round(get_unix_time() - start_time_stamp, 2)
|
||||||
|
print(delta)
|
||||||
|
sock.sendto(DISCOVERY_ACK, server_address)
|
||||||
|
data, addr = sock.recvfrom(4096)
|
||||||
|
print('IP: ' + str(addr[0]))
|
||||||
|
if data == DISCOVERY_RSP_GTW or data == DISCOVERY_RSP_GTW and addr[0] not in discovered_devices:
|
||||||
|
print('IP: ' + str(addr[0]))
|
||||||
|
discovered_devices.append(addr[0])
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
sorted_ips = dict(sorted(final.items(), key=lambda item: tuple(map(int, item[0].split('.')))))
|
finally:
|
||||||
|
sock.close()
|
||||||
|
|
||||||
gateways = []
|
|
||||||
for ip, state in sorted_ips.items():
|
|
||||||
if state:
|
|
||||||
try:
|
|
||||||
response = requests.get(f'http://{ip}:{port}/api')
|
|
||||||
# TODO: Check if the API is for real a gateway
|
|
||||||
if response.status_code == 200:
|
|
||||||
print(ip, response.json()) if DEBUG else {}
|
|
||||||
gateways.append([ip, response.json()])
|
|
||||||
except:pass
|
|
||||||
return gateways
|
|
||||||
|
|
||||||
|
# start_discovery_client()
|
||||||
|
|||||||
16
python/src/helpers.py
Normal file
16
python/src/helpers.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
def get_time_now():
|
||||||
|
date_now = datetime.datetime.now()
|
||||||
|
return str(date_now).split(" ")[0]
|
||||||
|
|
||||||
|
|
||||||
|
def get_unix_time():
|
||||||
|
return time.time()
|
||||||
|
|
||||||
|
|
||||||
|
def get_date():
|
||||||
|
date_now = datetime.datetime.now()
|
||||||
|
return str(date_now).split(" ")
|
||||||
@ -1,6 +1,6 @@
|
|||||||
from time import sleep
|
from time import sleep
|
||||||
from log_data import log_to_json
|
from log_data import log_to_json
|
||||||
from discovery import start_discovery
|
from ble_discovery import start_discovery
|
||||||
|
|
||||||
|
|
||||||
def start_loop(interval=40, timeout=20):
|
def start_loop(interval=40, timeout=20):
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
from discovery import start_discovery
|
from ble_discovery import start_discovery
|
||||||
from log_data import log_to_json
|
from log_data import log_to_json
|
||||||
from loop import start_loop
|
from loop import start_loop
|
||||||
from check_update import check_for_update
|
from check_update import check_for_update
|
||||||
|
|||||||
2
python/src/start_discovery_server.py
Normal file
2
python/src/start_discovery_server.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
from find_gateways import start_discovery_server
|
||||||
|
start_discovery_server()
|
||||||
Loading…
x
Reference in New Issue
Block a user