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.
373 lines
12 KiB
Python
373 lines
12 KiB
Python
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)
|
|
print(Globals.getValue('currentPro'))
|
|
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)
|
|
|
|
# if Globals.getValue('FFThread').isRunning():
|
|
# Globals.getValue('FFThread').reStart()
|
|
# return
|
|
# if proType == '7':
|
|
# Globals.getValue('FFThread').start()
|
|
|
|
# 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 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')
|
|
|
|
project = 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.createProject(n, proType, des)
|
|
projectList.append(n)
|
|
|
|
return projectList
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ProjectManage.importProject('1.project')
|
|
|