312 lines
12 KiB
Python
312 lines
12 KiB
Python
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)
|