import ping3 from ping3.errors import PingError import concurrent.futures from AcrossPlatform.get_platform import * from DeviceDefine.consensus import UNKNOWN, MANAGER, SLAVER from LSZXNetWork.NetworkDriverWin32.wifi_ap import get_self_ip_address from LSZXNetWork.encrypt import wifi_ap_name_generate, wifi_password_generate, SSID_HEAD # 根据平台导入对应的包 if SYS_PLATFORM == WINDOWS: from LSZXNetWork.NetworkDriverWin32 import wifi from LSZXNetWork.NetworkDriverWin32 import wifi_ap elif SYS_PLATFORM == LINUX: from LSZXNetWork.NetworkDriverLinux import wifi from LSZXNetWork.NetworkDriverLinux import wifi_ap import socket import threading import time import traceback # 定义数据包长度 DATA_LENGTH = 5 DEFAULT_MASTER_ADDRESS = "192.168.137.1" class Network: NETWORK_SERVER_PORT = 13131 NETWORK_CLIENT_PORT = 13132 def __init__(self, master_mode=True, device_type=UNKNOWN): super().__init__() # 设备类型 self.device_type = device_type self.ap = wifi_ap.WiFiAP() self.wifi = wifi.WIFI() self.ssid = wifi_ap_name_generate() self.master_mode = master_mode if master_mode: self.start_ap() self.master_ip = DEFAULT_MASTER_ADDRESS self.ip = "0.0.0.0" self.other_ip = {} self.device_lookup = {} self.connected_wifi_mes = None self.last_time = time.time() threading.Thread(target=self._threading_wifi_daemon, daemon=True).start() threading.Thread(target=self._threading_ip_assignment, daemon=True).start() threading.Thread(target=self._threading_ping, daemon=True).start() threading.Thread(target=self._threading_ip_sense, daemon=True).start() def get_ssid(self): return self.ssid def get_connected_wifi(self): wifi_mes = { "is_connected": self.wifi.wifi_connect_status(), "wifi_name": self.wifi.get_connected_wifi_name() } return wifi_mes def get_available_wifi(self): available_wifi = self.wifi.scan_wifi() available_wifi_name = [str(wifi) for wifi in available_wifi] available_wifi_name = list(filter(lambda s: SSID_HEAD in s, available_wifi_name)) available_wifi_name = list(set(available_wifi_name)) return available_wifi_name def start_ap(self): password = wifi_password_generate(self.ssid) self.ap.set_ssid(self.ssid) self.ap.set_password(password) self.ap.start() self.master_mode = True def stop_ap(self): self.ap.stop() self.master_mode = False def connect2wifi(self, ssid): self.stop_ap() self.wifi.wifi_device_initial() password = wifi_password_generate(ssid) self.connected_wifi_mes = (ssid, password) self.other_ip.clear() self.device_lookup.clear() return self.wifi.connect_wifi(ssid=ssid, password=password) def get_connected_wifi_name(self): return self.wifi.get_connected_wifi_name() def disconnect(self): self.connected_wifi_mes = None self.wifi.disconnect() def get_master_ip(self): return self.master_ip def get_self_ip(self): return self.ip def get_other(self): other_ip = list( filter( lambda ip: ip != self.ip, self.other_ip.keys() ) ) return other_ip def get_manager(self): manager_list = list( filter( lambda ip: self.device_lookup[ip] == MANAGER, self.device_lookup ) ) return manager_list def get_slaver(self): slaver_list = list( filter( lambda ip: self.device_lookup[ip] == SLAVER and ip != DEFAULT_MASTER_ADDRESS, self.device_lookup ) ) return slaver_list # wifi守护进程(当WiFi链接中断时,重新链接) def _threading_wifi_daemon(self): while True: try: if not self.master_mode and self.connected_wifi_mes: ssid, password = self.connected_wifi_mes if self.get_connected_wifi_name() != ssid: self.wifi.connect_wifi(ssid=ssid, password=password) except Exception as e: print(f"wifi守护出错,错误原因:{e.args},\n{traceback.format_exc()}") time.sleep(1) time.sleep(3) @staticmethod def ping_task(ip): try: ping3.ping(ip, timeout=30, unit="ms", size=1) except PingError: return # 尝试ping网段下所有网络,保证设备正常识别 def network_discover(self): ping_pool_num = 16 self_ip = get_self_ip_address() base_segments = self_ip.split(".")[0:3] # 创建一个线程池,最大线程数为ping_pool_num with concurrent.futures.ThreadPoolExecutor(max_workers=ping_pool_num) as executor: # 提交任务到线程池 for i in range(2, 255): ip = ".".join(base_segments + [str(i)]) executor.submit(self.ping_task, ip) def _threading_ping(self): while True: # 尝试ping通主机网络下其他设备。 self.network_discover() # 每隔30秒打印网络信息。 if time.time() - self.last_time > 30: self.last_time = time.time() print( "@网络成员打印:", "SELF", self.get_self_ip(), "MASTER", self.get_master_ip(), "SLAVER", self.get_slaver(), "MANAGER", self.get_manager(), "OTHERS", self.get_other(), ) # print(self.device_lookup) time.sleep(1) def _threading_ip_assignment(self): while True: try: # 获取当前设备中其他设备 ip_list = wifi_ap.get_machine_ip_address() # 获取自身ip self_ip = wifi_ap.get_self_ip_address() # 从机IP slaver_ip = ip_list.copy() if not ip_list: continue self.ip = self_ip # 标记已知的各类IP的标签 self.other_ip = { ip: int(self.device_lookup.get(ip)).to_bytes(length=1, byteorder="big", signed=False) if self.device_lookup.get(ip) else int(UNKNOWN).to_bytes(length=1, byteorder="big", signed=False) for ip in slaver_ip } # 对每一IP做类型广播 for ip in slaver_ip: ip_bytes = b"" ip_mes = ip.split(".") ip_bytes += b"".join([ int(seg).to_bytes(length=1, byteorder="big", signed=False) for seg in ip_mes ]) # 增加该IP类型 device_type = self.device_lookup.get(ip) if device_type: ip_bytes += int(device_type).to_bytes(length=1, byteorder="big", signed=False) else: ip_bytes += int(UNKNOWN).to_bytes(length=1, byteorder="big", signed=False) other_ips = ip_list.copy() for ip_mes in other_ips: ip_segment = b"".join([ int(seg).to_bytes(length=1, byteorder="big", signed=False) for seg in ip_mes.split(".") ]) # 添加设备类型 device_type = self.device_lookup.get(ip_mes) if device_type: ip_segment += int(device_type).to_bytes(length=1, byteorder="big", signed=False) else: ip_segment += int(UNKNOWN).to_bytes(length=1, byteorder="big", signed=False) ip_bytes += ip_segment try: client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.bind((self.ip, 0)) client.settimeout(1) client.connect((ip, Network.NETWORK_SERVER_PORT)) client.send(ip_bytes) device_type = client.recv(1) client.close() # 更新设备类型 self.device_lookup[ip] = int.from_bytes(device_type, signed=False, byteorder="big") self.other_ip[ip] = int.from_bytes(device_type, signed=False, byteorder="big") except ConnectionAbortedError or ConnectionRefusedError or ConnectionResetError: continue except socket.timeout: continue except ConnectionError: continue except OSError: continue except Exception as e: print(f"WiFi分配出错,错误原因:{e.args},\n{traceback.format_exc()}") time.sleep(1) def _threading_ip_sense(self): tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_server.bind(("0.0.0.0", Network.NETWORK_SERVER_PORT)) tcp_server.listen(16) tcp_server.settimeout(1) while True: # 被动模式 # 等待客户端连接 try: conn, connected_addr = tcp_server.accept() conn: socket.socket conn.settimeout(1) while True: try: data = conn.recv(1024) if data: conn.send(int(self.device_type).to_bytes(length=1, byteorder="big", signed=False)) ip_seg = [data[i: i + DATA_LENGTH] for i in range(0, len(data), DATA_LENGTH)] self_ip = ".".join([ str(int(ip_mes)) for ip_mes in ip_seg[0][0: 4] ]) master_ip = ".".join([ str(int(ip_mes)) for ip_mes in ip_seg[-1][0: 4] ]) other_ips = [ ".".join([ str(int(ip_mes)) for ip_mes in ip[0: 4] ]) for ip in ip_seg[1:-1] ] others_device_type = [ ip[4] for ip in ip_seg[1:-1] ] new_other_ip = { other_ips[i]: self.other_ip.get(other_ips[i]) if others_device_type[i] == UNKNOWN and other_ips[i] in self.other_ip.keys() else int(others_device_type[i]) for i in range(len(other_ips)) } self.other_ip.update(new_other_ip) else: break except socket.timeout: continue except socket.timeout: continue except ConnectionResetError: continue except Exception as e: # print(f"WiFi感知出错,错误原因:{e.args},\n{traceback.format_exc()}") tcp_server.close() tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_server.bind(("0.0.0.0", Network.NETWORK_SERVER_PORT)) tcp_server.listen(16) tcp_server.settimeout(1)