优化了ai个零件库

This commit is contained in:
2025-07-25 16:39:32 +08:00
parent 9fc6b4577a
commit 47e0b8419f
17 changed files with 480 additions and 102 deletions

View File

@@ -2,19 +2,13 @@ import requests
from packaging.version import parse as vparse
def check_update(local_version, repo="goldenfishs/MRobot"):
"""
检查 GitHub 上是否有新版本
:param local_version: 当前版本号字符串,如 "1.0.2"
:param repo: 仓库名,格式 "用户名/仓库名"
:return: 最新版本号字符串(如果有新版本),否则 None
"""
url = f"https://api.github.com/repos/{repo}/releases/latest"
try:
resp = requests.get(url, timeout=5)
if resp.status_code == 200:
latest = resp.json()["tag_name"].lstrip("v")
if vparse(latest) > vparse(local_version):
return latest
except Exception as e:
print(f"检查更新失败: {e}")
return None
resp = requests.get(url, timeout=5)
if resp.status_code == 200:
latest = resp.json()["tag_name"].lstrip("v")
if vparse(latest) > vparse(local_version):
return latest
else:
return None
else:
raise RuntimeError("GitHub API 请求失败")

View File

@@ -0,0 +1,45 @@
from PyQt5.QtCore import QThread, pyqtSignal
import requests
import shutil
import os
from urllib.parse import quote
class DownloadThread(QThread):
progressChanged = pyqtSignal(int)
finished = pyqtSignal(list, list) # success, fail
def __init__(self, files, server_url, secret_key, local_dir, parent=None):
super().__init__(parent)
self.files = files
self.server_url = server_url
self.secret_key = secret_key
self.local_dir = local_dir
def run(self):
success, fail = [], []
total = len(self.files)
max_retry = 3
for idx, rel_path in enumerate(self.files):
retry = 0
while retry < max_retry:
try:
rel_path_unix = rel_path.replace("\\", "/")
encoded_path = quote(rel_path_unix)
url = f"{self.server_url}/download/{encoded_path}"
params = {"key": self.secret_key}
resp = requests.get(url, params=params, stream=True, timeout=10)
if resp.status_code == 200:
local_path = os.path.join(self.local_dir, rel_path)
os.makedirs(os.path.dirname(local_path), exist_ok=True)
with open(local_path, "wb") as f:
shutil.copyfileobj(resp.raw, f)
success.append(rel_path)
break
else:
retry += 1
except Exception:
retry += 1
else:
fail.append(rel_path)
self.progressChanged.emit(int((idx + 1) / total * 100))
self.finished.emit(success, fail)

114
app/tools/task_config.py Normal file
View File

@@ -0,0 +1,114 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout
from qfluentwidgets import TitleLabel, BodyLabel, TableWidget, PushButton, SubtitleLabel, SpinBox, InfoBar, InfoBarPosition, LineEdit, CheckBox
from PyQt5.QtCore import Qt
import yaml
import os
class TaskConfigDialog(QDialog):
def __init__(self, parent=None, config_path=None):
super().__init__(parent)
self.setWindowTitle("任务配置")
self.resize(900, 480)
layout = QVBoxLayout(self)
layout.setContentsMargins(32, 32, 32, 32)
layout.setSpacing(18)
layout.addWidget(TitleLabel("FreeRTOS 任务配置"))
layout.addWidget(BodyLabel("请添加并配置您的任务参数,支持频率控制与描述。"))
self.table = TableWidget(self)
self.table.setColumnCount(6)
self.table.setHorizontalHeaderLabels(["任务名称", "运行频率", "初始化延迟", "堆栈大小", "任务描述", "频率控制"])
self.table.horizontalHeader().setSectionResizeMode(0, self.table.horizontalHeader().Stretch)
self.table.horizontalHeader().setSectionResizeMode(1, self.table.horizontalHeader().ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(2, self.table.horizontalHeader().ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(3, self.table.horizontalHeader().ResizeToContents)
self.table.horizontalHeader().setSectionResizeMode(4, self.table.horizontalHeader().Stretch)
self.table.horizontalHeader().setSectionResizeMode(5, self.table.horizontalHeader().ResizeToContents)
self.table.setMinimumHeight(260)
layout.addWidget(self.table)
btn_layout = QHBoxLayout()
self.add_btn = PushButton("添加任务")
self.del_btn = PushButton("删除选中")
self.ok_btn = PushButton("生成")
self.cancel_btn = PushButton("取消")
btn_layout.addWidget(self.add_btn)
btn_layout.addWidget(self.del_btn)
btn_layout.addStretch()
btn_layout.addWidget(self.ok_btn)
btn_layout.addWidget(self.cancel_btn)
layout.addLayout(btn_layout)
self.add_btn.clicked.connect(self.add_row)
self.del_btn.clicked.connect(self.del_row)
self.ok_btn.clicked.connect(self.accept)
self.cancel_btn.clicked.connect(self.reject)
# 自动读取配置文件
if config_path and os.path.exists(config_path):
try:
with open(config_path, "r", encoding="utf-8") as f:
tasks = yaml.safe_load(f)
if tasks:
for t in tasks:
self.add_row(t)
except Exception:
pass
def add_row(self, task=None):
row = self.table.rowCount()
self.table.insertRow(row)
name = LineEdit(task.get("name", f"Task{row+1}") if task else f"Task{row+1}")
freq = SpinBox()
freq.setRange(1, 10000)
freq.setValue(task.get("frequency", 500) if task else 500)
delay = SpinBox()
delay.setRange(0, 10000)
delay.setValue(task.get("delay", 0) if task else 0)
stack = SpinBox()
stack.setRange(128, 8192)
stack.setSingleStep(128)
stack.setValue(task.get("stack", 256) if task else 256)
desc = LineEdit(task.get("description", "") if task else "请填写任务描述")
freq_ctrl = CheckBox("启用")
freq_ctrl.setChecked(task.get("freq_control", True) if task else True)
self.table.setCellWidget(row, 0, name)
self.table.setCellWidget(row, 1, freq)
self.table.setCellWidget(row, 2, delay)
self.table.setCellWidget(row, 3, stack)
self.table.setCellWidget(row, 4, desc)
self.table.setCellWidget(row, 5, freq_ctrl)
def del_row(self):
selected = self.table.selectedItems()
if selected:
rows = set(item.row() for item in selected)
for row in sorted(rows, reverse=True):
self.table.removeRow(row)
def get_tasks(self):
tasks = []
for row in range(self.table.rowCount()):
name = self.table.cellWidget(row, 0).text().strip()
freq = self.table.cellWidget(row, 1).value()
delay = self.table.cellWidget(row, 2).value()
stack = self.table.cellWidget(row, 3).value()
desc = self.table.cellWidget(row, 4).text().strip()
freq_ctrl = self.table.cellWidget(row, 5).isChecked()
# 校验 stack 必须为 128*2^n
if stack < 128 or (stack & (stack - 1)) != 0 or stack % 128 != 0:
raise ValueError(f"{row+1}行任务“{name}”的堆栈大小必须为128、256、512、1024等128*2^n")
task = {
"name": name,
"function": f"Task_{name}",
"delay": delay,
"stack": stack,
"description": desc,
"freq_control": freq_ctrl
}
if freq_ctrl:
task["frequency"] = freq
tasks.append(task)
return tasks