From f9b9ae6403438bf7d5100bc5924ca0f9f929f32f Mon Sep 17 00:00:00 2001 From: "ZHANGXUXU\\95193" <951937200@qq.com> Date: Fri, 1 Aug 2025 17:16:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=85=A5=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E8=A1=A8bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UI/VarManages/AnalogModel.py | 4 +- UI/VarManages/ModbusModel.py | 42 +++++++++++- UI/VarManages/TCRTDModel.py | 4 +- model/ProjectModel/VarManage.py | 118 +++++++++++++++++++++++++------- utils/DBModels/ProtocolModel.py | 51 +++++++++++--- 5 files changed, 178 insertions(+), 41 deletions(-) diff --git a/UI/VarManages/AnalogModel.py b/UI/VarManages/AnalogModel.py index 7ed96ee..54bbb10 100644 --- a/UI/VarManages/AnalogModel.py +++ b/UI/VarManages/AnalogModel.py @@ -46,7 +46,7 @@ class AnalogModel(VarTableModel): self.table.proxy.invalidate() return for x in varDatas: - x.insert(1, '') + # x.insert(1, '') x.insert(2, '') self.datas.append(x) x.append('') @@ -55,6 +55,8 @@ class AnalogModel(VarTableModel): self.table.proxy.invalidate() # 初始化后立即刷新缓存 self.refreshValueCache() + + def data(self, QModelIndex, role=None): # print(Qt.__dict__.items()) diff --git a/UI/VarManages/ModbusModel.py b/UI/VarManages/ModbusModel.py index de6fdd3..6d76579 100644 --- a/UI/VarManages/ModbusModel.py +++ b/UI/VarManages/ModbusModel.py @@ -46,7 +46,7 @@ class VarTableModel(QAbstractTableModel): self.table = table self.editableList = [] # 表格中可编辑项 self.modbusType = modbusType - def initTable(self): + def initTable(self, initVar = None): self.datas = [] self.editableList = [] if self.table: @@ -193,6 +193,9 @@ class VarTableModel(QAbstractTableModel): if comboBox is None: # 如果comboBox不存在,跳过这一行 continue + # 检查comboBox对象是否仍然有效,避免RuntimeError + if not comboBox or comboBox.isHidden(): + continue # print(comboBox, i, num, cbRow) except Exception as e: continue @@ -332,6 +335,8 @@ class ModbusButtonDelegate(BaseButtonDelegate): "请输入强制值或数字", QMessageBox.Yes) return + + if min and max: if float(value) < float(min) or float(value) > float(max): reply = QMessageBox.question(self.parent(), @@ -376,7 +381,7 @@ class ModbusButtonDelegate(BaseButtonDelegate): sender = self.sender() model = self.parent().model modbusType = self.parent().modbusType - + pattern = re.compile(r'[^0-9\.-]+') # 使用基类的验证方法获取行索引 view_row, source_row = self._validate_button_indices(sender) if view_row is None: @@ -407,6 +412,39 @@ class ModbusButtonDelegate(BaseButtonDelegate): "有字段为空或输入错误", QMessageBox.Yes) return + + # 验证slaveID、address、min、max是否为有效数字 + # 检查slaveID是否为有效数字 + if slaveID and re.findall(pattern, slaveID): + reply = QMessageBox.question(self.parent(), + '警告', + "从站地址必须为数字", + QMessageBox.Yes) + return + + # 检查address是否为有效数字 + if address and re.findall(pattern, address): + reply = QMessageBox.question(self.parent(), + '警告', + "寄存器地址必须为数字", + QMessageBox.Yes) + return + + # 检查min是否为有效数字(如果存在) + if min and re.findall(pattern, min): + reply = QMessageBox.question(self.parent(), + '警告', + "工程量下限必须为数字", + QMessageBox.Yes) + return + + # 检查max是否为有效数字(如果存在) + if max and re.findall(pattern, max): + reply = QMessageBox.question(self.parent(), + '警告', + "工程量上限必须为数字", + QMessageBox.Yes) + return if sender.oldName and ModbusVarManage.getByName(sender.oldName, modbusType): diff --git a/UI/VarManages/TCRTDModel.py b/UI/VarManages/TCRTDModel.py index 3b63206..cc981b6 100644 --- a/UI/VarManages/TCRTDModel.py +++ b/UI/VarManages/TCRTDModel.py @@ -47,7 +47,7 @@ class TcRtdModel(VarTableModel): self.table.proxy.invalidate() return for x in varDatas: - x.insert(1, '') + # x.insert(1, '') x.insert(2, '') self.datas.append(x) x.append('') @@ -272,7 +272,6 @@ class TcRtdButtonDelegate(BaseButtonDelegate): model.editableList.append(source_row) else: varMes = model.datas[source_row] - print(varMes,2222) name, channelNumber, des, varType, min, max, compensationVar, unit = str(varMes[3]), str(varMes[4]), str(varMes[5]),str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[10]), str(varMes[9]) if not name or not varType: reply = QMessageBox.question(self.parent(), @@ -307,7 +306,6 @@ class TcRtdButtonDelegate(BaseButtonDelegate): varMes.insert(1, '') varMes.insert(2, '') varMes.append('') - print(varMes, 1111) model.insert_data(varMes, source_row) model.remove_row(source_row + 1) diff --git a/model/ProjectModel/VarManage.py b/model/ProjectModel/VarManage.py index 1f847eb..3112c4a 100644 --- a/model/ProjectModel/VarManage.py +++ b/model/ProjectModel/VarManage.py @@ -1,6 +1,3 @@ - - -from ast import mod import re from numpy import var import pandas as pd @@ -41,10 +38,26 @@ class ModbusVarManage(object): @classmethod def importVarForm(self, varName, varType, des, address, slaveID, min, max, order, modbusType, varModel, index): + pattern = re.compile(r'[^0-9\.-]+') varClass = self.getVarClass(modbusType) if varType not in [0, 1, 3, 4]: errorInfo = '表{}第{}行导入失败,{}'.format(str(modbusType), str(index + 1), '变量类型有误') return errorInfo + if not varName or not address or not slaveID: + errorInfo = '表{}第{}行导入失败,有关键字段为空'.format(str(modbusType), str(index + 1)) + return errorInfo + elif re.findall(pattern, str(address)) or re.findall(pattern, str(slaveID)) or \ + re.findall(pattern, str(min)) or re.findall(pattern, str(max)): + errorInfo = '表{}第{}行导入失败,{}'.format(str(modbusType), str(index + 1), '寄存器地址、从站地址、工程量下限、工程量上限只能为数字') + return errorInfo + if varModel not in ['本地值', '远程值', '模拟值']: + errorInfo = '表{}第{}行导入失败,{}'.format(str(modbusType), str(index + 1), '变量模型有误') + return errorInfo + if order not in ['int', 'ABCD', 'BADC', 'CDAB', 'DCBA']: + errorInfo = '表{}第{}行导入失败,{}'.format(str(modbusType), str(index + 1), '字节顺序有误') + return errorInfo + + if varClass.getByName(varName): # 如果变量已存在,更新其信息 @@ -361,7 +374,7 @@ class TcRtdManage(object): return l = [] for var in vars: - l.append([var.id, var.varName, var.channelNumber,var.description, var.varType, var.min, var.max, var.unit, var.compensationVar, var.varModel]) + l.append([var.id, var.initialValue, var.varName, var.channelNumber,var.description, var.varType, var.min, var.max, var.unit, var.compensationVar, var.varModel]) return l @@ -435,13 +448,37 @@ class TcRtdManage(object): refreshCache() @classmethod - def importVarForm(self, varName, channelNumber, varType, des, min, max, compensationVar, varModel, unit): - if TcRtdVar.getByName(varName): - # 如果变量已存在,更新其信息 - TcRtdVar.update(channelNumber = channelNumber, description=des, varType=varType, min=min, max=max, compensationVar = compensationVar, unit = unit).where(TcRtdVar.varName == varName).execute() + def importVarForm(self, varName, channelNumber, varType, des, min, max, compensationVar, varModel, unit, initialValue='', index = None): + varTypeList = ['R', 'S', 'B', 'J', 'T', 'E', 'K', 'N', 'C', 'A'] + pattern = re.compile(r'[^0-9\.-]+') + # or re.findall(pattern, varName) + if not varName or not varType or not varModel or not min or not max or not channelNumber : + errorInfo = '表TCRTD第{}行导入失败,有关键字段为空'.format(str(index + 1)) + return errorInfo + if re.findall(pattern, str(channelNumber)) or re.findall(pattern, str(min)) or re.findall(pattern, str(max)): + errorInfo = '表TCRTD第{}行导入失败,{}'.format(str(index + 1), '通道号、工程量下限、工程量上限只能为数字') + return errorInfo + if varType not in varTypeList or varType != 'PT100': + errorInfo = '表TCRTD第{}行导入失败,{}'.format(str(index + 1), str(index + 1), '变量类型错误') + if varModel not in ['本地值', '远程值', '模拟值']: + errorInfo = '表TCRTD第{}行导入失败,{}'.format(str(index + 1), str(index + 1), '变量模型有误') + return errorInfo + + if TcRtdVar.getByChannelNumber(channelNumber): + # 如果通道号已存在,更新其信息 + if varType in varTypeList: + #导入热电偶 + TcRtdVar.update(varName = varName, channelNumber = channelNumber, description=des, varType=varType, + min=min, max=max, compensationVar = compensationVar, unit = unit, + initialValue=initialValue).where((TcRtdVar.channelNumber == channelNumber) & (TcRtdVar.varType != 'PT100')).execute() + else: + #导入热电阻 + TcRtdVar.update(varName = varName, channelNumber = channelNumber, description=des, varType=varType, + min=min, max=max, compensationVar = compensationVar, unit = unit, + initialValue=initialValue).where((TcRtdVar.channelNumber == channelNumber) & (TcRtdVar.varType == 'PT100')).execute() else: tcRtdVarType = TcRtdVar() - tcRtdVarType.createVar(varName = varName, channelNumber=channelNumber, des = des, varType = varType, min = min, max = max, compensationVar = compensationVar, varModel = varModel, unit = unit) + tcRtdVarType.createVar(varName = varName, channelNumber=channelNumber, des = des, varType = varType, min = min, max = max, compensationVar = compensationVar, varModel = varModel, unit = unit,nitialValue=initialValue) # 操作后刷新缓存 refreshCache() @@ -450,18 +487,19 @@ class AnalogManage(object): super(AnalogManage, self).__init__() @classmethod - def createVar(self, varName, channelNumber, varType, des, min, max, varModel, unit): + def createVar(self, varName, channelNumber, varType, des, min, max, varModel, unit, initialValue=''): # 创建变量 name = str(varName) channelNumber = str(channelNumber) des = str(des) varModel = str(varModel) unit = str(unit) + initialValue = str(initialValue) # if AnalogVar.getByName(name): # print('已有同名变量') # else: analogVarType = AnalogVar() - analogVarType.createVar(varName = name, channelNumber = channelNumber, des = des, varType = varType, min = min, max = max, varModel = varModel, unit=unit) + analogVarType.createVar(varName = name, channelNumber = channelNumber, des = des, varType = varType, min = min, max = max, varModel = varModel, unit=unit, initialValue=initialValue) # 操作后刷新缓存 refreshCache() @@ -473,7 +511,7 @@ class AnalogManage(object): return l = [] for var in vars: - l.append([var.id, var.varName, var.channelNumber, var.description, var.varType, var.min, var.max, var.unit, var.varModel]) + l.append([var.id, var.initialValue, var.varName, var.channelNumber, var.description, var.varType, var.min, var.max, var.varModel, var.unit]) return l @@ -488,7 +526,7 @@ class AnalogManage(object): @classmethod - def editVar(self, name, Nname, channelNumber, des, varType, min, max, unit): + def editVar(self, name, Nname, channelNumber, des, varType, min, max, unit, initialValue=''): # 修改变量信息 name = str(name) Nname = str(Nname) @@ -523,7 +561,7 @@ class AnalogManage(object): var = AnalogVar.getByName(name) if var: - return [var.id, var.varName, var. channelNumber, var.description, var.varType, var.min, var.max, var.unit, var.varModel] + return [var.id, var.varName, var. channelNumber, var.description, var.varType, var.min, var.max, var.varModel, var.unit] else: return False @@ -559,13 +597,27 @@ class AnalogManage(object): self.createVar(varName=name, channelNumber=str(i), varType='AI', des=des, min='100', max='200', varModel = '本地值', unit='mA') @classmethod - def importVarForm(self, varName, channelNumber, varType, des, min, max, varModel, unit): - if AnalogVar.getByName(varName): - # 如果变量已存在,更新其信息 - AnalogVar.update(channelNumber =channelNumber, description=des, varType=varType, min=min, max=max, unit = unit).where(AnalogVar.varName == varName).execute() + def importVarForm(self, varName, channelNumber, varType, des, min, max, varModel, unit, initialValue='', index = None): + pattern = re.compile(r'[^0-9\.-]+') + if not varName or not channelNumber or not varType or not varModel: + errorInfo = '表IO第{}行导入失败,有关键字段为空'.format(str(index + 1)) + return errorInfo + if re.findall(pattern, str(channelNumber)) or re.findall(pattern, str(min)) or re.findall(pattern, str(max)): + errorInfo = '表IO第{}行导入失败,{}'.format(str(index + 1), '通道号、工程量下限、工程量上限只能为数字') + return errorInfo + if varType not in ['AI', 'AO', 'DI', 'DO']: + errorInfo = '表IO第{}行导入失败,{}'.format(str(index + 1), '变量类型错误') + return errorInfo + if varModel not in ['本地值', '远程值', '模拟值']: + errorInfo = '表IO第{}行导入失败,{}'.format(str(index + 1), '变量模型有误') + return errorInfo + + if AnalogVar.getByChannelNumber(channelNumber): + # 如果通道号已存在,更新其信息 + AnalogVar.update(varName = varName, description=des, varType=varType, min=min, max=max, unit = unit, initialValue=initialValue).where((AnalogVar.channelNumber == channelNumber) & (AnalogVar.varType == varType)).execute() else: analogVarType = AnalogVar() - analogVarType.createVar(varName = varName, channelNumber = channelNumber, des = des, varType = varType, min = min, max = max, varModel = varModel,unit = unit) + analogVarType.createVar(varName = varName, channelNumber = channelNumber, des = des, varType = varType, min = min, max = max, varModel = varModel,unit = unit, initialValue=initialValue) # 操作后刷新缓存 refreshCache() @@ -699,6 +751,10 @@ class GlobalVarManager(object): @classmethod def importVar(cls, sheetName, data): """导入变量""" + # 在处理数据前,将所有NaN值替换为空字符串 + data = data.fillna('') + + errorConList = [] match sheetName: case 'ModbusTCP主站' | 'ModbusTCP从站' | 'ModbusRTU主站' | 'ModbusRTU从站': @@ -723,7 +779,7 @@ class GlobalVarManager(object): slaveID=row['从站地址'], min=row.get('工程量下限', ''), max=row.get('工程量上限', ''), - order=row.get('字节顺序', 'int'), + order=row.get('字节顺序', ''), modbusType=modbusType, varModel=row.get('值类型', ''), index=index @@ -745,26 +801,36 @@ class GlobalVarManager(object): try: if sheetName == 'IO': - importFunc( + errInfo = importFunc( varName=row['变量名'], channelNumber=row['通道序号'], - varType=row['变量类型'], + varType=row.get('变量类型', ''), des=row.get('变量描述', ''), min=row.get('工程量下限', ''), max=row.get('工程量上限', ''), - varModel=row.get('值类型', '') + unit=row.get('单位', ''), + varModel=row.get('值类型', ''), + initialValue=row.get('初始值', ''), + index=index ) + if errInfo: + errorConList.append(errInfo) else: # TCRTD - importFunc( + errInfo = importFunc( varName=row['变量名'], channelNumber=row['通道序号'], varType=row['变量类型'], des=row.get('变量描述', ''), min=row.get('工程量下限', ''), max=row.get('工程量上限', ''), + unit=row.get('单位', ''), compensationVar=row['补偿值'], - varModel=row.get('值类型', '') + varModel=row.get('值类型', ''), + initialValue=row.get('初始值', ''), + index=index ) + if errInfo: + errorConList.append(errInfo) except Exception as e: errorConList.append(f'第{index+1}行导入失败: {str(e)}') @@ -792,6 +858,8 @@ class GlobalVarManager(object): Globals.getValue(l).model.initTable() if errorConList: return '\r\n'.join(errorConList) + + diff --git a/utils/DBModels/ProtocolModel.py b/utils/DBModels/ProtocolModel.py index ff4d2b9..0d413fc 100644 --- a/utils/DBModels/ProtocolModel.py +++ b/utils/DBModels/ProtocolModel.py @@ -68,8 +68,8 @@ class ModBusVar(BaseModel): varType = IntegerField() createTime = CharField() description = CharField() - address = CharField() - slaveID = CharField() + address = IntegerField() + slaveID = IntegerField() min = CharField() max = CharField() order = CharField() @@ -84,6 +84,13 @@ class ModBusVar(BaseModel): except: return False + @classmethod + def getByChannelNumber(cls, channelNumber): + try: + return cls.get(cls.channelNumber == str(channelNumber)) + except: + return False + # 删除变量 @classmethod def deleteVar(cls, name): @@ -178,6 +185,7 @@ class TcRtdVar(BaseModel): compensationVar = CharField() varModel = IntegerField() unit = CharField(default='') + initialValue = CharField(default='') # 查询变量是否存在 @classmethod @@ -186,6 +194,13 @@ class TcRtdVar(BaseModel): return cls.get(cls.varName == str(varName)) except: return False + + @classmethod + def getByChannelNumber(cls, channelNumber): + try: + return cls.get(cls.channelNumber == str(channelNumber)) + except: + return False # 删除变量 @classmethod @@ -194,7 +209,7 @@ class TcRtdVar(BaseModel): query.execute() # 创建变量 - def createVar(self, varName, channelNumber, des, varType, min, max, compensationVar, varModel, unit=''): + def createVar(self, varName, channelNumber, des, varType, min, max, compensationVar, varModel, unit='', initialValue=''): self.varName = varName self.channelNumber = channelNumber self.description = des @@ -205,10 +220,11 @@ class TcRtdVar(BaseModel): self.compensationVar = compensationVar self.varModel = varModel self.unit = unit + self.initialValue = initialValue # print(self.createTime) self.save() - def initVar(self, varName, channelNumber, des, varType, min, max, compensationVar, varModel, unit=''): + def initVar(self, varName, channelNumber, des, varType, min, max, compensationVar, varModel, unit='', initialValue=''): self.varName = varName self.channelNumber = channelNumber self.description = des @@ -219,18 +235,20 @@ class TcRtdVar(BaseModel): self.compensationVar = compensationVar self.varModel = varModel self.unit = unit + self.initialValue = initialValue self.save() class AnalogVar(BaseModel): varName = CharField() - channelNumber = CharField() + channelNumber = IntegerField() createTime = CharField() description = CharField() - varType = IntegerField() + varType = CharField() min = CharField() max = CharField() varModel = IntegerField() unit = CharField(default='') + initialValue = IntegerField(default='') # 添加初始值字段 # 查询变量是否存在 @classmethod @@ -239,15 +257,26 @@ class AnalogVar(BaseModel): return cls.get(cls.varName == str(varName)) except: return False - - # 删除变量 + @classmethod + def getByChannelNumber(cls, channelNumber): + try: + return cls.get(cls.channelNumber == str(channelNumber)) + except: + return False + + @classmethod + def getByVarType(cls, varType): + try: + return cls.get(cls.varType == str(varType)) + except: + return False # 删除变量 @classmethod def deleteVar(cls, name): query = cls.delete().where(cls.varName == name) query.execute() # 创建变量 - def createVar(self, varName, channelNumber, des, varType, min, max, varModel, unit=''): + def createVar(self, varName, channelNumber, des, varType, min, max, varModel, unit='', initialValue=''): self.varName = varName self.channelNumber = channelNumber self.description = des @@ -257,10 +286,11 @@ class AnalogVar(BaseModel): self.max = max self.varModel = varModel self.unit = unit + self.initialValue = initialValue # print(self.createTime) self.save() - def initVar(self, varName, channelNumber, des, varType, min, max, varModel, unit=''): + def initVar(self, varName, channelNumber, des, varType, min, max, varModel, unit='', initialValue=''): self.varName = varName self.channelNumber = channelNumber self.description = des @@ -270,6 +300,7 @@ class AnalogVar(BaseModel): self.max = max self.varModel = varModel self.unit = unit + self.initialValue = initialValue # print(self.createTime) self.save()