v1.0.7
parent
d385e770d1
commit
97dee8326b
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(python3 -c ' *)",
|
||||
"Bash(sqlite3 data.db \"PRAGMA table_info\\(task_instruction\\);\")",
|
||||
"Bash(venv/Scripts/python.exe -c ' *)",
|
||||
"Bash(venv/Scripts/python.exe -c \"import py_compile; py_compile.compile\\('taskForm.py', doraise=True\\)\")"
|
||||
]
|
||||
}
|
||||
}
|
||||
29
common.py
29
common.py
|
|
@ -915,7 +915,36 @@ class Common(QObject):
|
|||
# export_table_structure_and_data('data.db', 'task_group')
|
||||
# export_table_structure_and_data('data.db', 'task_instruction')
|
||||
# 导入表结构和数据
|
||||
def migrate_sql_to_database(self, db_path, table_name):
|
||||
import stat
|
||||
try:
|
||||
os.chmod(db_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||
except Exception:
|
||||
pass
|
||||
sql_file_path = f"{table_name}.sql"
|
||||
try:
|
||||
with open(sql_file_path, 'r', encoding='utf-8') as file:
|
||||
sql_script = file.read()
|
||||
except FileNotFoundError:
|
||||
return
|
||||
conn = sqlite3.connect(db_path)
|
||||
for stmt in sql_script.split(';'):
|
||||
stmt = stmt.strip()
|
||||
if not stmt:
|
||||
continue
|
||||
try:
|
||||
conn.execute(stmt)
|
||||
except sqlite3.Error:
|
||||
pass
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def import_sql_to_database(self,db_path, table_bame):
|
||||
import stat
|
||||
try:
|
||||
os.chmod(db_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
|
||||
except Exception:
|
||||
pass
|
||||
# 连接到SQLite数据库
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
|
|
|
|||
|
|
@ -704,11 +704,15 @@ class DevModelForm(QWidget):
|
|||
self.ui.textEditDescription.clear()
|
||||
groups = dmGroupManager.getInfo()
|
||||
self.dmGroupModelBlockSignals = True
|
||||
self.dmGroupModel.blockSignals(True)
|
||||
self.ui.tableViewDmGroup.setUpdatesEnabled(False)
|
||||
if len(groups) > 0:
|
||||
for group in groups:
|
||||
index = self.dmGroupModel.rowCount()
|
||||
self.dmGroupModel.setItem(index, 0, QStandardItem(str(group["id"])))
|
||||
self.dmGroupModel.setItem(index, 1, QStandardItem(group["name"]))
|
||||
self.dmGroupModel.blockSignals(False)
|
||||
self.ui.tableViewDmGroup.setUpdatesEnabled(True)
|
||||
self.dmGroupModelBlockSignals = False
|
||||
self.batchOperation()
|
||||
|
||||
|
|
@ -718,12 +722,16 @@ class DevModelForm(QWidget):
|
|||
self.devModelModel.clear()
|
||||
self.ui.textEditDescription.clear()
|
||||
if len(devModels) > 0:
|
||||
self.devModelModel.blockSignals(True)
|
||||
self.ui.tableViewModel.setUpdatesEnabled(False)
|
||||
for data in devModels:
|
||||
index = self.devModelModel.rowCount()
|
||||
self.devModelModel.setItem(index, 0, QStandardItem(str(data["id"])))
|
||||
self.devModelModel.setItem(index, 1, QStandardItem(str(index+1)))
|
||||
self.devModelModel.setItem(index, 2, QStandardItem(data["name"]))
|
||||
self.devModelModel.setItem(index, 3, QStandardItem(data["category"]))
|
||||
self.devModelModel.blockSignals(False)
|
||||
self.ui.tableViewModel.setUpdatesEnabled(True)
|
||||
self.ui.tableViewModel.sortByColumn(2, Qt.SortOrder.AscendingOrder)
|
||||
self.batchOperation()
|
||||
|
||||
|
|
@ -844,12 +852,13 @@ class DevModelForm(QWidget):
|
|||
self.batchOperation()
|
||||
|
||||
# 加载指令
|
||||
def loadInstruction(self,devModelId):
|
||||
def loadInstruction(self,devModelId):
|
||||
try:
|
||||
result = instructionManager.getDevmodelInstructions(devModelId)
|
||||
instructions = instructionManager.getDevmodelInstructions(devModelId)
|
||||
self.instructionModel.clear()
|
||||
self.ui.textEditDescription.setText("")
|
||||
instructions = result
|
||||
self.ui.textEditDescription.setText("")
|
||||
self.instructionModel.blockSignals(True)
|
||||
self.ui.tableViewCmd.setUpdatesEnabled(False)
|
||||
for data in instructions:
|
||||
index = self.instructionModel.rowCount()
|
||||
self.instructionModel.setItem(index, 0, QStandardItem(str(data["id"])))
|
||||
|
|
@ -866,6 +875,8 @@ class DevModelForm(QWidget):
|
|||
if "description" not in attr:
|
||||
attr["description"] = ""
|
||||
self.instructionModel.setItem(index, 5, QStandardItem(attr["description"]))
|
||||
self.instructionModel.blockSignals(False)
|
||||
self.ui.tableViewCmd.setUpdatesEnabled(True)
|
||||
self.ui.tableViewCmd.sortByColumn(2, Qt.SortOrder.AscendingOrder)
|
||||
self.batchOperation()
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -423,11 +423,13 @@ class DeviceForm(QWidget):
|
|||
self.updateDevBtnState()
|
||||
|
||||
# 加载设备
|
||||
def loadDevice(self):
|
||||
def loadDevice(self):
|
||||
devices = deviceManager.getGroupDevices(self.current_groupId)
|
||||
self.deviceModel.clear()
|
||||
self.ui.textEditDescription.clear()
|
||||
if len(devices) > 0:
|
||||
self.deviceModel.blockSignals(True)
|
||||
self.ui.tableViewDevice.setUpdatesEnabled(False)
|
||||
for device in devices:
|
||||
index = self.deviceModel.rowCount()
|
||||
self.deviceModel.setItem(index, 0, QxStandardItem(str(device["id"])))
|
||||
|
|
@ -437,7 +439,9 @@ class DeviceForm(QWidget):
|
|||
devModel = devModelManager.getInfo(device["dev_model_id"])
|
||||
if devModel != None:
|
||||
self.deviceModel.setItem(index, 4, QxStandardItem(devModel["name"], max_length=8))
|
||||
self.ui.tableViewDevice.sortByColumn(3, Qt.SortOrder.AscendingOrder)
|
||||
self.deviceModel.blockSignals(False)
|
||||
self.ui.tableViewDevice.setUpdatesEnabled(True)
|
||||
self.ui.tableViewDevice.sortByColumn(3, Qt.SortOrder.AscendingOrder)
|
||||
self.batchOperation()
|
||||
|
||||
# 任务分组选中
|
||||
|
|
@ -457,11 +461,15 @@ class DeviceForm(QWidget):
|
|||
self.ui.textEditDescription.clear()
|
||||
groups = devGroupManager.getInfo()
|
||||
self.devGroupModelBlockSignals = True
|
||||
self.devGroupModel.blockSignals(True)
|
||||
self.ui.tableViewDevGroup.setUpdatesEnabled(False)
|
||||
if len(groups) > 0:
|
||||
for group in groups:
|
||||
index = self.devGroupModel.rowCount()
|
||||
self.devGroupModel.setItem(index, 0, QStandardItem(str(group["id"])))
|
||||
self.devGroupModel.setItem(index, 1, QStandardItem(group["name"]))
|
||||
self.devGroupModel.blockSignals(False)
|
||||
self.ui.tableViewDevGroup.setUpdatesEnabled(True)
|
||||
self.devGroupModelBlockSignals = False
|
||||
self.batchOperation()
|
||||
|
||||
|
|
@ -741,20 +749,22 @@ class DeviceForm(QWidget):
|
|||
def loadDevInstruction(self,devModelId):
|
||||
instructions = instructionManager.getDevmodelInstructions(devModelId)
|
||||
self.devInstructionModel.clear()
|
||||
self.devInstructionModel.blockSignals(True)
|
||||
self.ui.tableViewDevCmd.setUpdatesEnabled(False)
|
||||
if instructions:
|
||||
self.ui.tableViewDevCmd.setItemDelegateForColumn(5, ProgressBarDelegate())
|
||||
for data in instructions:
|
||||
index = self.devInstructionModel.rowCount()
|
||||
self.devInstructionModel.setItem(index, 0, QxStandardItem(str(data["id"])))
|
||||
self.devInstructionModel.setItem(index, 1, QxStandardItem(str(index+1)))
|
||||
self.devInstructionModel.setItem(index, 2, QxStandardItem(data["name"]))
|
||||
attr = data["attr"]
|
||||
|
||||
if data["type"] is not None and data["type"] in self.supportedTypes:
|
||||
self.devInstructionModel.setItem(index, 3, QxStandardItem(attr[self.supportedTypes[data["type"]]["digestAttr"]]))
|
||||
else:
|
||||
self.devInstructionModel.setItem(index, 3, QxStandardItem(""))
|
||||
self.devInstructionModel.setItem(index, 4, QxStandardItem(attr["remark"]))
|
||||
progressItem = QxProgressStandardItem('',self)
|
||||
# 从全局缓存恢复进度值(如果有)
|
||||
instruction_id = str(data["id"])
|
||||
if instruction_id in self.instructionProgressCache:
|
||||
cache = self.instructionProgressCache[instruction_id]
|
||||
|
|
@ -762,11 +772,11 @@ class DeviceForm(QWidget):
|
|||
else:
|
||||
progressItem.setData({'instruction_id': data["id"], 'name': data["name"]}, Qt.ItemDataRole.UserRole)
|
||||
self.devInstructionModel.setItem(index, 5, progressItem)
|
||||
delegate = ProgressBarDelegate()
|
||||
self.ui.tableViewDevCmd.setItemDelegateForColumn(5, delegate)
|
||||
if "description" not in attr:
|
||||
attr["description"] = ""
|
||||
self.devInstructionModel.setItem(index, 6, QStandardItem(attr["description"]))
|
||||
self.devInstructionModel.blockSignals(False)
|
||||
self.ui.tableViewDevCmd.setUpdatesEnabled(True)
|
||||
self.ui.tableViewDevCmd.sortByColumn(2, Qt.SortOrder.AscendingOrder)
|
||||
self.batchOperation()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#!/opt/homebrew/bin/python3
|
||||
# -*- coding:utf-8 -*-
|
||||
import json
|
||||
import threading
|
||||
from PyQt6 import *
|
||||
from PyQt6.QtCore import *
|
||||
from logs import log
|
||||
|
|
@ -28,14 +29,16 @@ class InfluxdbManager(QObject):
|
|||
confData['influxdbName'] = influxdbName
|
||||
for _influxdb in influxdbs:
|
||||
if _influxdb["name"] == influxdbName:
|
||||
influxdb.close()
|
||||
influxdb.setConfig( _influxdb )
|
||||
influxdb.close()
|
||||
influxdb.setConfig(_influxdb)
|
||||
config.update(confData)
|
||||
projectInfo = projectManager.getCurrentProInfo()
|
||||
proname = "name" in projectInfo and projectInfo["name"] or ""
|
||||
def _open():
|
||||
influxdb.open()
|
||||
projectInfo = projectManager.getCurrentProInfo()
|
||||
proname = "name" in projectInfo and projectInfo["name"] or ""
|
||||
influxdb.create(proname)
|
||||
config.update(confData)
|
||||
return True
|
||||
threading.Thread(target=_open, daemon=True).start()
|
||||
return True
|
||||
return False
|
||||
|
||||
@pyqtSlot(str, result=QVariant)
|
||||
|
|
|
|||
20
logForm.py
20
logForm.py
|
|
@ -144,42 +144,32 @@ class LogForm(QWidget):
|
|||
self.ui.plainTextEdit.appendPlainText(text)
|
||||
|
||||
def setLogPlainText(self):
|
||||
"""增量更新:只追加新增的日志,不全量重绘"""
|
||||
try:
|
||||
current_id = self._getCurrentId()
|
||||
|
||||
if current_id not in self.logThread.msgDataMap:
|
||||
return
|
||||
|
||||
new_count = self.logThread.newCountMap.get(current_id, 0)
|
||||
if new_count <= 0:
|
||||
return
|
||||
self.logThread.newCountMap[current_id] = 0
|
||||
|
||||
data_list = self.logThread.msgDataMap[current_id]
|
||||
total = len(data_list)
|
||||
|
||||
# 如果数据被截断(超过 maxCount),需要全量重绘
|
||||
if self.lastRenderedCount > total:
|
||||
# 超过 maxCount 发生了截断,或首次渲染,全量重绘
|
||||
if self.lastRenderedCount >= total or self.lastRenderedCount + new_count > total:
|
||||
self.ui.plainTextEdit.clear()
|
||||
htmlText = "".join(data_list)
|
||||
self.ui.plainTextEdit.appendHtml(htmlText)
|
||||
self.ui.plainTextEdit.appendHtml("".join(data_list))
|
||||
self.lastRenderedCount = total
|
||||
else:
|
||||
# 只追加新增部分
|
||||
new_items = data_list[self.lastRenderedCount:]
|
||||
if new_items:
|
||||
newHtml = "".join(new_items)
|
||||
# 使用 moveCursor 追加到末尾,避免 clear
|
||||
cursor = self.ui.plainTextEdit.textCursor()
|
||||
cursor.movePosition(QTextCursor.MoveOperation.End)
|
||||
cursor.insertHtml(newHtml)
|
||||
cursor.insertHtml("".join(new_items))
|
||||
self.lastRenderedCount = total
|
||||
|
||||
# 重置新增计数
|
||||
self.logThread.newCountMap[current_id] = 0
|
||||
|
||||
self.scrollToBottom()
|
||||
|
||||
except Exception as e:
|
||||
log.error(f"setLogPlainText exception: {e}")
|
||||
|
||||
|
|
|
|||
|
|
@ -84,9 +84,21 @@ class MainWindow(QMainWindow):
|
|||
|
||||
|
||||
def closeEvent(self, event):
|
||||
running = [a for a in taskActuatorManager.taskActuatorDict.values() if a.isRunning()]
|
||||
if running:
|
||||
reply = QMessageBox.question(
|
||||
self, "确认退出",
|
||||
f"当前有 {len(running)} 个任务正在运行,是否停止所有任务并退出?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||
QMessageBox.StandardButton.No
|
||||
)
|
||||
if reply != QMessageBox.StandardButton.Yes:
|
||||
event.ignore()
|
||||
return
|
||||
taskActuatorManager.stopAll()
|
||||
self.windowClose.emit()
|
||||
self._exit()
|
||||
event.accept() # 接受关闭事件
|
||||
event.accept()
|
||||
|
||||
def initWindow(self):
|
||||
self.ui = Ui_MainWindow()
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class TaskInstruction(Base):
|
|||
delay = Column(String, nullable=True, doc='延时')
|
||||
target_type = Column(String, nullable=False, doc='目标类型')
|
||||
target_id = Column(String, nullable=False, doc='目标id')
|
||||
target_param = Column(Integer, nullable=False, doc='目标id')
|
||||
target_param = Column(String, nullable=True, doc='目标参数')
|
||||
interface_index = Column(Integer, nullable=True, doc='设备接口序号')
|
||||
level = Column(Integer, nullable=True, doc='层级')
|
||||
|
||||
|
|
|
|||
|
|
@ -171,8 +171,10 @@ class ProjectForm(QWidget):
|
|||
self.taskDetailModel.clear()
|
||||
tasks = taskManager.getInfos(self.targetIds)
|
||||
self.taskModelBlockSignals = True
|
||||
self.taskModel.blockSignals(True)
|
||||
self.ui.tableViewTask.setUpdatesEnabled(False)
|
||||
if len(tasks) > 0:
|
||||
|
||||
self.ui.tableViewTask.setItemDelegateForColumn(5, ProgressBarDelegate())
|
||||
for task in tasks:
|
||||
index = self.taskModel.rowCount()
|
||||
task_id = str(task["id"])
|
||||
|
|
@ -180,7 +182,7 @@ class ProjectForm(QWidget):
|
|||
if self.targetParams:
|
||||
param = task_id in self.targetParams and self.targetParams[task_id] or ""
|
||||
progressItem = QxStandardItem()
|
||||
progressItem.setData({'task_instruction_id': task["id"], 'name': task["name"]}, Qt.ItemDataRole.UserRole)
|
||||
progressItem.setData({'task_instruction_id': task["id"], 'name': task["name"]}, Qt.ItemDataRole.UserRole)
|
||||
self.taskModel.setItem(index, 0, QStandardItem(str(task["id"])))
|
||||
self.taskModel.setItem(index, 1, QStandardItem(task["name"]))
|
||||
self.taskModel.setItem(index, 2, QStandardItem(str(task["loop"])))
|
||||
|
|
@ -192,8 +194,8 @@ class ProjectForm(QWidget):
|
|||
self.setUnEditableStyle(self.taskModel.item(index, 2))
|
||||
self.setUnEditableStyle(self.taskModel.item(index, 3))
|
||||
self.setUnEditableStyle(self.taskModel.item(index, 5))
|
||||
delegate = ProgressBarDelegate()
|
||||
self.ui.tableViewTask.setItemDelegateForColumn(5, delegate)
|
||||
self.taskModel.blockSignals(False)
|
||||
self.ui.tableViewTask.setUpdatesEnabled(True)
|
||||
self.taskModelBlockSignals = False
|
||||
self.batchOperation()
|
||||
|
||||
|
|
@ -266,14 +268,17 @@ class ProjectForm(QWidget):
|
|||
def loadTaskDetail(self, taskId):
|
||||
self.setItemsEnable(False)
|
||||
self.taskDetailModelBlockSignals = True
|
||||
self.taskDetailModel.blockSignals(True)
|
||||
self.ui.tableViewTaskDetail.setUpdatesEnabled(False)
|
||||
self.taskDetailModel.clear()
|
||||
self.loadPageTaskDetail(taskId, 0, 50)
|
||||
self.taskDetailModel.blockSignals(False)
|
||||
self.ui.tableViewTaskDetail.setUpdatesEnabled(True)
|
||||
self.taskDetailModelBlockSignals = False
|
||||
self.setItemsEnable(True)
|
||||
self.batchOperation()
|
||||
|
||||
def loadPageTaskDetail(self, taskId, row, limit):
|
||||
QCoreApplication.processEvents()
|
||||
if taskId:
|
||||
taskInstructions = taskInstructionManager.getPageInfo(taskId,row, limit)
|
||||
if len(taskInstructions) > 0:
|
||||
|
|
@ -666,6 +671,8 @@ class ProjectForm(QWidget):
|
|||
if len(infos) == 0:
|
||||
projectManager.setCurrentProId(common.emputyProId)
|
||||
return
|
||||
self.projectModel.blockSignals(True)
|
||||
self.ui.tableViewPro.setUpdatesEnabled(False)
|
||||
for info in infos:
|
||||
index = self.projectModel.rowCount()
|
||||
self.projectModel.setItem(index, 0, QStandardItem(infos[info]["id"]))
|
||||
|
|
@ -676,15 +683,16 @@ class ProjectForm(QWidget):
|
|||
" subcontrol-position: center;"
|
||||
"}")
|
||||
radio.toggled.connect(self.proCheckedChanged)
|
||||
self.projectModel.setItem(index, 2 , QStandardItem())
|
||||
self.projectModel.setItem(index, 2, QStandardItem())
|
||||
if index == self.currentProjectIndex:
|
||||
self.ui.tableViewPro.selectRow(index)
|
||||
radio.setChecked(True)
|
||||
projectManager.setCurrentProId(infos[info]["id"])
|
||||
else:
|
||||
radio.setChecked(False)
|
||||
self.ui.tableViewPro.setIndexWidget(self.projectModel.index(index, 2), radio)
|
||||
|
||||
self.projectModel.blockSignals(False)
|
||||
self.ui.tableViewPro.setUpdatesEnabled(True)
|
||||
self.ui.tableViewPro.selectRow(self.currentProjectIndex)
|
||||
self.batchOperation()
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
|
|
@ -366,10 +366,7 @@ Item {
|
|||
height: parent.height
|
||||
model:serialPorts
|
||||
enabled: editCtrl.checked
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
anchors.right: parent.right
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
|
|
@ -400,12 +397,6 @@ Item {
|
|||
enabled: editCtrl.checked
|
||||
model:serialBuadRates
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
onEditTextChanged:{
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
|
@ -426,9 +417,6 @@ Item {
|
|||
enabled: editCtrl.checked
|
||||
model:serialByteSize
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
|
@ -449,10 +437,6 @@ Item {
|
|||
enabled: editCtrl.checked
|
||||
model:serialStopBits
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
|
@ -473,9 +457,6 @@ Item {
|
|||
enabled: editCtrl.checked
|
||||
model:serialParity
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
|
@ -495,9 +476,6 @@ Item {
|
|||
model:tcpRole
|
||||
enabled: editCtrl.checked
|
||||
anchors.right: parent.right
|
||||
onActivated: {
|
||||
updateInterface(rowIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
|
|
|
|||
169
taskForm.py
169
taskForm.py
|
|
@ -704,84 +704,87 @@ class TaskForm(QWidget):
|
|||
def loadTaskDetail(self, taskId):
|
||||
self.setItemsEnable(False)
|
||||
self.taskDetailModelBlockSignals = True
|
||||
self.taskDetailModel.blockSignals(True)
|
||||
self.taskDetailModel.clear()
|
||||
self.ui.textEditDescription.clear()
|
||||
self.clearTreeModel()
|
||||
self.loadPageTaskDetail(taskId, 0, 50)
|
||||
self.taskDetailModel.blockSignals(False)
|
||||
self.taskDetailModelBlockSignals = False
|
||||
self.loadPageTaskDetail(taskId, 0, 50)
|
||||
self.setItemsEnable(True)
|
||||
self.batchOperation()
|
||||
|
||||
def loadPageTaskDetail(self, taskId, row, limit):
|
||||
QCoreApplication.processEvents()
|
||||
if taskId:
|
||||
taskInstructions = taskInstructionManager.getPageInfo(taskId,row, limit)
|
||||
if len(taskInstructions) > 0:
|
||||
for taskInstruction in taskInstructions:
|
||||
index = self.taskDetailModel.rowCount()
|
||||
self.taskDetailModel.setItem(index, 0, QStandardItem(str(taskInstruction["id"])))
|
||||
self.taskDetailModel.setItem(index, 1, QStandardItem(str(taskInstruction["task_id"])))
|
||||
name = ""
|
||||
type = ""
|
||||
devicename = ""
|
||||
dev_model_id = ""
|
||||
devinterface = []
|
||||
if taskInstruction["target_type"] == "instruction":
|
||||
instruction = instructionManager.getInfo(str(taskInstruction["target_id"]))
|
||||
if instruction:
|
||||
name = instruction["name"]
|
||||
type = instruction["type"]
|
||||
if instruction["type"] is not None and instruction["type"] in self.supportedTypes:
|
||||
type = self.supportedTypes[instruction["type"]]["name"]
|
||||
device_id = taskInstruction["device_id"]
|
||||
device = deviceManager.getInfo(device_id)
|
||||
if device != None:
|
||||
devicename = device["name"]
|
||||
dev_model_id = device["dev_model_id"]
|
||||
devinterface = device["interface"]
|
||||
elif taskInstruction["target_type"] == "task":
|
||||
task = taskManager.getInfo(taskInstruction["target_id"])
|
||||
if task != None:
|
||||
devicename = "任务"
|
||||
name = task["name"]
|
||||
self.taskDetailModel.setItem(index, 2, QStandardItem(str(index+1)))
|
||||
self.taskDetailModel.setItem(index, 3, QStandardItem(devicename))
|
||||
self.taskDetailModel.setItem(index, 4, QStandardItem(name))
|
||||
self.taskDetailModel.setItem(index, 5, QStandardItem(type))
|
||||
self.taskDetailModel.setItem(index, 6, QStandardItem(str(taskInstruction["delay"])))
|
||||
self.taskDetailModel.setItem(index, 7, QStandardItem(str(taskInstruction["loop"])))
|
||||
self.taskDetailModel.setItem(index, 8, QStandardItem(taskInstruction["target_param"]))
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem(""))
|
||||
self.taskDetailModel.setItem(index, 10, QStandardItem(str(taskInstruction["level"])))
|
||||
self.taskDetailModel.setItem(index, 11, QStandardItem(str(taskInstruction["target_id"])))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 2))
|
||||
self.setDeviceStyle(self.taskDetailModel.item(index, 2), devicename)
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 3))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 4))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 5))
|
||||
|
||||
devModel = devModelManager.getInfo(dev_model_id)
|
||||
if devModel != None:
|
||||
attr_json_dict = devModel["attr"]
|
||||
devmodelInterfacetypes = {}
|
||||
if "interfaceType" in attr_json_dict:
|
||||
devmodelInterfacetypes = attr_json_dict["interfaceType"]
|
||||
if len(devmodelInterfacetypes) > 0:
|
||||
cmb = NoWheelComboBox()
|
||||
cmb.currentIndexChanged.connect(self.changeInterface)
|
||||
for devmodelInterfacetype in devmodelInterfacetypes:
|
||||
cmb.addItem(devmodelInterfacetype)
|
||||
interface_index = "interface_index" in taskInstruction and taskInstruction["interface_index"] or 0
|
||||
interface_index = interface_index != "" and interface_index or 0
|
||||
if interface_index < len(devmodelInterfacetypes):
|
||||
cmb.setCurrentIndex(interface_index)
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem(str(interface_index)))
|
||||
else:
|
||||
if len(devmodelInterfacetypes) > 0:
|
||||
cmb.setCurrentIndex(0)
|
||||
taskInstructionManager.update(str(taskInstruction["id"]), {"interface_index":0}) # 更新
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem("0"))
|
||||
self.ui.tableViewTaskDetail.setIndexWidget(self.taskDetailModel.index(index, 9), cmb)
|
||||
try:
|
||||
index = self.taskDetailModel.rowCount()
|
||||
self.taskDetailModel.setItem(index, 0, QStandardItem(str(taskInstruction["id"])))
|
||||
self.taskDetailModel.setItem(index, 1, QStandardItem(str(taskInstruction["task_id"])))
|
||||
name = ""
|
||||
type = ""
|
||||
devicename = ""
|
||||
dev_model_id = ""
|
||||
devinterface = []
|
||||
if taskInstruction["target_type"] == "instruction":
|
||||
instruction = instructionManager.getInfo(str(taskInstruction["target_id"]))
|
||||
if instruction:
|
||||
name = instruction["name"]
|
||||
type = instruction["type"]
|
||||
if instruction["type"] is not None and instruction["type"] in self.supportedTypes:
|
||||
type = self.supportedTypes[instruction["type"]]["name"]
|
||||
device_id = taskInstruction["device_id"]
|
||||
device = deviceManager.getInfo(device_id)
|
||||
if device != None:
|
||||
devicename = device["name"]
|
||||
dev_model_id = device["dev_model_id"]
|
||||
devinterface = device["interface"]
|
||||
elif taskInstruction["target_type"] == "task":
|
||||
task = taskManager.getInfo(taskInstruction["target_id"])
|
||||
if task != None:
|
||||
devicename = "任务"
|
||||
name = task["name"]
|
||||
self.taskDetailModel.setItem(index, 2, QStandardItem(str(index+1)))
|
||||
self.taskDetailModel.setItem(index, 3, QStandardItem(devicename))
|
||||
self.taskDetailModel.setItem(index, 4, QStandardItem(name))
|
||||
self.taskDetailModel.setItem(index, 5, QStandardItem(type))
|
||||
self.taskDetailModel.setItem(index, 6, QStandardItem(str(taskInstruction["delay"])))
|
||||
self.taskDetailModel.setItem(index, 7, QStandardItem(str(taskInstruction["loop"])))
|
||||
self.taskDetailModel.setItem(index, 8, QStandardItem(str(taskInstruction["target_param"] or "")))
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem(""))
|
||||
self.taskDetailModel.setItem(index, 10, QStandardItem(str(taskInstruction["level"])))
|
||||
self.taskDetailModel.setItem(index, 11, QStandardItem(str(taskInstruction["target_id"])))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 2))
|
||||
self.setDeviceStyle(self.taskDetailModel.item(index, 2), devicename)
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 3))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 4))
|
||||
self.setUnEditableStyle(self.taskDetailModel.item(index, 5))
|
||||
devModel = devModelManager.getInfo(dev_model_id)
|
||||
if devModel != None:
|
||||
attr_json_dict = devModel["attr"]
|
||||
devmodelInterfacetypes = {}
|
||||
if "interfaceType" in attr_json_dict:
|
||||
devmodelInterfacetypes = attr_json_dict["interfaceType"]
|
||||
if len(devmodelInterfacetypes) > 0:
|
||||
cmb = NoWheelComboBox()
|
||||
cmb.currentIndexChanged.connect(self.changeInterface)
|
||||
for devmodelInterfacetype in devmodelInterfacetypes:
|
||||
cmb.addItem(devmodelInterfacetype)
|
||||
interface_index = "interface_index" in taskInstruction and taskInstruction["interface_index"] or 0
|
||||
interface_index = interface_index != "" and interface_index or 0
|
||||
if interface_index < len(devmodelInterfacetypes):
|
||||
cmb.setCurrentIndex(interface_index)
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem(str(interface_index)))
|
||||
else:
|
||||
if len(devmodelInterfacetypes) > 0:
|
||||
cmb.setCurrentIndex(0)
|
||||
taskInstructionManager.update(str(taskInstruction["id"]), {"interface_index":0})
|
||||
self.taskDetailModel.setItem(index, 9, QStandardItem("0"))
|
||||
self.ui.tableViewTaskDetail.setIndexWidget(self.taskDetailModel.index(index, 9), cmb)
|
||||
except Exception as e:
|
||||
log.error(f"loadPageTaskDetail error: {e} | data: {taskInstruction}")
|
||||
self.batchOperation()
|
||||
self.loadPageTaskDetail(taskId, row + limit,limit)
|
||||
else:
|
||||
|
|
@ -906,34 +909,34 @@ class TaskForm(QWidget):
|
|||
self.clearTreeModel()
|
||||
tasks = taskManager.getGroupTask(self.current_groupId)
|
||||
self.taskModelBlockSignals = True
|
||||
self.taskModel.blockSignals(True)
|
||||
self.ui.tableViewTask.setUpdatesEnabled(False)
|
||||
if len(tasks) > 0:
|
||||
self.ui.tableViewTask.setItemDelegateForColumn(6, ProgressBarDelegate())
|
||||
for task in tasks:
|
||||
index = self.taskModel.rowCount()
|
||||
progressItem = QxStandardItem('',self)
|
||||
# 从全局缓存恢复进度值(如果有)
|
||||
task_id = str(task["id"])
|
||||
if task_id in self.taskProgressCache:
|
||||
cache = self.taskProgressCache[task_id]
|
||||
progressItem.setData({'task_instruction_id': task["id"], 'name': task["name"], 'value': cache['value'], 'maximum': cache['maximum']}, Qt.ItemDataRole.UserRole)
|
||||
else:
|
||||
progressItem.setData({'task_instruction_id': task["id"], 'name': task["name"]}, Qt.ItemDataRole.UserRole)
|
||||
self.taskModel.setItem(index, 0, QStandardItem(str(task["id"])))
|
||||
self.taskModel.setItem(index, 1, QStandardItem(str(index+1)))
|
||||
self.taskModel.setItem(index, 2, QStandardItem(task["name"]))
|
||||
self.taskModel.setItem(index, 3, QStandardItem(str(task["loop"])))
|
||||
self.taskModel.setItem(index, 4, QStandardItem(str(task["delay"])))
|
||||
self.taskModel.setItem(index, 5, QStandardItem(task["remark"]))
|
||||
self.taskModel.setItem(index, 6, progressItem)
|
||||
self.taskModel.setItem(index, 7, QStandardItem(str(task["group_id"])))
|
||||
self.taskModel.setItem(index, 8, QStandardItem("normal"))
|
||||
row = [
|
||||
QStandardItem(str(task["id"])),
|
||||
QStandardItem(str(index+1)),
|
||||
QStandardItem(task["name"]),
|
||||
QStandardItem(str(task["loop"])),
|
||||
QStandardItem(str(task["delay"])),
|
||||
QStandardItem(task["remark"]),
|
||||
progressItem,
|
||||
QStandardItem(str(task["group_id"])),
|
||||
QStandardItem("parent" if task_id in self.parentTasks else "child" if task_id in self.subTasks else "normal"),
|
||||
]
|
||||
self.taskModel.appendRow(row)
|
||||
self.setUnEditableStyle(self.taskModel.item(index, 1))
|
||||
delegate = ProgressBarDelegate()
|
||||
self.ui.tableViewTask.setItemDelegateForColumn(6, delegate)
|
||||
|
||||
if task_id in self.parentTasks:
|
||||
self.taskModel.setItem(index, 8, QStandardItem("parent"))
|
||||
if task_id in self.subTasks:
|
||||
self.taskModel.setItem(index, 8, QStandardItem("child"))
|
||||
self.taskModel.blockSignals(False)
|
||||
self.ui.tableViewTask.setUpdatesEnabled(True)
|
||||
self.taskModelBlockSignals = False
|
||||
self.batchOperation()
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ class TaskActuator(QThread):
|
|||
self.updateDetails.emit(taskId, current, total)
|
||||
|
||||
def run(self):
|
||||
proId = None
|
||||
operator = None
|
||||
try:
|
||||
tracemalloc.start()
|
||||
loopStartTime = 0
|
||||
|
|
@ -93,9 +95,6 @@ class TaskActuator(QThread):
|
|||
self.currentTask.start()
|
||||
|
||||
while not self.currentTask.isFinished and self.running:
|
||||
if self.running == False:
|
||||
break
|
||||
|
||||
self.currentTask.callBack(0)
|
||||
self.currentIndex = 0
|
||||
self.updateProgress.emit(self.id, 0, total)
|
||||
|
|
@ -123,62 +122,18 @@ class TaskActuator(QThread):
|
|||
|
||||
if target_type == "instruction":
|
||||
self.updateDetails.emit(str(self.parentId) + task_instruction_id, 0, target_loop)
|
||||
|
||||
for j in range(target_loop):
|
||||
loopStartTime = time.time()
|
||||
self.currentTask.callBack(2)
|
||||
if self.currentTask.isFinished:
|
||||
if self.currentTask.isFinished or not self.running:
|
||||
self.updateDetails.emit(str(self.parentId) + task_instruction_id, -1, -1)
|
||||
break
|
||||
if self.running == False:
|
||||
self.updateDetails.emit(str(self.parentId) + task_instruction_id, -1, -1)
|
||||
break
|
||||
# 执行指令
|
||||
currentInstruction.setInfo(taskInstructionInfo["instructionInfo"], taskInstructionInfo["target_param"])
|
||||
currentInstruction.setProInfo(proInfo)
|
||||
currentInstruction.setUserInfo(userManager.getCurrentUser())
|
||||
currentInstruction.setDevInfo(taskInstructionInfo["device"])
|
||||
interfaceInfos = interfaceManager.getInfo(taskInstructionInfo["interface"])
|
||||
interfaceInfo = {}
|
||||
if len(interfaceInfos) <= 0:
|
||||
continue
|
||||
interfaceInfo = interfaceInfos[0] #interface接口返回个数为1
|
||||
currentInstruction.setInterfaceInfo(interfaceInfo)
|
||||
session = interfaceManager.getSession(taskInstructionInfo["interface"])
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
|
||||
currentInstruction.logMsg.connect(self.onLogMsg, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.ioCtrl.connect(session.ioctrl, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.sendData.connect(session.send, type=Qt.ConnectionType.DirectConnection)
|
||||
|
||||
while not self.currentTask.isFinished and not session.lock() and self.running:
|
||||
self.updateProgress.emit(self.id, int( self.currentIndex + int(taskIndex*instructionListLength)), total)
|
||||
QThread.usleep(1)
|
||||
session.newDataArrive.connect(currentInstruction.dataHandler, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.start()
|
||||
while not self.currentTask.isFinished and not currentInstruction.isFinished and self.running:
|
||||
self.updateProgress.emit(self.id, int( self.currentIndex + int(taskIndex*instructionListLength)), total)
|
||||
currentInstruction.loop()
|
||||
QThread.usleep(1)
|
||||
|
||||
self.updateDetails.emit(str(self.parentId) + task_instruction_id, j+1, target_loop)
|
||||
#解除信号绑定
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
session.unlock()
|
||||
progress_cb = lambda: self.updateProgress.emit(self.id, int(self.currentIndex + int(taskIndex * instructionListLength)), total)
|
||||
self._run_single_instruction(currentInstruction, taskInstructionInfo, proInfo, None,
|
||||
lambda: not self.currentTask.isFinished, progress_cb)
|
||||
self.updateDetails.emit(str(self.parentId) + task_instruction_id, j + 1, target_loop)
|
||||
tmpTime = time.time()
|
||||
if tmpTime < loopStartTime + target_delay:
|
||||
if tmpTime < loopStartTime + target_delay:
|
||||
time.sleep(target_delay - (tmpTime - loopStartTime))
|
||||
|
||||
# time.sleep(target_delay) 指令延时在指令内部处理
|
||||
|
|
@ -237,48 +192,10 @@ class TaskActuator(QThread):
|
|||
|
||||
if target_type == "instruction":
|
||||
for j in range(target_loop):
|
||||
if self.running == False:
|
||||
if not self.running:
|
||||
break
|
||||
# 执行指令
|
||||
currentInstruction.setInfo(taskInstructionInfo["instructionInfo"], taskInstructionInfo["target_param"])
|
||||
currentInstruction.setProInfo(proInfo)
|
||||
currentInstruction.setUserInfo(userManager.getCurrentUser())
|
||||
currentInstruction.setDevInfo(taskInstructionInfo["device"])
|
||||
interfaceInfos = interfaceManager.getInfo(taskInstructionInfo["interface"])
|
||||
interfaceInfo = {}
|
||||
if len(interfaceInfos) <= 0:
|
||||
continue
|
||||
interfaceInfo = interfaceInfos[0] #interface接口返回个数为1
|
||||
currentInstruction.setInterfaceInfo(interfaceInfo)
|
||||
session = interfaceManager.getSession(taskInstructionInfo["interface"])
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
currentInstruction.logMsg.connect(self.onLogMsg, type=Qt.ConnectionType.UniqueConnection)
|
||||
currentInstruction.ioCtrl.connect(session.ioctrl, type=Qt.ConnectionType.UniqueConnection)
|
||||
currentInstruction.sendData.connect(session.send, type=Qt.ConnectionType.UniqueConnection)
|
||||
|
||||
while not session.lock() and self.running:
|
||||
QThread.usleep(1)
|
||||
session.newDataArrive.connect(currentInstruction.dataHandler, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.start()
|
||||
|
||||
while not currentInstruction.isFinished and self.running:
|
||||
currentInstruction.loop()
|
||||
QThread.usleep(1)
|
||||
# 解除信号绑定
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
session.unlock()
|
||||
self._run_single_instruction(currentInstruction, taskInstructionInfo, proInfo, None,
|
||||
lambda: True)
|
||||
time.sleep(target_delay)
|
||||
elif target_type == "task":
|
||||
# 执行子任务
|
||||
|
|
@ -304,48 +221,11 @@ class TaskActuator(QThread):
|
|||
if target_type == "instruction":
|
||||
self.updateInstructProgress.emit(target_id, 0, target_loop)
|
||||
for j in range(target_loop):
|
||||
if self.running == False:
|
||||
if not self.running:
|
||||
break
|
||||
# 执行指令
|
||||
currentInstruction.setInfo(taskInstructionInfo["instructionInfo"], taskInstructionInfo["target_param"])
|
||||
currentInstruction.setProInfo(proInfo)
|
||||
currentInstruction.setUserInfo(userManager.getCurrentUser())
|
||||
currentInstruction.setDevInfo(taskInstructionInfo["device"])
|
||||
interfaceInfos = interfaceManager.getInfo(taskInstructionInfo["interface"])
|
||||
interfaceInfo = {}
|
||||
if len(interfaceInfos) <= 0:
|
||||
continue
|
||||
interfaceInfo = interfaceInfos[0]
|
||||
currentInstruction.setInterfaceInfo(interfaceInfo)
|
||||
session = interfaceManager.getSession(taskInstructionInfo["interface"])
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
currentInstruction.logMsg.connect(self.onLogMsg, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.ioCtrl.connect(session.ioctrl, type=Qt.ConnectionType.UniqueConnection)
|
||||
currentInstruction.sendData.connect(session.send, type=Qt.ConnectionType.UniqueConnection)
|
||||
while not session.lock() and self.running:
|
||||
self.updateInstructProgress.emit(target_id, j, target_loop)
|
||||
QThread.msleep(10)
|
||||
session.newDataArrive.connect(currentInstruction.dataHandler, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.start()
|
||||
while not currentInstruction.isFinished and self.running:
|
||||
self.updateInstructProgress.emit(target_id, j, target_loop)
|
||||
currentInstruction.loop()
|
||||
QThread.msleep(10)
|
||||
# 解除信号绑定
|
||||
try:
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except:
|
||||
pass
|
||||
session.unlock()
|
||||
progress_cb = lambda: self.updateInstructProgress.emit(target_id, j, target_loop)
|
||||
self._run_single_instruction(currentInstruction, taskInstructionInfo, proInfo, None,
|
||||
lambda: True, progress_cb)
|
||||
time.sleep(target_delay)
|
||||
self.updateInstructProgress.emit(self.id,1,-1)
|
||||
currentInstruction.deleteLater()
|
||||
|
|
@ -389,20 +269,66 @@ class TaskActuator(QThread):
|
|||
# for stat in top_stats[:10]:
|
||||
# print(stat)
|
||||
|
||||
def _run_single_instruction(self, currentInstruction, taskInstructionInfo, proInfo, session_ref,
|
||||
stop_check, progress_cb=None):
|
||||
"""执行单次指令:连接信号、锁session、运行、解锁。返回使用的session。"""
|
||||
interfaceInfos = interfaceManager.getInfo(taskInstructionInfo["interface"])
|
||||
if not interfaceInfos:
|
||||
return None
|
||||
currentInstruction.setInfo(taskInstructionInfo["instructionInfo"], taskInstructionInfo["target_param"])
|
||||
currentInstruction.setProInfo(proInfo)
|
||||
currentInstruction.setUserInfo(userManager.getCurrentUser())
|
||||
currentInstruction.setDevInfo(taskInstructionInfo["device"])
|
||||
currentInstruction.setInterfaceInfo(interfaceInfos[0])
|
||||
session = interfaceManager.getSession(taskInstructionInfo["interface"])
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except Exception:
|
||||
pass
|
||||
currentInstruction.logMsg.connect(self.onLogMsg, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.ioCtrl.connect(session.ioctrl, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.sendData.connect(session.send, type=Qt.ConnectionType.DirectConnection)
|
||||
while not session.lock() and self.running and stop_check():
|
||||
if progress_cb:
|
||||
progress_cb()
|
||||
QThread.msleep(1)
|
||||
if not self.running or not stop_check():
|
||||
return None
|
||||
session.newDataArrive.connect(currentInstruction.dataHandler, type=Qt.ConnectionType.DirectConnection)
|
||||
currentInstruction.start()
|
||||
while not currentInstruction.isFinished and self.running and stop_check():
|
||||
if progress_cb:
|
||||
progress_cb()
|
||||
currentInstruction.loop()
|
||||
QThread.msleep(1)
|
||||
try:
|
||||
currentInstruction.logMsg.disconnect(self.onLogMsg)
|
||||
currentInstruction.ioCtrl.disconnect(session.ioctrl)
|
||||
currentInstruction.sendData.disconnect(session.send)
|
||||
session.newDataArrive.disconnect(currentInstruction.dataHandler)
|
||||
except Exception:
|
||||
pass
|
||||
session.unlock()
|
||||
return session
|
||||
|
||||
def onLogMsg(self, data):
|
||||
logManager.addLogMsg(data)
|
||||
self.logMsg.emit(data)
|
||||
|
||||
# 执行指令或者队列
|
||||
def execute(self, target, taskInfo = {}):
|
||||
if self.isRunning():
|
||||
return False
|
||||
self.running = True
|
||||
|
||||
|
||||
if isinstance(target, list): #队列
|
||||
self.instructionList = target
|
||||
self.taskInfo = taskInfo
|
||||
self.type = taskInfo.get("type", TaskActuator.TASK)
|
||||
self.name = taskInfo.get("name", TaskActuator.TASK)
|
||||
self.type = int(taskInfo.get("type", TaskActuator.TASK))
|
||||
self.name = taskInfo.get("name", "")
|
||||
self.start()
|
||||
return True
|
||||
elif isinstance(target, dict): #指令
|
||||
|
|
@ -436,28 +362,34 @@ class TaskActuator(QThread):
|
|||
self.quit()
|
||||
|
||||
def forceStop(self):
|
||||
"""强制立即停止任务(非阻塞)"""
|
||||
# 1. 立即设置停止标志
|
||||
self.running_lock.lock()
|
||||
self.running = False
|
||||
self.running_lock.unlock()
|
||||
|
||||
# 2. 停止子任务
|
||||
|
||||
if self.subTaskActuator and self.subTaskActuator.isRunning():
|
||||
self.subTaskActuator.forceStop()
|
||||
|
||||
# 3. 终止当前指令的执行
|
||||
|
||||
if self.currentTask and hasattr(self.currentTask, 'isFinished'):
|
||||
self.currentTask.isFinished = True
|
||||
|
||||
# 4. 强制终止线程(不等待)
|
||||
|
||||
# 等待线程自然退出(最多500ms),避免 terminate 造成锁泄漏
|
||||
if self.isRunning():
|
||||
self.wait(500)
|
||||
|
||||
# 超时仍在运行才强杀,并释放所有 session 锁
|
||||
if self.isRunning():
|
||||
for item in self.instructionList:
|
||||
try:
|
||||
iface = item.get("interface")
|
||||
if iface:
|
||||
interfaceManager.getSession(iface).unlock()
|
||||
except Exception:
|
||||
pass
|
||||
self.terminate()
|
||||
|
||||
# 5. 发送停止信号
|
||||
self.wait(200)
|
||||
|
||||
self.updateDetails.emit(self.id, -1, -1)
|
||||
self.taskStop.emit(self.id)
|
||||
|
||||
log.info(f"任务 {self.id} 已强制停止")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class TaskActuatorManager(QObject):
|
|||
else:
|
||||
taskInstructions = taskInstructionManager.getInfo(taskId)
|
||||
self.taskActuatorDict[taskId] = TaskActuator(taskId)
|
||||
self.taskActuatorDict[taskId].logMsg.connect(self.onLogMsg)
|
||||
self.taskActuatorDict[taskId].updateProgress.connect(self.onUpdateProgress)
|
||||
self.taskActuatorDict[taskId].updateDetails.connect(self.onUpdateDetails)
|
||||
self.taskActuatorDict[taskId].taskStop.connect(self.onTaskStop)
|
||||
|
|
@ -57,6 +58,9 @@ class TaskActuatorManager(QObject):
|
|||
def onExecuteFinished(self, taskId):
|
||||
self.executeFinished.emit(taskId)
|
||||
|
||||
def onLogMsg(self, data):
|
||||
self.logMsg.emit(data)
|
||||
|
||||
def onUpdateInstructProgress(self,id, value, maxValue):
|
||||
if id in self.instructProgressInfo:
|
||||
self.instructProgressInfo[id]["value"] = value
|
||||
|
|
@ -92,20 +96,39 @@ class TaskActuatorManager(QObject):
|
|||
|
||||
@pyqtSlot()
|
||||
def stopAll(self, excludeTaskId=None):
|
||||
"""立即停止所有运行中的任务"""
|
||||
stopped_count = 0
|
||||
# 复制键列表,避免遍历时修改字典
|
||||
for taskId in list(self.taskActuatorDict.keys()):
|
||||
# 如果指定了排除ID,跳过该任务
|
||||
if excludeTaskId and str(taskId) == str(excludeTaskId):
|
||||
continue
|
||||
|
||||
actuator = self.taskActuatorDict[taskId]
|
||||
if actuator.isRunning():
|
||||
actuator.forceStop()
|
||||
stopped_count += 1
|
||||
log.info(f"已强制停止 {stopped_count} 个任务")
|
||||
return stopped_count
|
||||
actuators = [
|
||||
a for tid, a in list(self.taskActuatorDict.items())
|
||||
if a.isRunning() and not (excludeTaskId and str(tid) == str(excludeTaskId))
|
||||
]
|
||||
# 先全部设置停止标志
|
||||
for a in actuators:
|
||||
a.running_lock.lock()
|
||||
a.running = False
|
||||
a.running_lock.unlock()
|
||||
if a.currentTask and hasattr(a.currentTask, 'isFinished'):
|
||||
a.currentTask.isFinished = True
|
||||
if a.subTaskActuator and a.subTaskActuator.isRunning():
|
||||
a.subTaskActuator.running_lock.lock()
|
||||
a.subTaskActuator.running = False
|
||||
a.subTaskActuator.running_lock.unlock()
|
||||
# 再统一等待/强杀
|
||||
for a in actuators:
|
||||
a.quit()
|
||||
if not a.wait(500):
|
||||
for item in a.instructionList:
|
||||
try:
|
||||
iface = item.get("interface")
|
||||
if iface:
|
||||
from interfaceSession.interfaceManager import interfaceManager
|
||||
interfaceManager.getSession(iface).unlock()
|
||||
except Exception:
|
||||
pass
|
||||
a.terminate()
|
||||
a.wait(200)
|
||||
a.updateDetails.emit(a.id, -1, -1)
|
||||
a.taskStop.emit(a.id)
|
||||
log.info(f"任务 {a.id} 已停止")
|
||||
return len(actuators)
|
||||
|
||||
def requestStopAll(self, requesterTaskId=None):
|
||||
"""请求停止所有任务(由主程序处理)"""
|
||||
|
|
@ -123,4 +146,27 @@ class TaskActuatorManager(QObject):
|
|||
"""启动任务(execute 的别名)"""
|
||||
self.execute(taskId, params)
|
||||
|
||||
@pyqtSlot(str, QVariant)
|
||||
def startInstruction(self, instructionId, attr=None):
|
||||
try:
|
||||
if not isinstance(attr, dict) and attr is not None:
|
||||
attr = attr.toVariant()
|
||||
attr = attr or {"deviceId": "", "param": "", "interfaceIndex": 0}
|
||||
taskInstruction = common.getInstructionDetail(instructionId, attr)
|
||||
if taskInstruction is None:
|
||||
return False
|
||||
if instructionId in self.taskActuatorDict:
|
||||
if self.taskActuatorDict[instructionId].isRunning():
|
||||
return False
|
||||
else:
|
||||
self.taskActuatorDict[instructionId] = TaskActuator(instructionId)
|
||||
self.taskActuatorDict[instructionId].logMsg.connect(self.onLogMsg)
|
||||
self.taskActuatorDict[instructionId].updateInstructProgress.connect(self.onUpdateInstructProgress)
|
||||
self.taskActuatorDict[instructionId].taskStop.connect(self.onTaskStop)
|
||||
self.taskActuatorDict[instructionId].execute(taskInstruction)
|
||||
return True
|
||||
except Exception as e:
|
||||
log.error(f"startInstruction 出错: {e}")
|
||||
return False
|
||||
|
||||
taskActuatorManager = TaskActuatorManager()
|
||||
|
|
|
|||
|
|
@ -82,16 +82,20 @@ class UserForm(QWidget):
|
|||
self.ui.tableViewUser.selectRow(row)
|
||||
|
||||
# 加载用户
|
||||
def loadUser(self):
|
||||
def loadUser(self):
|
||||
users = userManager.getInfo()
|
||||
if len(users) > 0:
|
||||
self.userModel.clear()
|
||||
self.userModel.blockSignals(True)
|
||||
self.ui.tableViewUser.setUpdatesEnabled(False)
|
||||
for user in users:
|
||||
index = self.userModel.rowCount()
|
||||
self.userModel.setItem(index, 0, QStandardItem(str(user["id"])))
|
||||
self.userModel.setItem(index, 1, QStandardItem(user["name"]))
|
||||
self.userModel.setItem(index, 2, QStandardItem(user["password"]))
|
||||
self.userModel.setItem(index, 3, QStandardItem(user["role_name"]))
|
||||
self.userModel.blockSignals(False)
|
||||
self.ui.tableViewUser.setUpdatesEnabled(True)
|
||||
self.batchOperation()
|
||||
|
||||
# 批量操作
|
||||
|
|
|
|||
Loading…
Reference in New Issue