LISHUZUOXUN_yangjiang/LSZXNetWork/network.py

312 lines
12 KiB
Python
Raw Normal View History

2024-09-23 14:54:15 +08:00
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)