You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

406 lines
13 KiB
Python

11 months ago
import os
import shutil
import subprocess
import time
from PyQt5.QtCore import QTimer
import sys
import zipfile
sys.path.append('../../')
import json
from model.ClientModel.Client import Client
from model.HistoryDBModel.HistoryDBManage import HistoryDBManage
from model.ProjectModel.VarManage import TcRtdManage, AnalogManage, HartVarManage, \
HartSimulateVarManage
from model.UserModel.UserManage import UserManage
from utils import Globals
from utils.DBModels.ClientModels import Project, ClientDB
from utils.DBModels.ProjectBaseModel import *
11 months ago
from utils.DBModels.ProtocolModel import ModbusTcpMasterVar, ModbusRtuMasterVar, ModbusRtuSlaveVar,\
ModbusTcpSlaveVar, TCPSetting, RTUSetting, InfluxMem, HartVar, TcRtdVar, AnalogVar, HartSimulateVar
11 months ago
from utils.DBModels.UserModels import User
10 months ago
from utils.DBModels.DeviceModels import DeviceDB
11 months ago
9 months ago
from protocol.ProtocolManage import ProtocolManage
11 months ago
class ProjectManage(object):
"""工程管理类"""
def __init__(self):
super(ProjectManage, self).__init__()
@classmethod
def createProject(self, name, des):
# 创建工程
name = str(name)
des = str(des)
Client.initDB()
if Project.getByName(name):
return '已有同名工程'
else:
os.mkdir(os.path.join('project', name))
os.mkdir(os.path.join('project', name, 'db'))
os.mkdir(os.path.join('project', name, 'config'))
os.mkdir(os.path.join('project', name, 'log'))
with open(os.path.join('project', name, 'config', 'config.json'), 'w') as f:
json.dump({'description' : des}, f)
project = Project()
project.createProject(name, des)
dbPath = os.path.join('project', name, 'db', 'project.db')
projectDB = SqliteDatabase(dbPath)
project_proxy.initialize(projectDB)
projectDB.connect()
10 months ago
projectDB.create_tables([ModbusTcpMasterVar,
ModbusRtuMasterVar,
ModbusRtuSlaveVar,
ModbusTcpSlaveVar,
User,
TCPSetting,
RTUSetting,
HartVar,
TcRtdVar,
HartSimulateVar,
AnalogVar,
InfluxMem,
DeviceDB],safe=True)
11 months ago
11 months ago
manageList = [HartVarManage(), AnalogManage(), TcRtdManage(), HartSimulateVarManage()]
for l in manageList:
l.initVar()
11 months ago
UserManage.initUser()
modbusMasterTcpSetting = TCPSetting()
modbusMasterTcpSetting.initSetting('master')
modbusSlaveTcpSetting = TCPSetting()
modbusSlaveTcpSetting.initSetting('slave')
modbusMasterRtuSetting = RTUSetting()
modbusMasterRtuSetting.initSetting('master')
modbusMasterRtuSetting = RTUSetting()
modbusMasterRtuSetting.initSetting('slave')
projectDB.close()
@classmethod
def deleteProject(self, name):
# 删除工程
name = str(name)
# print(name)
# print(Globals.getValue('currentPro'))
Client.initDB()
if not Project.getByName(name):
print('不存在的工程', Project.getByName(name))
return
try:
if name == Globals.getValue('currentPro'):
self.closePopen()
Globals.getValue('currentProDB').close()
Globals.setValue('currentPro', None)
QTimer.singleShot(1000, lambda:shutil.rmtree(os.path.join('project', name)))
except OSError as e:
print(e)
Project.deleteProject(name = name)
@classmethod
def switchProject(self, name):
# 切换工程
currentDB = Globals.getValue('currentProDB')
9 months ago
currentProtocolManage = Globals.getValue('protocolManage')
11 months ago
if currentDB:
currentDB.close()
9 months ago
if Globals.getValue('protocolManage'):
currentProtocolManage.shutdown()
11 months ago
Client.initDB()
dbPath = os.path.join('project', name, 'db', 'project.db')
if ClientDB.getByName():
ClientDB.update(value = name).where(ClientDB.currentProject == '0').execute()
else:
clientDB = ClientDB()
clientDB.createMes(name)
projectDB = SqliteDatabase(dbPath)
project_proxy.initialize(projectDB)
projectDB.connect()
self.closePopen()
Globals.setValue('currentPro', name)
Globals.setValue('currentProDB', projectDB)
Globals.setValue('currentProType', 1)#切换工程
9 months ago
protocolManage = ProtocolManage()
# protocolManage.writeVariableValue('无源4-20mA输出通道1', 150)
# protocolManage.writeVariableValue('有源24V数字输出通道12', 1)
# protocolManage.writeVariableValue('热偶输出2', 40)
# protocolManage.writeVariableValue('热阻输出3', 50)
# print(protocolManage.readVariableValue('有源/无源4-20mA输入通道2'))
# print(protocolManage.readVariableValue('无源24V数字输入通道2'))
# print(a)
Globals.setValue('protocolManage', protocolManage)
11 months ago
# if Globals.getValue('FFThread').isRunning():
# Globals.getValue('FFThread').reStart()
# return
# initDB
@classmethod
def closePopen(self):
if Globals.getValue('currentProType') == '5':
RTDTCThread = Globals.getValue('RTDTCThread')
RTDTCThread.pause()
RTDTCThread.RTDTCCom.quit()
elif Globals.getValue('currentProType') == '6':
AnalogThread = Globals.getValue('AnalogThread')
AnalogThread.pause()
AnalogThread.AnalogCom.close()
elif Globals.getValue('currentProType') == '7':
Globals.getValue('FFThread').pause()
elif Globals.getValue('currentProType') == '8':
FFSimulateThread = Globals.getValue('FFSimulateThread')
FFSimulateThread.pause()
FFSimulateThread.FFSimulate.stop()
elif Globals.getValue('currentProType') == '9':
HartSimulateThread = Globals.getValue('HartSimulateThread')
HartSimulateThread.pause()
HartSimulateThread.HartSimulate.stop()
popen = Globals.getValue('popen')
popenBeat = Globals.getValue('beatPopen')
if popen:
popen.kill()
Globals.setValue('popen', None)
if popenBeat:
popenBeat.kill()
Globals.setValue('beatPopen', None)
@classmethod
def startProtocol(self):
# 0 : MODBUSTCP 主站模式
# 1 : MODBUSTCP 从站模式
# 2 : MODBUSRTU 主站模式
# 3 : MODBUSRTU 从站模式
# 5 : RTD/TC
proType = Globals.getValue('currentProType')
if proType == '0':
popen = subprocess.Popen("celery -A MBTCPMTask worker -l error -P eventlet --purge", stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBTCPMaster')
QTimer.singleShot(5000, lambda:self.startBeat(proType))
elif proType == '1':
popen = subprocess.Popen("celery -A MBTCPSTask worker -l error -P solo -c 2 --purge", stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBTCPSlave')
QTimer.singleShot(5000, lambda:self.startBeat(proType))
elif proType == '2':
popen = subprocess.Popen("celery -A MBRTUMTask worker -l error -P solo -c 2 --purge", stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBRTUMaster')
QTimer.singleShot(5000, lambda:self.startBeat(proType))
elif proType == '3':
popen = subprocess.Popen("celery -A MBRTUSTask worker -l error -P solo -c 2 --purge", stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBRTUSlave')
QTimer.singleShot(5000, lambda:self.startBeat(proType))
elif proType == '4':
popen = subprocess.Popen("celery -A HARTTask worker -l error -P solo -c 2 --purge", stdout=subprocess.PIPE, cwd = 'protocol/Celery/HARTCelery')
QTimer.singleShot(5000, lambda:self.startBeat(proType))
# popenBeat = subprocess.Popen('celery -A HARTTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/HARTCelery')
elif proType == '5':
RTDTCThread = Globals.getValue('RTDTCThread')
RTDTCThread.RTDTCCom.start()
if RTDTCThread.isRunning():
RTDTCThread.reStart()
else:
RTDTCThread.start()
return
elif proType in ['6']:
AnalogThread = Globals.getValue('AnalogThread')
AnalogThread.AnalogCom.connect()
AnalogThread.start()
return
elif proType in ['8']:
FFSimulateThread = Globals.getValue('FFSimulateThread')
FFSimulateThread.FFSimulate.start()
FFSimulateThread.start()
return
elif proType in ['9']:
HartSimulateThread = Globals.getValue('HartSimulateThread')
HartSimulateThread.HartSimulate.start()
HartSimulateThread.start()
return
else:
return
Globals.setValue('popen', popen)
# popen.kill()
@classmethod
def startBeat(self, proType):
if proType == '0':
popenBeat = subprocess.Popen('celery -A MBTCPMTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBTCPMaster')
elif proType == '1':
popenBeat = subprocess.Popen('celery -A MBTCPSTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBTCPSlave')
elif proType == '2':
popenBeat = subprocess.Popen('celery -A MBRTUMTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBRTUMaster')
elif proType == '3':
popenBeat = subprocess.Popen('celery -A MBRTUSTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/MBRTUSlave')
elif proType == '4':
popenBeat = subprocess.Popen('celery -A HARTTask beat', stdout=subprocess.PIPE, cwd = 'protocol/Celery/HARTCelery')
Globals.setValue('beatPopen', popenBeat)
@classmethod
def recordingHistory(self, projectName, cursor):
# 记录打开通讯的时间 并创建INFLUXDB表
curTime = time.time()
# influxMem = InfluxMem()
# influxMem.createMem(time)
curTime = float("{:.5f}".format(curTime))
cursor.execute('insert into InfluxMem (mem) values ({})'.format(str(curTime)))
historyDB = HistoryDBManage(mem = curTime, bucket = projectName, isCelery = True)
return historyDB
@classmethod
def editProject(self, name, Nname, des):
# 修改工程信息
name = str(name)
Nname = str(Nname)
des = str(des)
Client.initDB()
if name == Nname:
if name == Globals.getValue('currentPro'):
self.editCurProject(name, Nname, des)
return
Project.update(projectName = Nname, description = des).where(Project.projectName == name).execute()
QTimer.singleShot(1000, lambda:os.rename(os.path.join('project', name), os.path.join('project', Nname)))
elif Project.getByName(Nname):
return '已有同名工程'
elif not Project.getByName(name):
print('不存在的工程')
return
else:
if name == Globals.getValue('currentPro'):
self.editCurProject(name, Nname, des)
return
Project.update(projectName = Nname, description = des).where(Project.projectName == name).execute()
QTimer.singleShot(1000, lambda:os.rename(os.path.join('project', name), os.path.join('project', Nname)))
@classmethod
def editCurProject(self, name, Nname, des):
self.closePopen()
Globals.getValue('currentProDB').close()
Project.update(projectName = Nname, description = des).where(Project.projectName == name).execute()
QTimer.singleShot(1000, lambda:self.reNameCurProDir(name, Nname))
Globals.getValue('MainWindow').varWidget.initIcon()
Globals.setValue('currentPro', Nname)
@classmethod
def reNameCurProDir(self, name, Nname):
os.rename(os.path.join('project', name), os.path.join('project', Nname))
self.switchProject(Nname)
@classmethod
def getAllProject(self):
# 查询所有工程
projects = Project.get_all()
if projects is 'error':
return
l = []
for x in projects:
l.append([x.id, x.projectName, x.description, x.createTime])
return l
@classmethod
def getByName(self, name):
# 查询指定工程信息
project = Project.getByName(name)
if project:
return [project.id, project.projectName, project.description, project.createTime]
else:
return False
@classmethod
def exportProject(self, zipName, projects):
"""
将多个文件夹打包成一个zip文件
:param projects: 要打包的工程列表
:param zipName: 结果zip文件的名称
"""
folders = [os.path.join('project', project) for project in projects]
with zipfile.ZipFile(zipName, 'w', zipfile.ZIP_DEFLATED) as zipf:
for folder in folders:
for root, dirs, files in os.walk(folder):
for file in files:
# 获取文件路径
filePath = os.path.join(root, file)
# 获取文件相对于根目录的相对路径
relPath = os.path.join(*filePath.split(os.sep)[-3:])
# 使用修改后的路径将文件写入归档文件
zipf.write(filePath, arcname=relPath)
if not dirs and not files:
# 获取文件夹路径
folderPath = os.path.join(root)
# 获取文件夹相对于根目录的相对路径
relPath = os.path.join(*folderPath.split(os.sep)[-2:])
# 使用修改后的路径将文件夹写入归档文件
zipInfo = zipfile.ZipInfo(relPath + '/')
zipf.writestr(zipInfo, '')
# To parse a zip file and get the list of folders inside it, use the following code:
@classmethod
def importProject(self, zipName):
l = self.getAllProject()
allName = [x[1] for x in l]
with zipfile.ZipFile(zipName, 'r') as zipf:
zipProjects = set()
repeatProject = set()
[zipProjects.add(x.split('/')[0]) for x in zipf.namelist()]
for projectName in allName:
if projectName in zipProjects:
repeatProject.add(projectName)
if repeatProject:
return repeatProject
zipf.extractall('project')
projectList = []
for n in zipProjects:
jsonPath = os.path.join('project', n, 'config', 'config.json')
with open(jsonPath, 'r') as f:
data = json.load(f)
# proType = data['ProjectType']
des = data['description']
project = Project()
project.createProject(n, des)
projectList.append(n)
return projectList
# ProjectManage.importProject('1.project')