diff --git a/.idea/misc.xml b/.idea/misc.xml index afcdc7f..12391f3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/python/docker_entrypoint.sh b/python/docker_entrypoint.sh index aeb780b..bafdaea 100644 --- a/python/docker_entrypoint.sh +++ b/python/docker_entrypoint.sh @@ -7,4 +7,5 @@ if [ "$API" = true ]; then sleep 1 fi -python3.12 main.py \ No newline at end of file +python3.12 start_discovery_server.py & +python3.12 main.py diff --git a/python/src/discovery.py b/python/src/ble_discovery.py similarity index 100% rename from python/src/discovery.py rename to python/src/ble_discovery.py diff --git a/python/src/find_gateways.py b/python/src/find_gateways.py index 2271f06..969c194 100644 --- a/python/src/find_gateways.py +++ b/python/src/find_gateways.py @@ -1,54 +1,75 @@ -from time import sleep -import socket -import FindMyIP -import ipaddress -import threading -import requests +# https://github.com/jholtmann/ip_discovery + 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 -max_threads = 50 -port = 8000 -final = {} +DISCOVERY_ACK = 'IP_DISCOVERY_ACK'.encode() # ACK for broadcast +DISCOVERY_RSP_GTW = 'IP_DISCOVERY_RSP_GTW'.encode() # RSP for gateway +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: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # TCP - # sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP - socket.setdefaulttimeout(2.0) # seconds (float) - result = sock.connect_ex((ip, port)) - if result == 0: final[ip] = True - else: final[ip] = False + sock.bind(server_address) + print("Started discovery socket") + while True: + data, addr = sock.recvfrom(4096) + print(f"Received a packet from {addr}") + 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() - except: - pass - -def scan_for_gateways(): +def start_discovery_client(): + 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 = local_ip.split('.')[:-1] - local_ip.append("0") - local_ip = '.'.join(local_ip) - print(f"Scan on {local_ip}/24 for port {port}") if DEBUG else {} + start_time_stamp = get_unix_time() + delta = round(get_unix_time() - start_time_stamp, 2) + discovered_devices = [] - for ip in ipaddress.IPv4Network(f'{local_ip}/24'): - threading.Thread(target=check_port, args=[str(ip), port]).start() - # limit the number of threads. - while threading.active_count() > max_threads: sleep(1) + try: + sock.bind(('', PORT_CLIENT)) + while True: + 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() diff --git a/python/src/helpers.py b/python/src/helpers.py new file mode 100644 index 0000000..e7aaafc --- /dev/null +++ b/python/src/helpers.py @@ -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(" ") diff --git a/python/src/loop.py b/python/src/loop.py index 561a624..d3625f5 100644 --- a/python/src/loop.py +++ b/python/src/loop.py @@ -1,6 +1,6 @@ from time import sleep 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): diff --git a/python/src/main.py b/python/src/main.py index 4561b4d..0f7ecac 100644 --- a/python/src/main.py +++ b/python/src/main.py @@ -1,5 +1,5 @@ import os -from discovery import start_discovery +from ble_discovery import start_discovery from log_data import log_to_json from loop import start_loop from check_update import check_for_update diff --git a/python/src/start_discovery_server.py b/python/src/start_discovery_server.py new file mode 100644 index 0000000..2eb9c21 --- /dev/null +++ b/python/src/start_discovery_server.py @@ -0,0 +1,2 @@ +from find_gateways import start_discovery_server +start_discovery_server()