370 lines
13 KiB
Python
Executable File
370 lines
13 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
import HVLibrary as hv
|
|
|
|
import sys
|
|
import datetime
|
|
import csv
|
|
import socket
|
|
import time
|
|
|
|
print("================== SOLARIS HV Controller for CAEN SY4527")
|
|
|
|
#-----------assign a port, to prevent the script run mulitple time
|
|
s = socket.socket()
|
|
host = socket.gethostname()
|
|
port = 4305
|
|
s.bind((host,port))
|
|
|
|
#------ database
|
|
import influxdb_client
|
|
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
|
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS
|
|
|
|
with open('INFLUX_TOKEN.txt', 'r') as f:
|
|
token = f.readline().replace('\n', '')
|
|
|
|
org = "Argonne National Laboratory"
|
|
databaseIP = "http://192.168.0.200:8086"
|
|
write_client = influxdb_client.InfluxDBClient(url=databaseIP, token=token, org=org)
|
|
bucket = "CAEN_SY4527"
|
|
write_api = write_client.write_api(write_options=ASYNCHRONOUS)
|
|
|
|
print("------- Database")
|
|
print(" IP : " + databaseIP)
|
|
print(" Buket : " + bucket)
|
|
print(" token : " + token)
|
|
|
|
pushToDB = False
|
|
|
|
print("--------- Generating GUI")
|
|
#------ GUI
|
|
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QCheckBox, QLineEdit, QLabel, QVBoxLayout, QWidget, QTabWidget, QGridLayout, QMessageBox, QFileDialog, QProgressBar
|
|
from PyQt6.QtCore import Qt, QThread, QTimer, QObject, pyqtSignal
|
|
from functools import partial
|
|
|
|
nMod = 2
|
|
nChPerMod = [48, 48]
|
|
updateTime = 3 #sec
|
|
|
|
######################################
|
|
|
|
bd = []
|
|
for k in range(nMod):
|
|
bd.append(hv.Board(3 + k))
|
|
|
|
ColStrList = ["Name", "Ch", 'On/Off', "Set V [V]", "Set I [uA]", "Out V [V]", "Out I [uA]"]
|
|
|
|
NameList = []
|
|
V0SetList = []
|
|
I0SetList = []
|
|
OnOffList = []
|
|
outVList = []
|
|
outIList = []
|
|
|
|
for k in range(nMod):
|
|
NameList.append(bd[k].GetPV('Name'))
|
|
V0SetList.append(bd[k].GetPV('V0Set'))
|
|
I0SetList.append(bd[k].GetPV('I0Set'))
|
|
OnOffList.append(bd[k].GetPV('Pw'))
|
|
outVList.append(bd[k].GetPV('VMon'))
|
|
outIList.append(bd[k].GetPV('IMon'))
|
|
|
|
class MyWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
|
|
self.setWindowTitle("Iseg Controller")
|
|
self.setGeometry(100, 100, 600, 200)
|
|
|
|
widget = QWidget()
|
|
layout = QVBoxLayout()
|
|
widget.setLayout(layout)
|
|
self.setCentralWidget(widget)
|
|
|
|
self.txtName = [[QLineEdit() for _ in range(rows)] for rows in nChPerMod]
|
|
self.txtV = [[QLineEdit() for _ in range(rows)] for rows in nChPerMod]
|
|
self.txtI = [[QLineEdit() for _ in range(rows)] for rows in nChPerMod]
|
|
self.txtVOut = [[QLineEdit() for _ in range(rows)] for rows in nChPerMod]
|
|
self.txtIOut = [[QLineEdit() for _ in range(rows)] for rows in nChPerMod]
|
|
self.chkON = [[QCheckBox() for _ in range(rows)] for rows in nChPerMod]
|
|
|
|
self.timer = QTimer(self)
|
|
self.timer.timeout.connect(self.updateTimer)
|
|
self.timer.start(updateTime*1000)
|
|
self.time = 0
|
|
|
|
#=========== database and refresh time
|
|
gLayout = QGridLayout()
|
|
layout.addLayout(gLayout)
|
|
|
|
# lbIP = QLabel("Database IP : ", self)
|
|
# lbIP.setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
# gLayout.addWidget(lbIP, 0, 0)
|
|
|
|
# self.txtIP = QLineEdit(self)
|
|
# self.txtIP.setText(IP)
|
|
# self.txtIP.textChanged.connect(partial(self.TextChange, self.txtIP))
|
|
# self.txtIP.returnPressed.connect(partial(self.UnSetTextColor, self.txtIP))
|
|
# gLayout.addWidget(self.txtIP, 0, 1)
|
|
|
|
lb1 = QLabel("Refresh period [sec] :", self)
|
|
lb1.setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
gLayout.addWidget(lb1, 1, 0)
|
|
|
|
self.txtRefresh = QLineEdit(self)
|
|
self.txtRefresh.setText(str(updateTime))
|
|
self.txtRefresh.textChanged.connect(partial(self.TextChange, self.txtRefresh))
|
|
self.txtRefresh.returnPressed.connect(self.SetTimer)
|
|
self.txtRefresh.returnPressed.connect(partial(self.UnSetTextColor, self.txtRefresh))
|
|
gLayout.addWidget(self.txtRefresh, 1, 1)
|
|
|
|
self.chkDB = QCheckBox("Enable DataBase Output", self)
|
|
gLayout.addWidget(self.chkDB, 0, 2)
|
|
|
|
#=========== set tab
|
|
self.tabWidget = QTabWidget(self)
|
|
layout.addWidget(self.tabWidget)
|
|
|
|
for k in range(0, nMod):
|
|
tab = QWidget(self)
|
|
layout_tab = QGridLayout()
|
|
layout_tab.setAlignment(Qt.AlignmentFlag.AlignTop)
|
|
tab.setLayout(layout_tab)
|
|
|
|
for index, lb in enumerate(ColStrList):
|
|
qlb = QLabel(lb, tab)
|
|
layout_tab.addWidget(qlb, 0, index)
|
|
|
|
for i in range(nChPerMod[k]) :
|
|
for j, lb in enumerate(ColStrList) :
|
|
#------------ name
|
|
if j == 0:
|
|
self.txtName[k][i].setText(NameList[k][i])
|
|
layout_tab.addWidget(self.txtName[k][i], 1+i, j)
|
|
|
|
self.txtName[k][i].returnPressed.connect(partial(self.SetName, k, i) )
|
|
self.txtName[k][i].returnPressed.connect(partial(self.UnSetTextColor, self.txtName[k][i]))
|
|
self.txtName[k][i].textChanged.connect(partial(self.TextChange, self.txtName[k][i]))
|
|
|
|
#------------ Ch
|
|
if j == 1:
|
|
qlb = QLabel(str(i), tab)
|
|
layout_tab.addWidget(qlb, 1+i, j, alignment=Qt.AlignmentFlag.AlignCenter)
|
|
|
|
#------------ On/Off
|
|
if j == 2:
|
|
self.chkON[k][i].setChecked( OnOffList[k][i] == 1)
|
|
layout_tab.addWidget(self.chkON[k][i], 1+i, j, alignment=Qt.AlignmentFlag.AlignCenter)
|
|
|
|
self.chkON[k][i].clicked.connect(partial(self.SetOnOff, k, i))
|
|
|
|
# #------------ V set
|
|
if j == 3:
|
|
self.txtV[k][i].setText(str(V0SetList[k][i]))
|
|
self.txtV[k][i].setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
layout_tab.addWidget(self.txtV[k][i], 1+i, j)
|
|
|
|
self.txtV[k][i].returnPressed.connect(partial(self.SetHV, k, i) )
|
|
self.txtV[k][i].returnPressed.connect(partial(self.UnSetTextColor, self.txtV[k][i]))
|
|
self.txtV[k][i].textChanged.connect(partial(self.TextChange, self.txtV[k][i]))
|
|
|
|
# #------------ I set
|
|
if j == 4:
|
|
self.txtI[k][i].setText(str(I0SetList[k][i]))
|
|
self.txtI[k][i].setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
layout_tab.addWidget(self.txtI[k][i], 1+i, j)
|
|
|
|
self.txtI[k][i].returnPressed.connect(partial(self.SetI, k, i) )
|
|
self.txtI[k][i].returnPressed.connect(partial(self.UnSetTextColor, self.txtI[k][i]))
|
|
self.txtI[k][i].textChanged.connect(partial(self.TextChange, self.txtI[k][i]))
|
|
|
|
# #------------ V out
|
|
if j == 5:
|
|
self.txtVOut[k][i].setText("{:.3f}".format(outVList[k][i]))
|
|
self.txtVOut[k][i].setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
layout_tab.addWidget(self.txtVOut[k][i], 1+i, j)
|
|
self.txtVOut[k][i].setReadOnly(True)
|
|
self.txtVOut[k][i].setStyleSheet("background-color: lightgrey; color: black;")
|
|
|
|
# #------------ I out
|
|
if j == 6:
|
|
self.txtIOut[k][i].setText("{:.3f}".format(outIList[k][i]))
|
|
self.txtIOut[k][i].setAlignment(Qt.AlignmentFlag.AlignRight)
|
|
layout_tab.addWidget(self.txtIOut[k][i], 1+i, j)
|
|
self.txtIOut[k][i].setReadOnly(True)
|
|
self.txtIOut[k][i].setStyleSheet("background-color: lightgrey; color: black;")
|
|
|
|
self.tabWidget.addTab(tab, "Mod-" + str(k+3))
|
|
|
|
#============= Save setting
|
|
sLayout = QGridLayout()
|
|
layout.addLayout(sLayout)
|
|
|
|
bLoad = QPushButton("Load", self)
|
|
bLoad.clicked.connect(self.LoadSetting)
|
|
sLayout.addWidget(bLoad, 0, 0)
|
|
|
|
self.txtFile = QLineEdit(self)
|
|
self.txtFile.textChanged.connect(partial(self.TextChange, self.txtFile))
|
|
sLayout.addWidget(self.txtFile, 0, 1)
|
|
|
|
bSave = QPushButton("Save", self)
|
|
bSave.clicked.connect(self.SaveSetting)
|
|
sLayout.addWidget(bSave, 0, 3)
|
|
|
|
#=================================
|
|
def UnSetTextColor(self, qLineEdit : QLineEdit):
|
|
qLineEdit.setStyleSheet("")
|
|
|
|
def TextChange(self, qLineEdit : QLineEdit):
|
|
qLineEdit.setStyleSheet("color : green;")
|
|
|
|
def SetTimer(self):
|
|
sec = float(self.txtRefresh.text())
|
|
self.timer.stop()
|
|
self.timer.start(int(sec * 1000))
|
|
|
|
#---------------------------------
|
|
def SetOnOff(self, mod, ch):
|
|
state = self.chkON[mod][ch].checkState()
|
|
if state == Qt.CheckState.Checked:
|
|
bd[mod].Channel[ch].SetPowerOnOff(1)
|
|
else:
|
|
bd[mod].Channel[ch].SetPowerOnOff(0)
|
|
|
|
value = bd[mod].Channel[ch].GetPowerOnOff()
|
|
OnOffList[mod][ch] = value
|
|
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(state) + " | " + str(value))
|
|
self.chkON[mod][ch].setChecked(value == 1)
|
|
|
|
#---------------------------------
|
|
def SetName(self, mod, ch):
|
|
value = self.txtName[mod][ch].text()
|
|
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + value)
|
|
bd[mod].Channel[ch].SetName(value)
|
|
newValue = bd[mod].Channel[ch].GetName()
|
|
NameList[mod][ch] = newValue
|
|
self.txtName[mod][ch].setText(newValue)
|
|
|
|
#---------------------------------
|
|
def SetHV(self, mod, ch):
|
|
value = float(self.txtV[mod][ch].text())
|
|
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(value))
|
|
bd[mod].Channel[ch].SetV0Set(value)
|
|
newValue = bd[mod].Channel[ch].GetV0Set()
|
|
V0SetList[mod][ch] = newValue
|
|
self.txtV[mod][ch].setText("{:.1f}".format(newValue))
|
|
|
|
#---------------------------------
|
|
def SetI(self, mod, ch):
|
|
value = float(self.txtI[mod][ch].text())
|
|
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(value))
|
|
bd[mod].Channel[ch].SetI0Set(value)
|
|
newValue = bd[mod].Channel[ch].GetI0Set()
|
|
I0SetList[mod][ch] = newValue
|
|
self.txtI[mod][ch].setText("{:.1f}".format(newValue))
|
|
|
|
#---------------------------------
|
|
def updateTimer(self):
|
|
self.time += 1
|
|
# print(f'Time: {self.time}')
|
|
|
|
outVList.clear()
|
|
outIList.clear()
|
|
for k in range(2):
|
|
outVList.append(bd[k].GetPV('VMon'))
|
|
outIList.append(bd[k].GetPV('IMon'))
|
|
|
|
if self.chkDB.checkState() == Qt.CheckState.Checked:
|
|
points = []
|
|
|
|
for k in range(0, nMod):
|
|
for i in range(bd[k].numCh) :
|
|
self.txtVOut[k][i].setText("{:.3f}".format(outVList[k][i]))
|
|
self.txtIOut[k][i].setText("{:.3f}".format(outIList[k][i]))
|
|
|
|
if self.chkDB.checkState() == Qt.CheckState.Checked:
|
|
points.append(Point("Voltage").tag("bd", int(k)).tag("Ch",int(i)).field("value",float(outVList[k][i])))
|
|
points.append(Point("LeakageCurrent").tag("bd", int(k)).tag("Ch",int(i)).field("value",float(outIList[k][i])))
|
|
|
|
if self.chkDB.checkState() == Qt.CheckState.Checked:
|
|
write_api.write(bucket=bucket, org=org, record=points)
|
|
|
|
def SaveSetting(self):
|
|
fileName = self.txtFile.text()
|
|
if fileName == "" :
|
|
msg_box = QMessageBox()
|
|
msg_box.setWindowTitle("Information")
|
|
msg_box.setText("Type file name first, then save.")
|
|
msg_box.setIcon(QMessageBox.Icon.Information)
|
|
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
|
|
msg_box.exec()
|
|
return
|
|
pos = fileName.rfind('.')
|
|
if pos == -1:
|
|
fileName = fileName + ".csv"
|
|
self.txtFile.setText(fileName)
|
|
outfile = open(fileName, "w")
|
|
csv_writer = csv.writer(outfile)
|
|
for k in range(0, nMod):
|
|
for i in range(bd[k].numCh) :
|
|
papap = [str(k), str(i), self.txtName[k][i].text(), self.txtV[k][i].text(),self.txtI[k][i].text()]
|
|
csv_writer.writerow( papap )
|
|
outfile.close()
|
|
self.txtFile.setStyleSheet("")
|
|
msg_box = QMessageBox()
|
|
msg_box.setWindowTitle("Information")
|
|
msg_box.setText("Setting saved to " + fileName + " as a csv file.")
|
|
msg_box.setIcon(QMessageBox.Icon.Information)
|
|
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
|
|
msg_box.exec()
|
|
|
|
def LoadSetting(self):
|
|
file_path, _ = QFileDialog.getOpenFileName(self, "Open File", "", "CSV Files (*.csv);;All Files (*)")
|
|
|
|
if file_path:
|
|
infile = open(file_path, "r")
|
|
csv_reader = csv.reader(infile)
|
|
row_count = sum(1 for row in csv_reader)
|
|
infile.seek(0)
|
|
count = 0
|
|
for row in csv_reader:
|
|
mod = row[0]
|
|
ch = row[1]
|
|
if mod.isdigit() and ch.isdigit():
|
|
chID = int(ch)
|
|
modID = int(mod)
|
|
|
|
NameList[modID][chID] = row[2]
|
|
V0SetList[modID][chID] = float(row[3])
|
|
I0SetList[modID][chID] = float(row[4])
|
|
|
|
for k in range(nMod):
|
|
bd[k].PutPV('Name', NameList[k])
|
|
bd[k].PutPV('V0Set', V0SetList[k])
|
|
bd[k].PutPV('I0Set', I0SetList[k])
|
|
|
|
self.txtFile.setText(file_path)
|
|
self.txtFile.setStyleSheet("")
|
|
|
|
NameList.clear()
|
|
V0SetList.clear()
|
|
I0SetList.clear()
|
|
for k in range(0, nMod):
|
|
NameList.append(bd[k].GetPV('Name'))
|
|
V0SetList.append(bd[k].GetPV('V0Set'))
|
|
I0SetList.append(bd[k].GetPV('I0Set'))
|
|
for i in range(bd[k].numCh) :
|
|
self.txtName[k][i].setText(NameList[k][i])
|
|
self.txtV[k][i].setText(str(V0SetList[k][i]))
|
|
self.txtI[k][i].setText(str(I0SetList[k][i]))
|
|
self.txtName[k][i].setStyleSheet("")
|
|
self.txtV[k][i].setStyleSheet("")
|
|
self.txtI[k][i].setStyleSheet("")
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
window = MyWindow()
|
|
window.show()
|
|
sys.exit(app.exec()) |