diff --git a/README.md b/README.md index f0913de..b1292f6 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,27 @@ Linux嵌入板卡发出热点供客户端连接,客户端通过浏览器访问热点,连接到Linux嵌入板卡的热点,并进行交互。 +- 连接逻辑: + 1. 检测 Wi-Fi 连接状态,若已连接,则退出程序 + 2. 扫描 Wi-Fi 网络并获取Wi-Fi列表 + 3. 关闭Wi-Fi,并启动热点和web服务器 + 4. 等待用户选择 Wi-Fi 网络并输入密码 + 5. 关闭热点并重新扫描 Wi-Fi,连接到用户选择的 Wi-Fi 网络 + +1. 扫描Wi-Fi,并将Wi-Fi list保存为json格式,存储在本地,命名为`scaned_wifi_list.json`; +2. 检查Wi-Fi连接状态,若已连接,则退出程序; +3. 关闭Wi-Fi,并启动热点和web服务器,web服务器监听80端口,并提供一个页面,页面中包含Wi-Fi列表; +4. 等待用户选择 Wi-Fi 网络并输入密码,并连接到用户选择的 Wi-Fi 网络; +5. 如果Wi-Fi连接成功,则显示Wi-Fi连接成功页面,并提供交互页面; +6. 如果Wi-Fi连接失败,则重新扫描Wi-Fi,并提示用户重新连接. + ### 环境准备 #### (1) 安装依赖项: ``` sudo apt-get update -sudo apt-get install hostapd dnsmasq +sudo apt-get install -y hostapd dnsmasq ``` #### (2) 克隆项目到本地并安装依赖: @@ -31,6 +45,62 @@ sudo pip install flask psutil #### (4) 配置开机自启动服务项: +##### (4.1) 配置WiFi热点服务项: + + +1. 创建一个service文件: + +``` +sudo vim /etc/systemd/system/hotspot.service +``` + +2. 在打开的文件中,添加以下内容: + +``` +[Unit] +Description=Hotspot Service +After=network.target + +[Service] +ExecStart=create_ap wlan0 eth0 Takway-Toys --no-virt +User=root + +[Install] +WantedBy=multi-user.target +``` + +请确保将`wlan0`替换为你的无线网卡接口,将`eth0`替换为你的有线网卡接口,`Takway-Toys`替换为你想要设置的热点名称。 + +3. 保存并关闭文件。 + +4. 重新加载systemd配置: + +``` +sudo systemctl daemon-reload +``` + +5. 启用并启动Hotspot service: + +``` +# sudo systemctl enable hotspot.service +sudo systemctl start hotspot.service +``` + + +6. 如果需要停止Hotspot service,可以使用以下命令: + +``` +sudo systemctl stop hotspot.service +``` + +7. 如果需要查看Hotspot service的状态: + +``` +sudo systemctl status hotspot.service +``` + +##### (4.2) 配置WiFi热点管理服务项: + - 编辑 ``` @@ -76,4 +146,43 @@ sudo systemctl status wifi_hotspot.service - 手动连接`http://192.168.12.1/` -- 连接成功后,输入用户名密码,即可进入交互界面。 \ No newline at end of file +- 连接成功后,输入用户名密码,即可进入交互界面。 + + + +## 其他参考命令 + +- 创建热点: + +``` +sudo systemctl start hotspot.service +``` + +- 关闭热点: + +``` +sudo systemctl stop hotspot.service +``` + +- 开启Wi-Fi连接: + +``` +nmcli dev wifi connect Innoxsz-Public password innox2023 +``` + +- 断开Wi-Fi连接: + +``` +nmcli dev disconnect iface wlan0 +``` + +- 扫描Wi-Fi: + +``` +nmcli dev wifi +``` + +- 检查Wi-Fi连接状态: +``` +nmcli dev status +``` diff --git a/wifi_manager.py b/wifi_manager.py index 65eebc0..a01efa8 100644 --- a/wifi_manager.py +++ b/wifi_manager.py @@ -1,10 +1,3 @@ -# 逻辑: -# 1. 检测 Wi-Fi 连接状态,若已连接,则退出程序 -# 2. 扫描 Wi-Fi 网络并获取Wi-Fi列表 -# 3. 关闭Wi-Fi,并启动热点和web服务器 -# 4. 等待用户选择 Wi-Fi 网络并输入密码 -# 5. 关闭热点并重新扫描 Wi-Fi,连接到用户选择的 Wi-Fi 网络 - import subprocess import re import os @@ -23,6 +16,7 @@ except ImportError: print("Error importing OrangePi") +app = Flask(__name__) def close_app(): if led_enabled: @@ -40,9 +34,23 @@ def close_app(): for pid in python_pids: os.kill(pid, signal.SIGTERM) +def start_hotspot(): + try: + subprocess.Popen('sudo systemctl start hotspot.service', shell=True) + if led_enabled: + orangepi.set_led_on('blue') + except subprocess.CalledProcessError as e: + print(f"{datetime.datetime.now()}: Error starting create_ap service: {e}") -app = Flask(__name__) - +def close_hotspot(): + # 关闭热点 + try: + subprocess.Popen('sudo systemctl stop hotspot.service', shell=True) + print(f"{datetime.datetime.now()}: Stopping create_ap service") + except subprocess.CalledProcessError as e: + print(f"{datetime.datetime.now()}: Error stopping hotspot: {e}") + + # 检测 Wi-Fi 连接状态 def check_wifi_connection(): cmd = "nmcli dev status" @@ -54,105 +62,141 @@ def check_wifi_connection(): columns = line.split() print(columns) if len(columns) >= 4 and columns[2] == "connected": + wifi_ssid = columns[3] if led_enabled: orangepi.set_led_off('blue') - return True + return True, wifi_ssid return False -def restart_hotspot(): - try: - # sudo systemctl stop dnsmasq - # sudo systemctl restart NetworkManager - # sudo nmcli radio wifi off - # sudo nmcli radio wifi on - # nohup sudo create_ap wlan0 eth0 Takway-Toys --no-virt > create_ap.log 2>&1 & - subprocess.run(['sudo', 'systemctl', 'stop', 'dnsmasq'], check=True) - subprocess.run(['sudo', 'systemctl', 'restart', 'NetworkManager'], check=True) - subprocess.run(['sudo', 'nmcli', 'radio', 'wifi', 'off'], check=True) - subprocess.run(['sudo', 'nmcli', 'radio', 'wifi', 'on'], check=True) - subprocess.Popen('sudo nohup create_ap wlan0 eth0 Takway-Toys --no-virt > create_ap.log 2>&1 &', shell=True) - if led_enabled: - orangepi.set_led_on('blue') - except subprocess.CalledProcessError as e: - print(f"{datetime.datetime.now()} Error stopping create_ap hotspot service: {e}") - - def scan_wifi(): - try: - subprocess.run(['nmcli', 'dev', 'wifi', 'rescan'], check=True) - time.sleep(1) - output = subprocess.check_output(['nmcli', 'dev', 'wifi']) - wifi_list = [] - lines = output.decode().splitlines() - for idx, line in enumerate(lines[1:]): - print(f"{idx}: {line}") - - # 分割字符串以空格为分隔符 - columns = line.split() + subprocess.run(['nmcli', 'dev', 'wifi', 'rescan'], check=True) + cmd = "nmcli dev wifi" + output = subprocess.run(cmd, shell=True, capture_output=True, text=True) + + wifi_list = [] + output = result.stdout.strip() + lines = output.split("\n")[1:] # Skip the header line + for line in lines: + columns = line.split() + print(columns) + for i, column in enumerate(columns): + print(f"{i}: {column}") + exit() + ''' + # 分割字符串以空格为分隔符 + columns = line.split() - # 提取第一列和第三列的值 - mac_address = columns[0] - - ssid = " ".join(columns[1:3]) - if "Infra" in ssid: - ssid = ssid.replace(" Infra", "") - if ":" in ssid: - # "72:A6:CC:8C:89:6C Takway-AI" - # 去除字符串中的MAC地址 - ssid = re.sub(r'\b\w{2}(:\w{2}){5}\b', '', ssid) - - # 提取第六列的强度值 - last_info = columns[4:8] - # 去除所有的空格 - columns = line.replace(" ", "") - # 提取"Mbit/s"后的三位以内数字 - strength = int(columns[columns.index("Mbit/s")+6:columns.index("Mbit/s")+8]) - - - # print("MAC地址:", mac_address) - # print("SSID:", ssid) - # print("强度:", strength) - - wifi_list.append({'ssid': ssid, 'signal': strength}) - if len(wifi_list) == 15: - break + # 提取第一列和第三列的值 + mac_address = columns[0] - # save wifi_list to file - with open('wifi_list.txt', 'w') as f: - for wifi in wifi_list: - f.write(f"{wifi['ssid']},{wifi['signal']}\n") - - return wifi_list - except subprocess.CalledProcessError as e: - print(f"{datetime.datetime.now()}: Error scanning for Wi-Fi networks: {e}") - return [] + ssid = " ".join(columns[1:3]) + if "Infra" in ssid: + ssid = ssid.replace(" Infra", "") + if ":" in ssid: + # "72:A6:CC:8C:89:6C Takway-AI" + # 去除字符串中的MAC地址 + ssid = re.sub(r'\b\w{2}(:\w{2}){5}\b', '', ssid) + # 提取第六列的强度值 + last_info = columns[4:8] + # 去除所有的空格 + columns = line.replace(" ", "") + # 提取"Mbit/s"后的三位以内数字 + strength = int(columns[columns.index("Mbit/s")+6:columns.index("Mbit/s")+8]) + + # print("MAC地址:", mac_address) + # print("SSID:", ssid) + # print("强度:", strength) + + wifi_list.append({'ssid': ssid, 'signal': strength}) + if len(wifi_list) == 15: + break + ''' + # save wifi_list to file + with open('wifi_list.txt', 'w') as f: + for wifi in wifi_list: + f.write(f"{wifi['ssid']},{wifi['signal']}\n") + + return wifi_list + +''' +def scan_wifi(): + subprocess.run(['nmcli', 'dev', 'wifi', 'rescan'], check=True) + cmd = "nmcli dev wifi" + output = subprocess.run(cmd, shell=True, capture_output=True, text=True) + + wifi_list = [] + lines = output.decode().splitlines() + for idx, line in enumerate(lines[1:]): + print(f"{idx}: {line}") + + # 分割字符串以空格为分隔符 + columns = line.split() + + # 提取第一列和第三列的值 + mac_address = columns[0] + + ssid = " ".join(columns[1:3]) + if "Infra" in ssid: + ssid = ssid.replace(" Infra", "") + if ":" in ssid: + # "72:A6:CC:8C:89:6C Takway-AI" + # 去除字符串中的MAC地址 + ssid = re.sub(r'\b\w{2}(:\w{2}){5}\b', '', ssid) + + # 提取第六列的强度值 + last_info = columns[4:8] + # 去除所有的空格 + columns = line.replace(" ", "") + # 提取"Mbit/s"后的三位以内数字 + strength = int(columns[columns.index("Mbit/s")+6:columns.index("Mbit/s")+8]) + + # print("MAC地址:", mac_address) + # print("SSID:", ssid) + # print("强度:", strength) + + wifi_list.append({'ssid': ssid, 'signal': strength}) + if len(wifi_list) == 15: + break + + # save wifi_list to file + with open('wifi_list.txt', 'w') as f: + for wifi in wifi_list: + f.write(f"{wifi['ssid']},{wifi['signal']}\n") + + return wifi_list +''' # 连接 Wi-Fi def connect_wifi(ssid, password): - # 关闭热点 - try: - subprocess.run(['sudo', 'create_ap', '--stop', 'wlan0'], check=True) - print(f"{datetime.datetime.now()}: Stopping create_ap service") - except subprocess.CalledProcessError as e: - print(f"{datetime.datetime.now()}: Error stopping hotspot: {e}") - - time.sleep(1) - - # 扫描 Wi-Fi 网络 - # scan_wifi() - - time.sleep(1) - # 连接到用户选择的 Wi-Fi 网络 try: - subprocess.run(['nmcli', 'dev', 'wifi', 'connect', ssid, 'password', password], check=True) - print(f"{datetime.datetime.now()}: Successfully connected to Wi-Fi: {ssid}") - return True + output = subprocess.check_output(['nmcli', 'dev', 'wifi', 'connect', ssid, 'password', password]) + output_str = output.decode('utf-8') # 将输出转换为字符串 + if "successfully" in output_str: + print(f"{datetime.datetime.now()}: Successfully connected to Wi-Fi: {ssid}") + return True + else: + print(f"{datetime.datetime.now()}: Error connecting to Wi-Fi: {output_str}") + return False except subprocess.CalledProcessError as e: print(f"{datetime.datetime.now()}: Error connecting to Wi-Fi: {e}") return False - + +# 关闭 Wi-Fi +def disconnect_wifi(): + try: + output = subprocess.check_output(['nmcli', 'dev', 'disconnect', 'iface', 'wlan0']) + output_str = output.decode('utf-8') # 将输出转换为字符串 + if "successfully disconnected" in output_str: + return True + except subprocess.CalledProcessError as e: + pass # 处理命令执行错误 + return False + + + + # 主页 @app.route('/') def index(): @@ -190,16 +234,18 @@ def submit(): if __name__ == '__main__': debug_mode = False # 设置为 True 以跳过 Wi-Fi 连接状态检测 + if debug_mode: + disconnect_wifi() if led_enabled: orangepi.set_led_on('blue') - if not debug_mode: - time.sleep(5) # 等待 Wi-Fi 连接 - if check_wifi_connection(): - print(f"{datetime.datetime.now()}: 系统已自动连接到 Wi-Fi 网络,退出程序") - close_app() - else: - print(f"{datetime.datetime.now()}: 未连接到 Wi-Fi 网络") + + + if check_wifi_connection(): + print(f"{datetime.datetime.now()}: 系统已自动连接到 Wi-Fi 网络,退出程序") + close_app() + else: + print(f"{datetime.datetime.now()}: 未连接到 Wi-Fi 网络") print(f"{datetime.datetime.now()}: Starting Flask server") print("----------------------------")