#!/opt/homebrew/bin/python3 # -*- coding:utf-8 -*- import json import tracemalloc import gc import time import base64 from PyQt6 import * from PyQt6.QtCore import * from logs import log from typing import Union from inspect import isfunction from common import common from influxDB import influxdb from logModel.logManager import logManager from instructionModel.instructionModel import InstructionModel from projectModel.projectManager import projectManager from userModel.userManager import userManager from taskModel.taskManager import taskManager from taskInstructionModel.taskInstructionManager import taskInstructionManager from taskModel.taskModel import TaskModel from interfaceSession.interfaceManager import interfaceManager class TaskActuator(QThread): TASK = 0 VIRTUAL = 1 INSTRUCTION = 2 logMsg = pyqtSignal(dict) updateProgress = pyqtSignal(str, int, int) updateInstructProgress = pyqtSignal(str, int, int) updateDetails = pyqtSignal(str, int, int) executeFinished = pyqtSignal(str) def __init__(self, id): super().__init__() self.currentIndex = 0 self.task_instruction_id = "" self.instructionList = [] self.currentTask = None self.parentId = "" self.running_lock = QMutex() # 新增互斥锁 self.running = False self.eventInfo = {} self.subTaskActuator = None self.taskScript = "" self.type = TaskActuator.INSTRUCTION self.id = str(id) self.name = "" self.taskInfo = {} def onUpdateProgress(self, taskId, current, total): self.updateProgress.emit(taskId, current, total) def onUpdateDetails(self, taskId, current, total): self.updateDetails.emit(taskId, current, total) def run(self): try: tracemalloc.start() loopStartTime = 0 currentInstruction = InstructionModel() session = None proId = projectManager.getCurrentProId() proInfo = projectManager.getCurrentProInfo() bucketName = "name" in proInfo and proInfo["name"] or "DEFAULT" influxdb.create(bucketName) operator = userManager.getCurrentUser() if proId != None and proId != "": projectManager.addHistory(proId, { "event": "执行", "type": self.type, "name": self.name, "operator": operator, }) instructionListLength = len(self.instructionList) if self.type == TaskActuator.TASK and instructionListLength > 0: self.currentTask = TaskModel(self.taskInfo) self.currentTask.setProInfo(proInfo) self.currentTask.logMsg.connect(self.onLogMsg, type=Qt.ConnectionType.DirectConnection) self.currentTask.updateProgress.connect(self.onUpdateProgress) loop = int(self.taskInfo.get("loop", 1)) delay = float(int(self.taskInfo.get("delay",0))/1000) taskIndex = 0 self.updateProgress.emit(self.id, 0, instructionListLength) self.updateDetails.emit(self.id, 0, instructionListLength) self.updateDetails.emit(self.parentId, 0, instructionListLength) self.currentTask.setTargetList(self.instructionList) self.currentTask.start() while not self.currentTask.isFinished and self.running: if self.running == False: break self.currentTask.callBack(0) self.currentIndex = 0 total = instructionListLength * loop self.updateProgress.emit(self.id, 0, total) # 执行任务 while not self.currentTask.isFinished and self.currentIndex < instructionListLength and self.running: taskInstructionInfo = self.instructionList[self.currentIndex] self.currentTask.setTargetId(taskInstructionInfo["target_id"]) self.currentTask.callBack(1) task_instruction_id = str(taskInstructionInfo["id"]) or "" target_id = str(taskInstructionInfo["target_id"]) or "" target_type = taskInstructionInfo["target_type"] or "" level = str(taskInstructionInfo["level"]) or "" target_loop = "loop" in taskInstructionInfo and int(taskInstructionInfo["loop"]) or 1 target_delay = "delay" in taskInstructionInfo and float(int(taskInstructionInfo["delay"])/1000) or 0 if self.parentId == "": self.parentId = self.id 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: 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() tmpTime = time.time() if tmpTime < loopStartTime + target_delay: time.sleep(target_delay - (tmpTime - loopStartTime)) # time.sleep(target_delay) 指令延时在指令内部处理 elif target_type == "task": # 执行子任务 for j in range(target_loop): if not self.running: break self.currentTask.callBack(5) self.subTaskActuator = TaskActuator(target_id) self.subTaskActuator.parentId = str(self.parentId) + task_instruction_id self.subTaskActuator.task_instruction_id = str(self.parentId) + task_instruction_id taskInfo = taskManager.getInfo(target_id) taskInfo["params"] = taskInstructionInfo["target_param"] taskInstructions = taskInstructionManager.getInfo(target_id) common.getTaskDetails(taskInstructions) self.subTaskActuator.updateDetails.connect(self.onUpdateDetails, type=Qt.ConnectionType.DirectConnection) self.subTaskActuator.execute(taskInstructions, taskInfo) self.subTaskActuator.wait() self.currentTask.callBack(6) time.sleep(target_delay) # 子任务执行完毕 self.currentIndex += 1 if loop > 0: if self.currentTask.isFinished: self.updateProgress.emit(self.id,1,-1) self.updateDetails.emit(self.id,-1,-1) elif self.running: if self.task_instruction_id != "": self.updateDetails.emit( self.task_instruction_id, int( self.currentIndex + int(taskIndex*instructionListLength)), total) else: self.updateDetails.emit(self.id, int( self.currentIndex + int(taskIndex*instructionListLength)), total) self.updateProgress.emit(self.id, int( self.currentIndex + int(taskIndex*instructionListLength)), total) taskIndex += 1 self.currentTask.next() if loop > 1: time.sleep(delay) self.updateProgress.emit(str(self.taskInfo["id"]),1,-1) currentInstruction.deleteLater() elif self.type == TaskActuator.VIRTUAL and instructionListLength > 0: session = None currentInstruction = InstructionModel() self.currentIndex = 0 total = instructionListLength # 执行任务 while self.currentIndex < instructionListLength and self.running: taskInstructionInfo = self.instructionList[self.currentIndex] target_id = str(taskInstructionInfo["target_id"]) or "" target_type = taskInstructionInfo["target_type"] or "" target_loop = "loop" in taskInstructionInfo and int(taskInstructionInfo["loop"]) or 1 target_delay = "delay" in taskInstructionInfo and float(int(taskInstructionInfo["delay"])/1000) or 0 if target_type == "instruction": for j in range(target_loop): if self.running == False: 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() time.sleep(target_delay) elif target_type == "task": # 执行子任务 for j in range(target_loop): self.subTaskActuator = TaskActuator(target_id) taskInfo = taskManager.getInfo(target_id) taskInstructions = taskInstructionManager.getInfo(target_id) common.getTaskDetails(taskInstructions) self.subTaskActuator.execute(taskInstructions, taskInfo) self.subTaskActuator.wait() time.sleep(target_delay) # 子任务执行完毕 self.currentIndex += 1 currentInstruction.deleteLater() elif self.type == TaskActuator.INSTRUCTION and instructionListLength == 1: session = None currentInstruction = InstructionModel() taskInstructionInfo = self.instructionList[0] target_id = str(taskInstructionInfo["target_id"]) or "" target_type = taskInstructionInfo["target_type"] or "" target_loop = "loop" in taskInstructionInfo and int(taskInstructionInfo["loop"]) or 1 target_delay = "delay" in taskInstructionInfo and float(int(taskInstructionInfo["delay"])/1000) or 0 if target_type == "instruction": self.updateInstructProgress.emit(target_id, 0, target_loop) for j in range(target_loop): if self.running == False: 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() time.sleep(target_delay) self.updateInstructProgress.emit(self.id,1,-1) currentInstruction.deleteLater() except Exception as e: try: common.showAlert.emit("EXEC错误", str(e), 0) except Exception as e: log.info(str(e)) finally: try: currentInstruction.ioCtrl.disconnect(session.ioctrl) currentInstruction.sendData.disconnect(session.send) currentInstruction.logMsg.disconnect(self.onLogMsg) session.newDataArrive.disconnect(currentInstruction.dataHandler) session.unlock() except: pass if proId != None and proId != "": projectManager.addHistory(proId, { "event": "结束", "type": self.type, "name": self.name, "operator": operator, }) self.updateInstructProgress.emit(self.id,1,-1) self.updateProgress.emit(self.id,1,-1) self.updateDetails.emit(self.id,1,-1) self.executeFinished.emit(self.id) self.quit() # currentInstruction.deleteLater() # currentInstruction = None # gc.collect() # 手动触发垃圾回收 # snapshot = tracemalloc.take_snapshot() # # 打印内存分配的前10条统计信息 # top_stats = snapshot.statistics('lineno') # print("内存分配的前10行:") # for stat in top_stats[:10]: # print(stat) def onLogMsg(self, data): logManager.addLogMsg(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.start() return True elif isinstance(target, dict): #指令 self.instructionList = [] self.name = target["instructionInfo"]["name"] self.instructionList.append(target) self.type = TaskActuator.INSTRUCTION self.start() return True return False def stopSub(self): self.running_lock.lock() self.running = False self.running_lock.unlock() # 停止子任务 if self.subTaskActuator and self.subTaskActuator.isRunning(): self.subTaskActuator.stopSub() self.updateDetails.emit(str(self.parentId) , -1, -1) self.quit() def stop(self): self.running_lock.lock() self.running = False self.running_lock.unlock() # 停止子任务 if self.subTaskActuator and self.subTaskActuator.isRunning(): self.subTaskActuator.stopSub() self.quit() defaultTaskActuator = TaskActuator("defaultTaskActuator")