Merge pull request '主线代码合入天煤分支' (#2) from master into tianmei-tech

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-04-21 16:27:02 +08:00
22 changed files with 11985 additions and 5 deletions

View File

@@ -148,6 +148,22 @@ if [ "$1" = "run" ]; then
exit 0 exit 0
fi fi
if [ "$1" = "enable_autostart" ]; then
enable_autostart
exit 0
fi
if [ "$1" = "disable_autostart" ]; then
disable_autostart
exit 0
fi
if [ "$1" = "status" ]; then
show_status
exit 0
fi
# 交互式主程序 # 交互式主程序
while true; do while true; do
show_menu show_menu

BIN
config/logos/logo.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1486
lj360_camera_keepalive.log Normal file

File diff suppressed because it is too large Load Diff

2
surround_config.json Normal file → Executable file
View File

@@ -4,5 +4,5 @@
"radar_unit": 0, "radar_unit": 0,
"show_radar": 1, "show_radar": 1,
"radar_alarm_dist": 15, "radar_alarm_dist": 15,
"display_mode": 0 "display_mode": 1
} }

384
temp.py Normal file
View File

@@ -0,0 +1,384 @@
import sys
import psutil
import time
from datetime import datetime
import csv
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout,
QWidget, QLabel, QPushButton, QFileDialog, QMessageBox)
from PyQt5.QtCore import QTimer, Qt, QPoint
from PyQt5.QtGui import QPainter, QPen, QColor, QFont, QBrush
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class CPUMonitor(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("CPU 监控")
self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
# 数据存储
self.cpu_percent_history = []
self.cpu_temp_history = []
self.max_history_length = 120 # 增加到120个数据点
self.logging_enabled = False
self.log_file = None
self.csv_writer = None
self.init_ui()
self.init_timer()
def init_ui(self):
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
layout.setSpacing(15)
layout.setContentsMargins(20, 20, 20, 20)
# 获取屏幕尺寸,设置为半个屏幕
screen_geometry = QApplication.primaryScreen().geometry()
screen_width = screen_geometry.width()
screen_height = screen_geometry.height()
# 设置为半个屏幕的大小
window_width = screen_width // 2
window_height = screen_height // 2
self.resize(window_width, window_height)
# 窗口居中
self.move(screen_width // 4, screen_height // 4)
# 顶部栏 (拖动用)
title_layout = QHBoxLayout()
title_label = QLabel("360环视 主板核心温度监控")
title_font = QFont("微软雅黑", 20, QFont.Bold)
title_label.setFont(title_font)
title_label.setStyleSheet("color: white; font-weight: bold;")
title_layout.addWidget(title_label)
# 关闭按钮
self.close_btn = QPushButton("")
self.close_btn.setFixedSize(50, 50)
close_font = QFont("微软雅黑", 24, QFont.Bold)
self.close_btn.setFont(close_font)
self.close_btn.setStyleSheet("""
QPushButton {
background-color: #e74c3c;
color: white;
border-radius: 10px;
}
QPushButton:hover {
background-color: #c0392b;
}
""")
self.close_btn.clicked.connect(self.close)
# 日志按钮
self.log_btn = QPushButton("开始记录")
self.log_btn.setFixedSize(150, 50)
log_font = QFont("微软雅黑", 16)
self.log_btn.setFont(log_font)
self.log_btn.setStyleSheet("""
QPushButton {
background-color: #3498db;
color: white;
border-radius: 10px;
}
QPushButton:hover {
background-color: #2980b9;
}
""")
self.log_btn.clicked.connect(self.toggle_logging)
title_layout.addStretch()
title_layout.addWidget(self.log_btn)
title_layout.addSpacing(10)
title_layout.addWidget(self.close_btn)
layout.addLayout(title_layout)
# 数据标签(大字号)
info_layout = QHBoxLayout()
# CPU使用率显示
cpu_frame = QWidget()
cpu_frame.setStyleSheet("background-color: rgba(0, 0, 0, 100); border-radius: 15px;")
cpu_layout = QVBoxLayout(cpu_frame)
cpu_title = QLabel("CPU 使用率")
cpu_title_font = QFont("微软雅黑", 18, QFont.Bold)
cpu_title.setFont(cpu_title_font)
cpu_title.setStyleSheet("color: #ecf0f1;")
cpu_layout.addWidget(cpu_title)
self.cpu_label = QLabel("--%")
self.cpu_label.setFont(QFont("微软雅黑", 48, QFont.Bold))
self.cpu_label.setStyleSheet("color: #2ecc71;")
self.cpu_label.setAlignment(Qt.AlignCenter)
cpu_layout.addWidget(self.cpu_label)
# 温度显示
temp_frame = QWidget()
temp_frame.setStyleSheet("background-color: rgba(0, 0, 0, 100); border-radius: 15px;")
temp_layout = QVBoxLayout(temp_frame)
temp_title = QLabel("CPU 温度")
temp_title.setFont(cpu_title_font)
temp_title.setStyleSheet("color: #ecf0f1;")
temp_layout.addWidget(temp_title)
self.temp_label = QLabel("--°C")
self.temp_label.setFont(QFont("微软雅黑", 48, QFont.Bold))
self.temp_label.setStyleSheet("color: #e67e22;")
self.temp_label.setAlignment(Qt.AlignCenter)
temp_layout.addWidget(self.temp_label)
info_layout.addWidget(cpu_frame)
info_layout.addSpacing(20)
info_layout.addWidget(temp_frame)
layout.addLayout(info_layout)
# 图形(更大尺寸)
self.figure = Figure(figsize=(12, 6), dpi=100, facecolor='#1e1e1e')
self.canvas = FigureCanvas(self.figure)
self.ax = self.figure.add_subplot(111)
self.ax.set_facecolor('#2d2d2d')
self.ax.spines['bottom'].set_color('white')
self.ax.spines['top'].set_color('white')
self.ax.spines['right'].set_color('white')
self.ax.spines['left'].set_color('white')
# 设置大字号
self.ax.tick_params(colors='white', labelsize=12)
self.ax.set_ylim(0, 100)
self.ax.set_xlim(0, self.max_history_length)
self.ax.set_title("CPU line", color='white', fontsize=20, fontweight='bold')
self.ax.set_xlabel("time (s)", color='white', fontsize=16)
self.ax.set_ylabel("number", color='white', fontsize=16)
# 绘制曲线
self.line, = self.ax.plot([], [], '#2ecc71', linewidth=3, label='CPU use (%)')
self.temp_line, = self.ax.plot([], [], '#e74c3c', linewidth=3, alpha=0.8, label='CPU temp (°C)')
# 图例
self.ax.legend(loc='upper right', facecolor='#2d2d2d', labelcolor='white',
fontsize=14, framealpha=0.9)
# 添加网格
self.ax.grid(True, alpha=0.3, color='white')
layout.addWidget(self.canvas)
# 状态栏
status_layout = QHBoxLayout()
self.status_label = QLabel("就绪")
self.status_label.setFont(QFont("微软雅黑", 12))
self.status_label.setStyleSheet("color: #bdc3c7;")
status_layout.addWidget(self.status_label)
status_layout.addStretch()
# 添加时间显示
self.time_label = QLabel("")
self.time_label.setFont(QFont("微软雅黑", 12))
self.time_label.setStyleSheet("color: #bdc3c7;")
status_layout.addWidget(self.time_label)
layout.addLayout(status_layout)
# 设置窗口样式
self.setStyleSheet("""
QMainWindow {
background-color: rgba(20, 20, 30, 220);
border: 2px solid #3498db;
border-radius: 15px;
}
QLabel {
background: transparent;
}
""")
def init_timer(self):
self.timer = QTimer()
self.timer.timeout.connect(self.update_monitor)
self.timer.start(1000) # 每秒更新
# 图形更新定时器
self.graph_timer = QTimer()
self.graph_timer.timeout.connect(self.update_graph)
self.graph_timer.start(500)
# 更新时间显示
self.time_timer = QTimer()
self.time_timer.timeout.connect(self.update_time)
self.time_timer.start(1000)
def update_time(self):
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.time_label.setText(current_time)
def get_cpu_temperature(self):
"""获取CPU温度"""
try:
temps = psutil.sensors_temperatures()
if not temps:
return None
for name in ['coretemp', 'cpu_thermal', 'k10temp', 'cpu-thermal']:
if name in temps:
return temps[name][0].current
for sensor in temps.values():
if sensor:
return sensor[0].current
return None
except:
return None
def update_monitor(self):
# 获取CPU使用率
cpu_percent = psutil.cpu_percent(interval=0.1)
self.cpu_label.setText(f"{cpu_percent:.1f}%")
# 根据使用率改变颜色
if cpu_percent < 80:
self.cpu_label.setStyleSheet("color: #2ecc71;")
elif cpu_percent < 95:
self.cpu_label.setStyleSheet("color: #f39c12;")
else:
self.cpu_label.setStyleSheet("color: #e74c3c;")
# 获取CPU温度
cpu_temp = self.get_cpu_temperature()
if cpu_temp is not None:
self.temp_label.setText(f"{cpu_temp:.1f}°C")
# 根据温度改变颜色
if cpu_temp < 60:
self.temp_label.setStyleSheet("color: #2ecc71;")
elif cpu_temp < 80:
self.temp_label.setStyleSheet("color: #f39c12;")
else:
self.temp_label.setStyleSheet("color: #e74c3c;")
else:
self.temp_label.setText("N/A")
# 保存数据
self.cpu_percent_history.append(cpu_percent)
self.cpu_temp_history.append(cpu_temp if cpu_temp is not None else 0)
# 保持历史长度
if len(self.cpu_percent_history) > self.max_history_length:
self.cpu_percent_history.pop(0)
self.cpu_temp_history.pop(0)
# 保存日志
if self.logging_enabled and self.csv_writer:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
temp_value = f"{cpu_temp:.1f}" if cpu_temp is not None else "N/A"
self.csv_writer.writerow([timestamp, f"{cpu_percent:.1f}", temp_value])
self.log_file.flush()
def update_graph(self):
"""更新图形"""
if not self.cpu_percent_history:
return
# 更新CPU使用率曲线
x_data = list(range(len(self.cpu_percent_history)))
self.line.set_data(x_data, self.cpu_percent_history)
# 更新温度曲线
if any(self.cpu_temp_history):
temp_data = [t if t is not None else 0 for t in self.cpu_temp_history]
self.temp_line.set_data(x_data, temp_data)
# 动态调整Y轴范围温度
max_temp = max(temp_data)
if max_temp > 0:
self.ax.set_ylim(0, max(100, max_temp + 10))
else:
self.temp_line.set_data([], [])
# 调整X轴范围
self.ax.set_xlim(0, max(self.max_history_length, len(self.cpu_percent_history)))
# 重绘
self.canvas.draw_idle()
def toggle_logging(self):
"""切换日志记录状态"""
if not self.logging_enabled:
default_filename = f"cpu_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
filepath, _ = QFileDialog.getSaveFileName(
self, "保存日志文件", default_filename, "CSV文件 (*.csv)"
)
if filepath:
try:
self.log_file = open(filepath, 'w', newline='', encoding='utf-8')
self.csv_writer = csv.writer(self.log_file)
self.csv_writer.writerow(['时间', 'CPU使用率(%)', 'CPU温度(°C)'])
self.logging_enabled = True
self.log_btn.setText("📝 记录中...")
self.log_btn.setStyleSheet("""
QPushButton {
background-color: #27ae60;
color: white;
border-radius: 10px;
}
QPushButton:hover {
background-color: #229954;
}
""")
self.status_label.setText(f"日志记录中: {os.path.basename(filepath)}")
QMessageBox.information(self, "日志记录", f"开始记录日志到:\n{filepath}")
except Exception as e:
QMessageBox.warning(self, "错误", f"无法创建日志文件:\n{str(e)}")
else:
self.logging_enabled = False
if self.log_file:
self.log_file.close()
self.log_file = None
self.csv_writer = None
self.log_btn.setText("📝 开始记录")
self.log_btn.setStyleSheet("""
QPushButton {
background-color: #3498db;
color: white;
border-radius: 10px;
}
QPushButton:hover {
background-color: #2980b9;
}
""")
self.status_label.setText("日志记录已停止")
QMessageBox.information(self, "日志记录", "日志记录已停止")
def mousePressEvent(self, event):
"""实现窗口拖动"""
if event.button() == Qt.LeftButton:
self.drag_position = event.globalPos() - self.frameGeometry().topLeft()
event.accept()
def mouseMoveEvent(self, event):
"""实现窗口拖动"""
if event.buttons() == Qt.LeftButton:
self.move(event.globalPos() - self.drag_position)
event.accept()
def closeEvent(self, event):
"""关闭时清理"""
if self.logging_enabled and self.log_file:
self.log_file.close()
event.accept()
def main():
app = QApplication(sys.argv)
window = CPUMonitor()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

10091
web.log Normal file

File diff suppressed because it is too large Load Diff

11
web.py
View File

@@ -293,6 +293,9 @@ class SerialWorker(threading.Thread):
buf.append(b) buf.append(b)
if len(buf) == 10: if len(buf) == 10:
self._parse_rx_frame(bytes(buf)) self._parse_rx_frame(bytes(buf))
print("[RX] active: {} radar: {} stopped: {} reverse: {}".format(
self._active_dirs, self._radar_dist, self._stopped, self._reverse))
buf.clear() buf.clear()
elif len(buf) > 10: elif len(buf) > 10:
buf.clear() buf.clear()
@@ -317,7 +320,7 @@ class RemoteSignals(QObject):
exit_settings = pyqtSignal() exit_settings = pyqtSignal()
class RemoteWorker(threading.Thread): class RemoteWorker(threading.Thread):
def __init__(self, port="/dev/ttyS3", baudrate=115200): def __init__(self, port="/dev/ttyS3", baudrate=9600):
super().__init__(daemon=True) super().__init__(daemon=True)
self.port = port self.port = port
self.baudrate = baudrate self.baudrate = baudrate
@@ -476,7 +479,7 @@ class BirdViewWorker(threading.Thread):
while self.running: while self.running:
self.frame_idx += 1 self.frame_idx += 1
if self.frame_idx % self.framestep != 0: if self.frame_idx % self.framestep != 0:
time.sleep(0.005) time.sleep(0.033)
continue continue
frames = [] frames = []
for name, model in zip(self.names, self.models): for name, model in zip(self.names, self.models):
@@ -490,7 +493,7 @@ class BirdViewWorker(threading.Thread):
print("[BIRD ERROR] {}".format(e)) print("[BIRD ERROR] {}".format(e))
break break
if len(frames) != 4: if len(frames) != 4:
time.sleep(0.01) time.sleep(0.033)
continue continue
try: try:
self.birdview.update_frames(frames) self.birdview.update_frames(frames)
@@ -670,7 +673,7 @@ class MultiCameraBirdView:
return return
self.caps = [] self.caps = []
self.which_cameras = {"front":0, "left":1, "back":2, "right":3} self.which_cameras = {"front":2, "left":3, "back":0, "right":1}
for name in self.names: for name in self.names:
cap_id = self.which_cameras.get(name, 0) cap_id = self.which_cameras.get(name, 0)
cap = cv2.VideoCapture(cap_id, cv2.CAP_V4L2) cap = cv2.VideoCapture(cap_id, cv2.CAP_V4L2)