From 6734107967f91f7f57dad2626564b3cb9908d93c Mon Sep 17 00:00:00 2001 From: "ZHANGXUXU\\95193" <951937200@qq.com> Date: Wed, 9 Apr 2025 19:04:52 +0800 Subject: [PATCH] =?UTF-8?q?20250409=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UI/Main/Main.py | 18 +- UI/ProjectManages/ProjectModel.py | 3 +- UI/VarManages/HartSimulateModel.py | 1 - UI/VarManages/ModbusModel.py | 137 +++++------ UI/VarManages/Thread.py | 3 - UI/VarManages/VarTable.py | 14 +- UI/VarManages/VarWidget.py | 9 +- model/ClientModel/RegisterManage.py | 1 - model/ProjectModel/ProjectManage.py | 17 +- model/ProjectModel/VarManage.py | 63 +++-- protocol/FF/FFProtocol.py | 236 ------------------- protocol/FF/FFSimulate.py | 63 ----- protocol/FF/NationalInstruments.Fieldbus.dll | Bin 105352 -> 0 bytes protocol/FF/__init__.py | 0 utils/DBModels/ProtocolModel.py | 15 +- 15 files changed, 140 insertions(+), 440 deletions(-) delete mode 100644 protocol/FF/FFProtocol.py delete mode 100644 protocol/FF/FFSimulate.py delete mode 100644 protocol/FF/NationalInstruments.Fieldbus.dll delete mode 100644 protocol/FF/__init__.py diff --git a/UI/Main/Main.py b/UI/Main/Main.py index ffa3aef..bd14721 100644 --- a/UI/Main/Main.py +++ b/UI/Main/Main.py @@ -84,7 +84,15 @@ class MainWindow(QMainWindow): self.projectWidget = ProjectWidgets() self.userWidget = UserWidgets() - self.ModBusWidget = VarWidgets() + + self.ModbusTcpMasterWidget = VarWidgets('ModbusTcpMaster') + self.ModbusTcpSlaveWidget = VarWidgets('ModbusTcpSlave') + self.ModbusRtuMasterWidget = VarWidgets('ModbusRtuMaster') + self.ModbusRtuSlaveWidget = VarWidgets('ModbusRtuSlave') + + modbusWidgetList = [self.ModbusTcpMasterWidget, self.ModbusTcpSlaveWidget, self.ModbusRtuMasterWidget, self.ModbusRtuSlaveWidget] + modbusNameList = ['MODBUSTCP主站', 'MODBUSTCP从站', 'MODBUSRTU主站', 'MODBUSRTU从站',] + self.trendWidget = TrendWidgets() self.SettingWidget = SettingWidget() self.hartWidget = HartWidgets() @@ -95,7 +103,7 @@ class MainWindow(QMainWindow): self.userWidget.setObjectName('userWidget') self.projectWidget.setObjectName('projectWidget') self.trendWidget.setObjectName('trendWidget') - self.ModBusWidget.setObjectName('varWidget') + # self.ModBusWidget.setObjectName('varWidget') self.analogWidget.setObjectName('analogWidget') self.hartsimulateWidget.setObjectName('hartsimulateWidget') @@ -103,8 +111,10 @@ class MainWindow(QMainWindow): self.rightWidget = QStackedWidget() self.rightWidget.setObjectName("rightWidget") self.rightWidget.addWidget(self.projectWidget) - - self.varManageTabWidget.addTab(self.ModBusWidget,'ModBus') + for widget, name in zip(modbusWidgetList, modbusNameList): + widget.setObjectName('varWidget') + self.varManageTabWidget.addTab(widget, name) + self.varManageTabWidget.addTab(self.analogWidget,'AIAO') self.varManageTabWidget.addTab(self.tcrtdWidget,'TCRTD') self.varManageTabWidget.addTab(self.hartWidget,'HART读取') diff --git a/UI/ProjectManages/ProjectModel.py b/UI/ProjectManages/ProjectModel.py index 7e94ee0..c1daebd 100644 --- a/UI/ProjectManages/ProjectModel.py +++ b/UI/ProjectManages/ProjectModel.py @@ -221,7 +221,8 @@ class ProjectButtonDelegate(QItemDelegate): ProjectManage.switchProject(str(self.parent().model.datas[sender.index[0]][1])) #初始化读取数据库数据 - modelLists = ['varTable', 'HartTable', 'TcRtdTable', 'AnalogTable', 'HartSimulateTable', 'userTable'] + modelLists = ['ModbusTcpMasterTable', 'ModbusTcpSlaveTable', 'ModbusRtuMasterTable', \ + 'ModbusRtuSlaveTable', 'HartTable', 'TcRtdTable', 'AnalogTable', 'HartSimulateTable', 'userTable'] for l in modelLists: Globals.getValue(l).model.initTable() Globals.getValue('HistoryWidget').exchangeProject() diff --git a/UI/VarManages/HartSimulateModel.py b/UI/VarManages/HartSimulateModel.py index 44808cd..29dd894 100644 --- a/UI/VarManages/HartSimulateModel.py +++ b/UI/VarManages/HartSimulateModel.py @@ -19,7 +19,6 @@ class HartSimulateModel(VarTableModel): def initTable(self): self.datas = [] # varDatas = None - proType = Globals.getValue('currentProType') # if proType in ['9']: varDatas = HartSimulateVarManage.getAllVar() diff --git a/UI/VarManages/ModbusModel.py b/UI/VarManages/ModbusModel.py index 75a2910..49ee30f 100644 --- a/UI/VarManages/ModbusModel.py +++ b/UI/VarManages/ModbusModel.py @@ -1,3 +1,4 @@ +from ast import mod import typing import sys @@ -35,7 +36,7 @@ class QPushButton(QtWidgets.QPushButton): class VarTableModel(QAbstractTableModel): ''' 变量表模型类''' - def __init__(self, header, data: list, table = None): + def __init__(self, header, data: list, modbusType = None, table = None): ''' header : 表头变量 data : 表格内容 @@ -48,16 +49,14 @@ class VarTableModel(QAbstractTableModel): self.supportedDragActions() self.table = table self.editableList = [] # 表格中可编辑项 - - + self.modbusType = modbusType def initTable(self): self.datas = [] self.editableList = [] - self.table.parent.initIcon() - # proType = Globals.getValue('currentProType') - - varDatas = ModbusVarManage.getAllVar() - + if self.table: + self.table.parent.initIcon() + varDatas = ModbusVarManage.getAllVar(self.modbusType) + if not varDatas: # self.layoutChanged.emit() self.table.proxy.invalidate() @@ -189,43 +188,27 @@ class VarTableModel(QAbstractTableModel): def refreshComboBox(self): #功能类型的index是5,通讯类型index是10 - for num in range(1,3): - for i in range(len(self.datas)): - cbRow = str('cb' + str(i) + str(num*5)) - index = self.index(i, int(num*5)) - delegate = self.table.itemDelegate(index) - delegate.paint(self.table, QStyleOptionViewItem(), index) - try: - comboBox = getattr(delegate, cbRow) - # print(comboBox, i, num, cbRow) - except Exception as e: - continue - if num == 1: - if self.datas[i][5] in [0, 1]: - comboBox.setCurrentIndex(self.datas[i][5]) - elif self.datas[i][5] in [3, 4]: - comboBox.setCurrentIndex(self.datas[i][5] - 1) - else: - comboBox.setCurrentIndex(-1) - if num == 2: - if self.datas[i][10] in [0, 1, 2, 3]: - comboBox.setCurrentIndex(self.datas[i][10]) - else: - comboBox.setCurrentIndex(-1) + + for i in range(len(self.datas)): + cbRow = str('cb' + str(i) + str(5)) + index = self.index(i, int(5)) + delegate = self.table.itemDelegate(index) + delegate.paint(self.table, QStyleOptionViewItem(), index) + try: + comboBox = getattr(delegate, cbRow) + # print(comboBox, i, num, cbRow) + except Exception as e: + continue + + if self.datas[i][5] in [0, 1]: + comboBox.setCurrentIndex(self.datas[i][5]) + elif self.datas[i][5] in [3, 4]: + comboBox.setCurrentIndex(self.datas[i][5] - 1) + else: + comboBox.setCurrentIndex(-1) + -class ModBusTCPSlaveModel(VarTableModel): - def __init__(self, header, data: list, table = None): - ''' - header : 表头变量 - data : 表格内容 - table : 缺省参数 - ''' - VarTableModel.__init__(self, header, data, table = table) - - - - @@ -324,10 +307,11 @@ class VarButtonDelegate(QItemDelegate): def indexChange(self): sender = self.sender() + modbusType = self.parent().modbusType index = sender.currentIndex() text = sender.itemText(index) name = self.parent().model.datas[sender.index[0]][3] - ModbusVarManage.editOrder(name, text) + ModbusVarManage.editOrder(name, text, modbusType) self.parent().model.datas[sender.index[0]][sender.index[1]] = text def start_action(self): @@ -385,50 +369,50 @@ class VarButtonDelegate(QItemDelegate): def edit_action(self): sender = self.sender() model = self.parent().model + modbusType = self.parent().modbusType fucationCbRow = str('cb' + str(sender.index[0]) + str(5)) fucationIndex = self.parent().model.index(sender.index[0], 5) fucationDelegate = self.parent().itemDelegate(fucationIndex) fucationCheckbox = getattr(fucationDelegate, fucationCbRow) - modbusTypeCbRow = str('cb' + str(sender.index[0]) + str(10)) - modbusTypeIndex = self.parent().model.index(sender.index[0], 10) - modbusTypeDelegate = self.parent().itemDelegate(modbusTypeIndex) - modbusTypeCheckbox = getattr(modbusTypeDelegate, modbusTypeCbRow) - if sender.isEdit: sender.setIcon(qtawesome.icon('fa.save', color='#1fbb6f')) sender.isEdit = False sender.oldName = model.datas[sender.index[0]][3] model.editableList.append(sender.index[0]) fucationCheckbox.setEnabled(True) - modbusTypeCheckbox.setEnabled(True) + else: varMes = model.datas[sender.index[0]] - name, des, varType, slaveID, address, min, max, modbusType, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10]), str(varMes[11]) + name, des, varType, slaveID, address, min, max, order = str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[-1]) # print(name, des, varType, slaveID, address, min, max, order) if not name or not varType: reply = QMessageBox.question(self.parent(), '警告', - "有字段为空", + "有字段为空或输入错误", QMessageBox.Yes) return - if sender.oldName and ModBusVar.getByName(sender.oldName): + if sender.oldName and Globals()[modbusType + 'Var'].getByName(sender.oldName): if sender.oldName == name or [varMes[3] for varMes in model.datas].count(name) < 2: - ModbusVarManage.editVar(name = sender.oldName, Nname = name, des = des, varType = varType, slaveID = slaveID, address = address, min = min, max = max, order = order, modbusType = modbusType) + ModbusVarManage.editVar(name = sender.oldName, Nname = name, des = des, + varType = varType, slaveID = slaveID, address = address, + min = min, max = max, order = order, modbusType = modbusType) else: QMessageBox.information(self.parent(), '提示', '已有同名变量') return else: - res = ModbusVarManage.createVar(varName = name, varType = varType, des = des, address = address, slaveID = slaveID, min = min, max = max, order = order, modbusType = modbusType) + res = ModbusVarManage.createVar(varName = name, varType = varType, des = des, + address = address, slaveID = slaveID, min = min, + max = max, order = order, modbusType = modbusType) if res: QMessageBox.information(self.parent(), '提示', '已有同名变量') return sender.setIcon(qtawesome.icon('fa.pencil', color='#4c8cf2')) rowIndex = sender.index[0] - varMes = ModbusVarManage.getByName(name) + varMes = ModbusVarManage.getByName(name, modbusType) varMes.append('int') varMes.insert(1, '') varMes.insert(2, '') @@ -437,7 +421,6 @@ class VarButtonDelegate(QItemDelegate): sender.isEdit = True fucationCheckbox.setEnabled(False) - modbusTypeCheckbox.setEnabled(False) model.editableList.remove(sender.index[0]) @@ -459,29 +442,22 @@ class VarButtonDelegate(QItemDelegate): class ModbusTypeBox(QItemDelegate): def __init__(self, parent=None): super(ModbusTypeBox, self).__init__(parent) - self.items = items - self.comboxType = comboxType - + def paint(self, painter, option, index): - if (index.column() == 5 or index.column() == 10) and index.row() not in self.parent().model.editableList: + if (index.column() == 5) and index.row() not in self.parent().model.editableList: data = self.parent().model.datas[index.row()] comBox = str('cb' + str(index.row()) + str(index.column())) setattr(self, comBox, QComboBox()) comboBox = getattr(self, comBox) - comboBox.addItems(self.items) - if self.comboxType == 'founctionCombox': - if self.parent().model.datas[index.row()][index.column()] in [0, 1]: - comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()]) - elif self.parent().model.datas[index.row()][index.column()] in [3, 4]: - comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()] - 1) - else: - comboBox.setCurrentIndex(-1) - elif self.comboxType == 'modbusTypeCombox': - if self.parent().model.datas[index.row()][index.column()] in [0, 1, 2, 3]: - comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()]) - else: - comboBox.setCurrentIndex(-1) - # self.parent().model.comboboxList.append(comboBox) + items = ['Coil Status', 'Input Status', 'Input Register', 'Holding Register'] + comboBox.addItems(items) + if self.parent().model.datas[index.row()][index.column()] in [0, 1]: + comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()]) + elif self.parent().model.datas[index.row()][index.column()] in [3, 4]: + comboBox.setCurrentIndex(self.parent().model.datas[index.row()][index.column()] - 1) + else: + comboBox.setCurrentIndex(0) + comboBox.currentIndexChanged.connect( self.indexChange) comboBox.setObjectName('ModbusTypeBox') @@ -515,10 +491,7 @@ class ModbusTypeBox(QItemDelegate): def indexChange(self): sender = self.sender() index = sender.currentIndex() - if self.comboxType == 'founctionCombox': - if index in [2, 3]: - index += 1 - self.parent().model.datas[sender.index[0]][sender.index[1]] = index - elif self.comboxType == 'modbusTypeCombox': - self.parent().model.datas[sender.index[0]][sender.index[1]] = index - + if index in [2, 3]: + index += 1 + self.parent().model.datas[sender.index[0]][sender.index[1]] = index + \ No newline at end of file diff --git a/UI/VarManages/Thread.py b/UI/VarManages/Thread.py index e775ee4..2444cee 100644 --- a/UI/VarManages/Thread.py +++ b/UI/VarManages/Thread.py @@ -1,10 +1,7 @@ import time from PyQt5.QtCore import QThread, pyqtSignal - -from UI.TrendManage.ActualTrendWidget import ActualTrend from protocol.TCP.RTDTC import RTDTCClient from protocol.TCP.Analog import AnalogClient -from protocol.FF.FFSimulate import FFSimulate from protocol.Hart.HartSimulate import HartSimulate from utils import Globals diff --git a/UI/VarManages/VarTable.py b/UI/VarManages/VarTable.py index 9755c43..acb26af 100644 --- a/UI/VarManages/VarTable.py +++ b/UI/VarManages/VarTable.py @@ -74,19 +74,19 @@ class CheckBoxHeader(QHeaderView): class VarTableView(QTableView): - def __init__(self, parent=None): + def __init__(self, modbusType, parent=None): super(VarTableView, self).__init__(parent) self.parent = parent + self.modbusType = modbusType self.setHeader() self.setupUi() def setHeader(self): - founctionItem = ['Coil Status', 'Input Status', 'Input Register', 'Holding Register'] - modbusTypeComboxItem = ['MODBUSTCP主站模式', 'MODBUSTCP从站模式', 'MODBUSRTU主站模式', 'MODBUSRTU从站模式'] - self.setItemDelegateForColumn(11, VarButtonDelegate(self)) - self.setItemDelegateForColumn(5, ModbusTypeBox(founctionItem, 'founctionCombox', self)) - self.setItemDelegateForColumn(10, ModbusTypeBox(modbusTypeComboxItem, 'modbusTypeCombox', self)) - self.model = VarTableModel(['ID', '强制值', '当前值', '变量名', '变量描述', '变量类型', '从站地址', '寄存器地址', '工程量下限', '工程量上限', '通讯类型', '操作'],[], table = self) + self.setItemDelegateForColumn(10, VarButtonDelegate(self)) + self.setItemDelegateForColumn(5, ModbusTypeBox(self)) + self.model = VarTableModel(['ID', '强制值', '当前值', '变量名', '变量描述', '变量类型', + '从站地址', '寄存器地址', '工程量下限', '工程量上限', '操作'], + [], modbusType = self.modbusType, table = self) def setupUi(self): self.setShowGrid(True) diff --git a/UI/VarManages/VarWidget.py b/UI/VarManages/VarWidget.py index 3cb87a4..ec39ccb 100644 --- a/UI/VarManages/VarWidget.py +++ b/UI/VarManages/VarWidget.py @@ -20,8 +20,9 @@ import re class VarWidgets(QtWidgets.QWidget): _isPopenOpen = False - def __init__(self, parent=None): + def __init__(self, modbusType, parent=None): super(VarWidgets, self).__init__(parent) + self.modbusType = modbusType self.setupUI() def setupUI(self): @@ -62,7 +63,7 @@ class VarWidgets(QtWidgets.QWidget): self.startProtocolBtn.setIconSize(QSize(22, 22)) self.startProtocolBtn.clicked.connect(self.startProtocol) - self.varView = VarTableView(self) + self.varView = VarTableView(self.modbusType, self) self.varView.setObjectName('varView') self.proxy = QtCore.QSortFilterProxyModel(self) self.proxy.setSourceModel(self.varView.model) @@ -75,7 +76,7 @@ class VarWidgets(QtWidgets.QWidget): self.timer.timeout.connect(self.proxy.invalidate) self.timer.start(50) # 启动timer - Globals.setValue('varTable', self.varView) + Globals.setValue(str(self.modbusType) + 'Table', self.varView) # self.varView.model.initTable() # [self.varView.model.append_data([1,1,1,1,1,1,1,1,1,1]) for x in range(100)] @@ -218,7 +219,7 @@ class VarWidgets(QtWidgets.QWidget): # check.sort(reverse=True) for i in check: varMes = self.varView.model.datas[i] - value, name, des, varType, slaveID, address, min, max, modbusType, order = str(varMes[1]), str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10]), str(varMes[11]) + value, name, des, varType, slaveID, address, min, max, order = str(varMes[1]), str(varMes[3]), str(varMes[4]), str(varMes[5]), str(varMes[6]), str(varMes[7]), str(varMes[8]), str(varMes[9]), str(varMes[10]), str(varMes[11]) pattern = re.compile(r'[^0-9\.-]+') if not value or re.findall(pattern, str(value)): reply = QMessageBox.question(self.parent(), diff --git a/model/ClientModel/RegisterManage.py b/model/ClientModel/RegisterManage.py index fbacc22..c7b5c4b 100644 --- a/model/ClientModel/RegisterManage.py +++ b/model/ClientModel/RegisterManage.py @@ -68,6 +68,5 @@ class Register: else: return False else: - print('ccc') return False diff --git a/model/ProjectModel/ProjectManage.py b/model/ProjectModel/ProjectManage.py index 3fac901..71c062c 100644 --- a/model/ProjectModel/ProjectManage.py +++ b/model/ProjectModel/ProjectManage.py @@ -22,8 +22,8 @@ from utils import Globals from utils.DBModels.ClientModels import Project, ClientDB from utils.DBModels.ProjectBaseModel import * -from utils.DBModels.ProtocolModel import ModBusVar, TCPSetting, RTUSetting, InfluxMem, HartVar, TcRtdVar, AnalogVar, \ - FFSimulateVar, HartSimulateVar +from utils.DBModels.ProtocolModel import ModbusTcpMasterVar, ModbusRtuMasterVar, ModbusRtuSlaveVar,\ + ModbusTcpSlaveVar, TCPSetting, RTUSetting, InfluxMem, HartVar, TcRtdVar, AnalogVar, HartSimulateVar from utils.DBModels.UserModels import User @@ -60,14 +60,13 @@ class ProjectManage(object): project_proxy.initialize(projectDB) projectDB.connect() - projectDB.create_tables([ModBusVar, User, TCPSetting, RTUSetting,\ - HartVar, TcRtdVar, FFSimulateVar, HartSimulateVar,AnalogVar,InfluxMem],safe=True) + projectDB.create_tables([ModbusTcpMasterVar, ModbusRtuMasterVar, ModbusRtuSlaveVar, \ + ModbusTcpSlaveVar, TCPSetting, User, TCPSetting, RTUSetting,HartVar, \ + TcRtdVar, HartSimulateVar, AnalogVar, InfluxMem],safe=True) - - HartVarManage().initVar() - AnalogManage().initVar() - TcRtdManage().initVar() - HartSimulateVarManage().initVar() + manageList = [HartVarManage(), AnalogManage(), TcRtdManage(), HartSimulateVarManage()] + for l in manageList: + l.initVar() UserManage.initUser() modbusMasterTcpSetting = TCPSetting() diff --git a/model/ProjectModel/VarManage.py b/model/ProjectModel/VarManage.py index 7ef5937..8caf925 100644 --- a/model/ProjectModel/VarManage.py +++ b/model/ProjectModel/VarManage.py @@ -2,15 +2,28 @@ import openpyxl from pytz import NonExistentTimeError -from utils.DBModels.ProtocolModel import ModBusVar, HartVar, TcRtdVar, AnalogVar, FFSimulateVar, HartSimulateVar +from utils.DBModels.ProtocolModel import ModbusTcpMasterVar, ModbusRtuMasterVar, ModbusRtuSlaveVar,\ + ModbusTcpSlaveVar, HartVar, TcRtdVar, AnalogVar, FFSimulateVar, HartSimulateVar from utils import Globals # ID 从站地址 变量名 变量描述 功能码 寄存器地址 工程量下限 工程量上限 class ModbusVarManage(object): + ModBusVarClass = { + 'ModbusTcpMaster': ModbusTcpMasterVar, + 'ModbusTcpSlave': ModbusRtuMasterVar, + 'ModbusRtuMaster': ModbusRtuSlaveVar, + 'ModbusRtuSlave': ModbusTcpSlaveVar, + } def __init__(self): super().__init__() + + + @classmethod + def getVarClass(self, modbusType): + """根据类型获取对应的变量类""" + return self.ModBusVarClass.get(modbusType) @classmethod def importModbusVar(self, path): @@ -25,7 +38,6 @@ class ModbusVarManage(object): addrIndex = None minIndex = None maxIndex = None - modbusType = None for index, cell in enumerate(list(ws.iter_rows())[0]): if cell.value in ['id', 'ID']: @@ -44,10 +56,8 @@ class ModbusVarManage(object): minIndex = index if cell.value == '工程量上限': maxIndex = index - if cell.value == '通讯类型': - modbusType = index # print(IDIndex, slaveIndex, nameIndex, desIndex, typeIndex, addrIndex, minIndex, maxIndex) - if IDIndex == None or slaveIndex == None or nameIndex == None or desIndex == None or typeIndex == None or addrIndex == None or minIndex == None or maxIndex == None or modbusType == NonExistentTimeError: + if IDIndex == None or slaveIndex == None or nameIndex == None or desIndex == None or typeIndex == None or addrIndex == None or minIndex == None or maxIndex == None: # print('表头错误') return '表头错误' errorConList = [] @@ -101,7 +111,7 @@ class ModbusVarManage(object): @classmethod - def createVar(self, varName, varType, des, address, slaveID, min, max, modbusType, order): + def createVar(self, varName, varType, des, address, slaveID, min, max, order, modbusType): # 创建变量 name = str(varName) des = str(des) @@ -111,24 +121,25 @@ class ModbusVarManage(object): min = str(min) max = str(max) order = order - modbusType = str(modbusType) - if ModBusVar.getByName(name): + if self.getVarClass(modbusType).getByName(name): return 1 else: - varModel = ModBusVar() - varModel.createVar(varName = varName, varType = varType, des = des, address = address, slaveID = slaveID, min = min, max = max, modbusType = modbusType, order = order) + + varModel =self.getVarClass(modbusType)() + varModel.createVar(varName = varName, varType = varType, des = des, address = address, slaveID = slaveID, min = min, max = max, order = order) @classmethod - def deleteVar(self, name): + def deleteVar(self, name, modbusType): # 删除变量 name = str(name) # print(name) - ModBusVar.deleteVar(name = name) + self.getVarClass(modbusType).deleteVar(name = name) @classmethod - def editVar(self, name, Nname, des, varType, slaveID, address, min, max, modbusType, order): + def editVar(self, name, Nname, des, varType, slaveID, address, min, max, order, modbusType): + # 修改变量信息 name = str(name) Nname = str(Nname) @@ -138,41 +149,41 @@ class ModbusVarManage(object): address = str(address) min = str(min) max = str(max) - modbusType = str(modbusType) if Nname == name: - ModBusVar.update(varName = Nname, description = des, varType = varType, address = address, slaveID = slaveID, min = min, max = max, modbusType = modbusType, order = order).where(ModBusVar.varName == name).execute() - elif ModBusVar.getByName(Nname): + self.getVarClass(modbusType).update(varName = Nname, description = des, varType = varType, address = address, slaveID = slaveID, min = min, max = max, order = order).where(self.getVarClass(modbusType).varName == name).execute() + elif self.getVarClass(modbusType).getByName(Nname): print('已有同名变量') return - elif not ModBusVar.getByName(name): + elif not self.getVarClass(modbusType).getByName(name): print('不存在的变量') return else: - ModBusVar.update(varName = Nname, description = des, varType = varType, address = address, slaveID = slaveID, min = min, max = max, modbusType = modbusType, order = order).where(ModBusVar.varName == name).execute() + self.getVarClass(modbusType).update(varName = Nname, description = des, varType = varType, address = address, slaveID = slaveID, min = min, max = max, order = order).where(self.getVarClass(modbusType).varName == name).execute() @classmethod - def editOrder(self, name, order): + def editOrder(self, name, order, modbusType): name = str(name) order = str(order) - ModBusVar.update(order = order).where(ModBusVar.varName == name).execute() + self.getVarClass(modbusType).update(order = order).where(self.getVarClass(modbusType).varName == name).execute() @classmethod - def getAllVar(self): + def getAllVar(self, modbusType): # 查询所有变量 - vars = ModBusVar.get_all() + + vars = self.getVarClass(modbusType).get_all() if vars is 'error': return l = [] for var in vars: - l.append([var.id, var.varName, var.description, var.varType, var.slaveID, var.address, var.min, var.max, var.modbusType, var.order]) + l.append([var.id, var.varName, var.description, var.varType, var.slaveID, var.address, var.min, var.max, var.order]) return l @classmethod - def getByName(self, name): + def getByName(self, name, modbusType): # 查询指定变量信息 - var = ModBusVar.getByName(name) + var = self.getVarClass(modbusType).getByName(name) if var: - return [var.id, var.varName, var.description, var.varType, var.slaveID, var.address, var.min, var.max, var.modbusType] + return [var.id, var.varName, var.description, var.varType, var.slaveID, var.address, var.min, var.max] else: return False diff --git a/protocol/FF/FFProtocol.py b/protocol/FF/FFProtocol.py deleted file mode 100644 index 8f6a9dc..0000000 --- a/protocol/FF/FFProtocol.py +++ /dev/null @@ -1,236 +0,0 @@ -from pythonnet import load -# load('coreclr') -import clr # 与其他模块不同此处不直接导入pythonnet 而是导入clr(python与c#交互核心) -dll_path = 'protocol\\FF\\NationalInstruments.Fieldbus' # 为了方便理解这里给到dll所在的绝对路径且包含dll文件本身 -clr.AddReference(dll_path) #加载c#库 -clr.AddReference('System.Collections') -clr.AddReference('System') -from NationalInstruments.FieldBus import Session, FBDate -from NationalInstruments.FieldBus.ParameterHandler import Parameter, ParameterType -from NationalInstruments.FieldBus.ElementHandler import * -from System.Collections.Generic import * -from System import * -# import numpy as np - - -# session = Session() -# session.Open() -# link = session.Links[0] -# link.Open() -# print([x.Tag for x in link.Devices]) -# dev = link.Devices[1] -# VFD = dev.GetVfdByOrdinalNumber(0) -# VFD.Open() -# blocks = VFD.Blocks -# print([x.Tag for x in blocks]) -# block = blocks[1] -# block.Open() -# Params = block.Parameters -# print([x.Type.ToString() + ' ' + x.Name for x in Params]) -# print(byte(10)) -class ParamItem(object): - def __init__(self, param): - self.param = param - self.name = param.Name - self.type = param.Type.ToString() - self.elemDict = {} - match(param.Type): - case ParameterType.ODT_SIMPLEVAR: - self.elements = [param.Element] - case ParameterType.ODT_ARRAY: - self.elements = param.Elements - case ParameterType.ODT_RECORD: - self.elements = param.Elements - - def getElements(self): - for elem in self.elements: - self.elemDict[elem.Name] = [elem.Type.ToString(), elem.ValueString(), elem] - return self.elemDict - - -class FFProtocol(object): - """docstring for FF""" - paramDict = {} - def __init__(self): - pass - - def open(self): - self.session = Session() - self.session.Open() - self.link = self.session.Links[0] - self.link.Open() - - - def getDevices(self): - self.devices = [x for x in self.link.Devices][1:] - for device in self.devices: - device.Open() - VFD = device.GetVfdByOrdinalNumber(0) - VFD.Open() - return [x.Tag for x in self.devices] - - def getBlocks(self, devTag): - device = self.link.GetDeviceByTag(devTag) - VFD = device.GetVfdByOrdinalNumber(0) - blocks = [x for x in VFD.Blocks] - for block in blocks: - block.Open() - return [x.Tag for x in blocks] - - def getParams(self, devTag, blockTag): - device = self.link.GetDeviceByTag(devTag) - VFD = device.GetVfdByOrdinalNumber(0) - block = VFD.GetBlockByTag(blockTag) - Params = block.Parameters - paramList = [] - for param in Params: - paramList.append(ParamItem(param = param)) - if devTag not in self.paramDict: - self.paramDict[devTag] = {blockTag : paramList} - else: - self.paramDict[devTag][blockTag] = paramList - # print(self.paramDict) - return paramList - - def refreshParams(self, reParams = None): - if reParams: - for param in reParams: - param.Read() - # print(reParams) - # for device, blockDict in self.paramDict.items(): - # for block, paramList in blockDict.items(): - # else: - # param.param.Read() - # for elem in param.elements: - # return elem.get_Value() - - def writeValue(self, param, elem, value): - param.Read() - match(elem.Type): - case ElementType.FF_BOOLEAN: - if value in [True, False]: - elem.Value = value - elif value in ['True', 'true']: - elem.Value = True - elif value in ['False', 'false']: - elem.Value = False - case ElementType.FF_INTEGER8 | ElementType.FF_INTEGER16: - value = int(value) - elem.Value = Int16(value) - case ElementType.FF_INTEGER32 | ElementType.FF_UNSIGNED16: - value = int(value) - elem.Value = Int32(value) - case ElementType.FF_UNSIGNED8: - value = int(value) - elem.Value = Byte(value) - case ElementType.FF_UNSIGNED32: - value = int(value) - elem.Value = Int64(value) - case ElementType.FF_FLOAT: - value = float(value) - elem.Value = Single(value) - case ElementType.FF_VISIBLE_STRING: - value = str(value) - elem.Value = value - case ElementType.FF_OCTET_STRING: - value = str(value) - if len(value) % 2 != 0: - return - startIndex = 0 - # byteArray = [x for x in range(int(len(value) / 2))] - byteArray = Array.CreateInstance(Byte, int(len(value) / 2)) - for i in range(int(len(value) / 2)): - varStr = value[startIndex:startIndex + 2] - startIndex += 2 - byteArray[i] = Byte(int(varStr)) - elem.Value = byteArray - case ElementType.FF_DATE: - value = str(value) - valueList = [int(x) for x in value.split(':')] - elem.Value.Year = Byte(valueList[0]) - elem.Value.Month = Byte(valueList[1]) - elem.Value.DayOfMonth =Byte(valueList[2]) - elem.Value.Hour = Byte(valueList[3]) - elem.Value.Minute = Byte(valueList[4]) - elem.Value.Millisecond = int(valueList[5]) - case ElementType.FF_TIMEOFDAY | ElementType.FF_TIME_DIFF: - value = str(value) - valueList = [int(x) for x in value.split(':')] - elem.Value.Day = int(valueList[0]) - elem.Value.Millisecond = Int64(valueList[1]) - case ElementType.FF_BIT_STRING: - value = str(value) - for s in value: - if s not in ['0', '1']: - return - if len(value) % 8 != 0: - return - j = -1 - byteArray = Array.CreateInstance(Byte, int(len(value) / 8)) - for i in range(len(value)): - if i % 8 == 0: - j += 1 - if value[i] == '1': - # print(type(byteArray[j])) - byteArray[j] += 1<<(7-(i % 8)) - byteArray[j] = Byte(byteArray[j]) - elem.Value = byteArray - case ElementType.FF_TIME_VALUE: - value = str(value) - valueList = [int(x) for x in value.split(':')] - elem.Value.Lower = Int64(valueList[0]) - elem.Value.Upper = Int64(valueList[1]) - - param.Write() - - - - def close(self): - for device in self.devices: - device.Close() - self.link.Close() - self.session.Close() - - -if __name__ == '__main__': - a = FFProtocol() - a.open() - devs = a.getDevices() - blocks = a.getBlocks(devs[0]) - - par = a.getParams(devs[0], blocks[0])[7] - - ele1 = par.getElements()['VALUE_1'][2] - ele2 = par.getElements()['VALUE_2'][2] - ele3 = par.getElements()['VALUE_3'][2] - ele4 = par.getElements()['VALUE_4'][2] - ele5 = par.getElements()['VALUE_5'][2] - ele6 = par.getElements()['VALUE_6'][2] - ele7 = par.getElements()['VALUE_7'][2] - ele8 = par.getElements()['VALUE_8'][2] - ele9 = par.getElements()['VALUE_9'][2] - ele10 = par.getElements()['VALUE_10'][2] - ele11 = par.getElements()['VALUE_11'][2] - ele12 = par.getElements()['VALUE_12'][2] - ele13 = par.getElements()['VALUE_13'][2] - ele14 = par.getElements()['VALUE_14'][2] - ele15 = par.getElements()['VALUE_15'][2] - - a.writeValue(par.param, ele1, True) - a.writeValue(par.param, ele2, 1) - a.writeValue(par.param, ele3, 2) - a.writeValue(par.param, ele4, 3) - a.writeValue(par.param, ele5, 4) - a.writeValue(par.param, ele6, 5) - a.writeValue(par.param, ele7, 6) - a.writeValue(par.param, ele8, 1.1) - a.writeValue(par.param, ele9, 'test') - a.writeValue(par.param, ele10, '9999494949494949494949494949494949494949494949494949494949494949') - a.writeValue(par.param, ele11, '23:02:18:14:49:50') - a.writeValue(par.param, ele12, '18:59') - a.writeValue(par.param, ele13, '25:60') - a.writeValue(par.param, ele14, '1111000000001111') - a.writeValue(par.param, ele15, '55:55') - - - a.close() \ No newline at end of file diff --git a/protocol/FF/FFSimulate.py b/protocol/FF/FFSimulate.py deleted file mode 100644 index a41b2ab..0000000 --- a/protocol/FF/FFSimulate.py +++ /dev/null @@ -1,63 +0,0 @@ -import sys -sys.path.append('../') -sys.path.append('../../') -sys.path.append('../../../') -from protocol.ModBus.rtuslave_example import RTUSlave - -import modbus_tk.defines as cst - -class FFSimulate(object): - def __init__(self): - self.rtuSlave = RTUSlave(port = 'COM12', baudrate = 9600, bytesize = 8, parity = 'N', stopbits = 1, xonxoff = 0) - self.AIAddr = [x for x in range(4100, 4107) if x % 2 == 0] - self.AOAddr = [x for x in range(4200, 4207) if x % 2 == 0] - self.DIAddr = [x for x in range(4300, 4304)] - self.DOAddr = [x for x in range(4400, 4404)] - self.writeList = self.AIAddr + self.DIAddr - self.readList = self.writeList + self.AOAddr + self.DOAddr - - def start(self): - self.rtuSlave.start() - try: - self.addSlave() - except: - pass - - def stop(self): - self.rtuSlave.server.stop() - - def addSlave(self): - self.rtuSlave.server.add_slave(1) - slave = self.rtuSlave.server.get_slave(1) - slave.add_block('4', cst.HOLDING_REGISTERS, 4000, 5000) - - def readValue(self): - valueList = [] - for index, address in enumerate(self.readList): - if index < 4 or 7 < index < 12: - order = 'ABCD' - else: - order = 'int' - value = self.rtuSlave.readValue(1, '4', address, order = order) - valueList.append(value) - return valueList - - def writeValue(self, index, value): - index = int(index) - if index < 4: - value = float(value) - order = 'ABCD' - else: - value = int(value) - order = 'int' - self.rtuSlave.setValue(1, '4', self.writeList[index], value, order = order) - - -if __name__ == '__main__': - a = FFSimulate() - a.start() - # a.addSlave() - a.writeValue(1, 16.5) - a.writeValue(7, 1) - print(a.readValue()) - print(a.writeList) \ No newline at end of file diff --git a/protocol/FF/NationalInstruments.Fieldbus.dll b/protocol/FF/NationalInstruments.Fieldbus.dll deleted file mode 100644 index 3c58a35eef92fc5a78f23f054321c1b598538627..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105352 zcmeEv34B!5+4s4#+?h-!A(Lei0%QRa#!M1+L`B&|a1Wb;8wgkdkzj%ghGB6*v_ZtJ zinxn)*Q#}^wQfblUDVR56s=n;t$V8$@%#UubMBoxnSj=}eZTkneJ?-mbI<>Ip7Wgj zoadZ-Gxy*lE>M1@Q~=j^-zoI~?)*1G=&s2!i1RBS%2)U1JYW5Qb|rJ|7L5YHEwPAjd%KQ`spj@ zbbsp5-d~rl-STy6+Fr57nIi|iyK%s(Wos(F{@ar7bN~MB#=lN@{F`N6eZN|~wd+SO zz1qI;_6lEH2)&^W_prI6NP;80=l1idm??nIpCWHdsJ3-3D)RI?@Ga9la&lA%=?I6D9xTv-?c%{r#bEy{Wl@>IYfyI0< z-SW(IeQnIGvF0dJ?`7zrtHipfwgY`C5V1?AjzRXwllEkhkd&&xRfDS@*Fao*;u?vI zec(`Bhv7OJ*9kkhW`Uoa<7@4T%Bu6V4%WA%zV*|$WAts3zD?D)T78?LZ%CHWksIFj z(>Dw)q9T1en787(1AHyuFG#T^eF-ERsq1MPP1jLCRU=Pmr6Z7kv1${yS<220 z)mwEwyBXDH*VX!U{f)0f-3AnzigQNHS75xbVUe)V(cVk(IF1BEK_ zwHS_uE1#V@hLg@wxHxd<<6;GdD>pSB7_R(s>KK?+y>Sh}#W3%@m~}RdgBj*5Hw;&D zP#}^V()tr{PH%-t(8WTR2wf($Stwcw(xpO|llp9_D0Y2z6y`lBS%UGHzZtzL@)Ejk zw?sFD5}3Rq^|tQ#{)Oa6?DOa7s3#MiKc~@%?YM`HuvBmlwg&sDUvc6_M|Z}DFM$MY zXH1NAJ9j)cS%v|_yh#F~HO=S)k=jt{lw8z4tq%C3-I6^T*j`5>4RiyO2273Y5ls%x zuvQwbteiGuTD*V0-Gc6HhG;Tsw@h?VxO8eX9Pj&-H_iKOJ(wQyC6EW(*Trf(2*YT0 ziaGLC=BGH4eL91ysxcMFtRZC&sw(6QdNG|7U5~mtb3<`E9y)(cLTbtx&uj}%t|NX_ zx)>erx5uZOPIbe$Mnr|$iuu>~M5+;=-OhUgUD57z&MGNM&si8Z-Z^V$ZDQKPnWD1l z{<==Nay!y#K9oxtPh#$qODxJ zCEcIwQ1c=TM%{_*7W6`ARt`0vx-$WKUgt5eo_8)dac6=PD8M{|WgxrLvc0d*C{so; z{^w*}_x;Y>xiVKbbZZ-ms@s|6!i=Qy(*0N(*}s0dv`?Yc_LPNH>J-GV0X7g|SP1wn z0hUhzPY}#E;Aw)>40xPio&ir1EHL01g3|%&n2!~mp=&v=T5k z1Z?aSb3?!ePBAwG>^LdrhJY>na*Ej@YNm+UAz;r-F+2WHJJaiI?B=76{Ofy}vCI3; z{f+;?*uA^cv0I^=6f=oZ?QWjjna7!Tx=7x!e964S`+sZRWnG~!0^h}*6TJRU3l;=t zxVIde4(n02o*B+9v|5gbBvFMi>MTbmrd4;<^Se4ToLh3YhOjiE?{RL1ABpybMe=t=&%7 zvznUp`tWaB&;DKgYSEAES7lC}xh411*?*V6HWTgQ?K3;~*Lrv6uh}hdI?dSg`ca!Y zSq7!P$0EH#cN}}XpWJvfSseW4EQG4oBTlEWESFJ>*vlxJE<>IFxt(9Z?Xg{gySA$_$G@f!2G*Yzkz){o!*Zy zyQ`V4GEdi2D-I7lYkDKn#GcXdO{H@D>#^%VS+I=XkCm=@DPj=ZN00&#AJ`}R$T;E_ zsvRYa;mvWO(lzmNiYACy{1fM=XvA-~Q@`Wd`M+%x{ePm3aHfE9bOc)Phxzy%M`+t0 zHjczD$I+SSFV1ku7)Q%Jf~<`T{X>qUbb6*&GP^(2>@LSqiD{#=k&U!(%yHBeWz?zZ z%JHwqgsI2TgB&_%AqL0M0|aLPm~n(c@XSZX5o364ueC}tQ)G$zrL1!ogJS$AZk~CchO*M3^FQ?;tuYfQ*ZV4|G9d@v5h-^{)KvDZe3pw zUjNSh;Tt>MHS{p`Hn-g^ce>≠7V7>J6Tx_`|$+s36p!Q%C=S{f_I~;Z*6z)Dbhx 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

soEAA9%%?wU^F@Mn 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 V4hW6f)+