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.
DCS/model/ProjectModel/ProjectManage.py

373 lines
12 KiB
Python

2 years 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, FFSimulateManage, \
HartSimulateVarManage
from model.UserModel.UserManage import UserManage
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.UserModels import User
class ProjectManage(object):
"""工程管理类"""
def __init__(self):
super(ProjectManage, self).__init__()
@classmethod
def createProject(self, name, proType, 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({'ProjectType' : proType, 'description' : des}, f)
project = Project()
project.createProject(name, proType, des)
dbPath = os.path.join('project', name, 'db', 'project.db')
projectDB = SqliteDatabase(dbPath)
project_proxy.initialize(projectDB)
if proType == '0':
modelsArr = [ModBusVar, User, TCPSetting, InfluxMem]
if proType == '1':
modelsArr = [ModBusVar, User, TCPSetting, InfluxMem]
if proType == '2':
modelsArr = [ModBusVar, User, RTUSetting, InfluxMem]
if proType == '3':
modelsArr = [ModBusVar, User, RTUSetting, InfluxMem]
if proType == '4':
modelsArr = [HartVar, User, InfluxMem]
if proType == '5':
modelsArr = [TcRtdVar, User, InfluxMem]
if proType == '6':
modelsArr = [AnalogVar, User, InfluxMem]
if proType == '7':
modelsArr = [AnalogVar, User, InfluxMem]
if proType == '8':
modelsArr = [FFSimulateVar, User, InfluxMem]
if proType == '9':
modelsArr = [HartSimulateVar, User, InfluxMem]
projectDB.connect()
projectDB.create_tables(modelsArr, safe = True)
if proType in ['0', '1']:
TcpSetting = TCPSetting()
TcpSetting.initSetting()
elif proType in ['2', '3']:
RtuSetting = RTUSetting()
RtuSetting.initSetting()
elif proType in ['4']:
HartVarManage().initVar()
elif proType in ['5']:
TcRtdManage().initVar()
elif proType in ['6']:
AnalogManage().initVar()
elif proType in ['7']:
AnalogManage().initVar()
elif proType in ['8']:
FFSimulateManage().initVar()
elif proType in ['9']:
HartSimulateVarManage().initVar()
UserManage.initUser()
projectDB.close()
@classmethod
def deleteProject(self, name):
# 删除工程
name = str(name)
# print(name)
2 years ago
# print(Globals.getValue('currentPro'))
2 years ago
Client.initDB()
if name == Globals.getValue('currentPro'):
Globals.getValue('currentProDB').close()
if not Project.getByName(name):
print('不存在的工程', Project.getByName(name))
return
try:
shutil.rmtree(os.path.join('project', name))
except OSError as e:
print(e)
Project.deleteProject(name = name)
@classmethod
def switchProject(self, name, proType):
# 切换工程
currentDB = Globals.getValue('currentProDB')
if currentDB:
currentDB.close()
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', proType)
2 years ago
if Globals.getValue('FFThread').isRunning():
Globals.getValue('FFThread').reStart()
return
if proType == '7':
Globals.getValue('FFThread').start()
2 years ago
# 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)))
2 years ago
historyDB = HistoryDBManage(mem = curTime, bucket = projectName, isCelery = True)
2 years ago
return historyDB
@classmethod
def editProject(self, name, Nname, des):
# 修改工程信息
name = str(name)
Nname = str(Nname)
des = str(des)
Client.initDB()
if Project.getByName(Nname):
return '已有同名工程'
elif not Project.getByName(name):
print('不存在的工程')
return
else:
Project.update(projectName = Nname, description = des).where(Project.projectName == name).execute()
os.rename(os.path.join('project', name), os.path.join('project', 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, x.projectType])
return l
@classmethod
def getByName(self, name):
# 查询指定工程信息
project = Project.getByName(name)
if project:
return [project.id, project.projectName, project.description, project.createTime, project.projectType]
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')
2 years ago
projectList = []
2 years ago
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']
2 years ago
project = Project()
2 years ago
project.createProject(n, proType, des)
projectList.append(n)
return projectList
# ProjectManage.importProject('1.project')