Files

362 lines
14 KiB
Python

from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
QLineEdit, QTextEdit, QGroupBox, QFormLayout, QComboBox,
QGridLayout, QMessageBox, QSpinBox, QCheckBox)
from PyQt5.QtCore import Qt, pyqtSlot, QTimer
import serial.tools.list_ports
import os
import json
import time
class SettingsTab(QWidget):
def __init__(self, lte_manager):
"""初始化设置标签页"""
super().__init__()
self.lte_manager = lte_manager
self.settings = {}
self.settings_file = os.path.join(os.path.expanduser('~'), '.LTE', 'settings.json')
# 加载设置
self.settings = {
"at_port": "",
"at_baudrate": "115200",
"nmea_port": "None",
"nmea_baudrate": "9600",
"auto_connect": False
}
self.load_settings()
# 初始化UI
self.init_ui()
# 注册状态变化的信号处理
self.lte_manager.status_changed.connect(self.on_status_changed)
# 如果启用了自动连接,尝试连接
if self.settings.get("auto_connect", False):
QTimer.singleShot(1000, self.try_auto_connect)
def init_ui(self):
"""初始化用户界面"""
main_layout = QVBoxLayout()
self.setLayout(main_layout)
# 端口设置组
port_group = QGroupBox("端口设置")
port_layout = QFormLayout()
# AT端口
at_port_layout = QHBoxLayout()
self.at_port_combo = QComboBox()
at_port_layout.addWidget(self.at_port_combo)
self.refresh_ports_button = QPushButton("刷新")
self.refresh_ports_button.clicked.connect(self.refresh_ports)
at_port_layout.addWidget(self.refresh_ports_button)
port_layout.addRow("AT Port:", at_port_layout)
# AT波特率
self.at_baudrate_combo = QComboBox()
self.at_baudrate_combo.addItems(["9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"])
self.at_baudrate_combo.setCurrentText(self.settings["at_baudrate"]) # 从保存的设置设置
port_layout.addRow("AT Baudrate:", self.at_baudrate_combo)
# NMEA端口
nmea_port_layout = QHBoxLayout()
self.nmea_port_combo = QComboBox()
self.nmea_port_combo.addItem("None")
nmea_port_layout.addWidget(self.nmea_port_combo)
port_layout.addRow("NMEA Port:", nmea_port_layout)
# NMEA波特率
self.nmea_baudrate_combo = QComboBox()
self.nmea_baudrate_combo.addItems(["4800", "9600", "19200", "38400", "57600", "115200"])
self.nmea_baudrate_combo.setCurrentText(self.settings["nmea_baudrate"]) # 从保存的设置设置
port_layout.addRow("NMEA Baudrate:", self.nmea_baudrate_combo)
# 自动连接复选框
self.auto_connect_checkbox = QCheckBox("自动连接")
self.auto_connect_checkbox.setChecked(self.settings.get("auto_connect", False))
self.auto_connect_checkbox.stateChanged.connect(self.on_auto_connect_changed)
port_layout.addRow("启动选项:", self.auto_connect_checkbox)
# 刷新端口列表
self.refresh_ports()
# 连接/断开按钮
buttons_layout = QHBoxLayout()
self.connect_button = QPushButton("连接")
self.connect_button.clicked.connect(self.on_connect_button_clicked)
buttons_layout.addWidget(self.connect_button)
self.disconnect_button = QPushButton("断开")
self.disconnect_button.clicked.connect(self.on_disconnect_button_clicked)
self.disconnect_button.setEnabled(False)
buttons_layout.addWidget(self.disconnect_button)
port_layout.addRow("", buttons_layout)
port_group.setLayout(port_layout)
main_layout.addWidget(port_group)
# 模块信息组
module_group = QGroupBox("模块信息")
module_layout = QVBoxLayout()
# 添加信息文本显示区域
self.info_text = QTextEdit()
self.info_text.setReadOnly(True)
self.info_text.setMinimumHeight(150)
module_layout.addWidget(self.info_text)
# 刷新按钮
self.refresh_info_button = QPushButton("刷新信息")
self.refresh_info_button.clicked.connect(self.refresh_module_info)
self.refresh_info_button.setEnabled(False)
module_layout.addWidget(self.refresh_info_button)
module_group.setLayout(module_layout)
main_layout.addWidget(module_group)
# AT命令控制台
console_group = QGroupBox("AT命令控制台")
console_layout = QVBoxLayout()
# 命令输入
command_layout = QHBoxLayout()
self.command_input = QLineEdit()
self.command_input.setPlaceholderText("输入AT命令")
command_layout.addWidget(self.command_input)
self.send_command_button = QPushButton("发送")
self.send_command_button.clicked.connect(self.on_send_command_button_clicked)
self.send_command_button.setEnabled(False)
command_layout.addWidget(self.send_command_button)
console_layout.addLayout(command_layout)
# 响应显示
console_layout.addWidget(QLabel("响应:"))
self.response_display = QTextEdit()
self.response_display.setReadOnly(True)
console_layout.addWidget(self.response_display)
console_group.setLayout(console_layout)
main_layout.addWidget(console_group)
# 状态显示
self.status_display = QTextEdit()
self.status_display.setReadOnly(True)
self.status_display.setMaximumHeight(100)
main_layout.addWidget(QLabel("状态:"))
main_layout.addWidget(self.status_display)
def get_available_ports(self):
"""Get list of available serial ports"""
ports = []
for port in serial.tools.list_ports.comports():
ports.append(port.device)
return ports
def refresh_ports(self):
"""Refresh available serial ports"""
self.at_port_combo.clear()
self.nmea_port_combo.clear()
self.nmea_port_combo.addItem("None")
ports = self.get_available_ports()
for port in ports:
self.at_port_combo.addItem(port)
self.nmea_port_combo.addItem(port)
# Set saved ports if available
if self.settings["at_port"] in ports:
self.at_port_combo.setCurrentText(self.settings["at_port"])
if self.settings["nmea_port"] in ports or self.settings["nmea_port"] == "None":
self.nmea_port_combo.setCurrentText(self.settings["nmea_port"])
def on_connect_button_clicked(self):
"""Handle connect button click"""
at_port = self.at_port_combo.currentText()
at_baudrate = int(self.at_baudrate_combo.currentText())
nmea_port = self.nmea_port_combo.currentText()
if nmea_port == "None":
nmea_port = ""
nmea_baudrate = int(self.nmea_baudrate_combo.currentText())
# Save settings
self.settings["at_port"] = at_port
self.settings["at_baudrate"] = self.at_baudrate_combo.currentText()
self.settings["nmea_port"] = nmea_port if nmea_port else "None"
self.settings["nmea_baudrate"] = self.nmea_baudrate_combo.currentText()
self.settings["auto_connect"] = self.auto_connect_checkbox.isChecked()
self.save_settings()
if self.lte_manager.connect(at_port, at_baudrate, nmea_port, nmea_baudrate):
self.connect_button.setEnabled(False)
self.disconnect_button.setEnabled(True)
self.refresh_info_button.setEnabled(True)
self.send_command_button.setEnabled(True)
self.add_status_message("Connected to LTE module")
self.refresh_module_info()
else:
self.add_status_message("Failed to connect to LTE module")
def on_disconnect_button_clicked(self):
"""Handle disconnect button click"""
self.lte_manager.disconnect()
self.connect_button.setEnabled(True)
self.disconnect_button.setEnabled(False)
self.refresh_info_button.setEnabled(False)
self.send_command_button.setEnabled(False)
self.add_status_message("Disconnected from LTE module")
# Reset module information
self.info_text.clear()
self.refresh_info_button.setEnabled(False)
def on_send_command_button_clicked(self):
"""Handle send command button click"""
command = self.command_input.text().strip()
if not command:
return
self.add_status_message(f"Sending command: {command}")
response = self.lte_manager.send_at_command(command)
self.response_display.setText(response)
self.command_input.clear()
def refresh_module_info(self):
"""刷新模块信息显示"""
if not self.lte_manager.is_connected():
self.add_status_message("请先连接模块")
return
try:
self.info_text.clear()
self.add_status_message("正在获取模块信息...")
# 获取模块信息
module_info = self.lte_manager.get_module_info()
if not module_info:
self.add_status_message("获取模块信息失败")
return
# 显示模块信息
self.info_text.append("<b>模块信息:</b>")
for key, value in module_info.items():
if value: # 只显示有值的项目
self.info_text.append(f"<b>{key}:</b> {value}")
# 获取运营商信息
carrier_info = self.lte_manager.get_carrier_info()
if carrier_info:
if isinstance(carrier_info, tuple) and len(carrier_info) == 2:
carrier, network = carrier_info
self.info_text.append(f"<b>运营商:</b> {carrier}")
self.info_text.append(f"<b>网络类型:</b> {network}")
else:
self.info_text.append(f"<b>运营商:</b> {carrier_info}")
# 获取电话号码
phone_number = self.lte_manager.get_phone_number()
if phone_number:
self.info_text.append(f"<b>电话号码:</b> {phone_number}")
# 获取信号强度
signal_info = self.lte_manager.get_signal_strength()
if signal_info:
if isinstance(signal_info, tuple) and len(signal_info) == 2:
signal_text, signal_desc = signal_info
self.info_text.append(f"<b>信号强度:</b> {signal_text} ({signal_desc})")
else:
self.info_text.append(f"<b>信号强度:</b> {signal_info}")
# 获取网络信息
network_info = self.lte_manager.get_network_info()
if network_info:
self.info_text.append("<b>网络信息:</b>")
for key, value in network_info.items():
if value: # 只显示有值的项目
self.info_text.append(f"<b>{key}:</b> {value}")
# 添加时间戳
self.info_text.append(f"<i>更新时间: {time.strftime('%Y-%m-%d %H:%M:%S')}</i>")
self.add_status_message("模块信息已更新")
except Exception as e:
self.add_status_message(f"刷新模块信息出错: {str(e)}")
import traceback
traceback.print_exc()
def on_status_changed(self, status):
"""Handle status change"""
self.add_status_message(status)
def add_status_message(self, message):
"""Add message to status display"""
self.status_display.append(message)
self.status_display.ensureCursorVisible()
def on_auto_connect_changed(self, state):
"""Handle auto connect checkbox state change"""
self.settings["auto_connect"] = bool(state)
self.save_settings()
def try_auto_connect(self):
"""Try to automatically connect using saved settings"""
if not self.settings.get("auto_connect", False):
return False
at_port = self.settings.get("at_port", "")
if not at_port:
self.add_status_message("Auto-connect: No saved port")
return False
# Check if the saved port is available
available_ports = self.get_available_ports()
if at_port not in available_ports:
self.add_status_message(f"Auto-connect: Port {at_port} not available")
return False
# Get other settings
at_baudrate = int(self.settings.get("at_baudrate", "115200"))
nmea_port = self.settings.get("nmea_port", "None")
if nmea_port == "None":
nmea_port = ""
nmea_baudrate = int(self.settings.get("nmea_baudrate", "9600"))
# Try to connect
self.add_status_message(f"Auto-connect: Trying to connect to {at_port}")
if self.lte_manager.connect(at_port, at_baudrate, nmea_port, nmea_baudrate):
self.connect_button.setEnabled(False)
self.disconnect_button.setEnabled(True)
self.refresh_info_button.setEnabled(True)
self.send_command_button.setEnabled(True)
self.add_status_message("Auto-connect: Connected to LTE module")
self.refresh_module_info()
return True
else:
self.add_status_message("Auto-connect: Failed to connect")
return False
def load_settings(self):
"""Load settings from file"""
try:
if os.path.exists(self.settings_file):
with open(self.settings_file, 'r') as f:
loaded_settings = json.load(f)
# Update settings with loaded values
for key, value in loaded_settings.items():
self.settings[key] = value
except Exception as e:
print(f"Error loading settings: {str(e)}")
def save_settings(self):
"""Save settings to file"""
try:
with open(self.settings_file, 'w') as f:
json.dump(self.settings, f, indent=4)
except Exception as e:
print(f"Error saving settings: {str(e)}")