added README.md, complete the influx for V2
This commit is contained in:
parent
760e2387d7
commit
6bbf93bf7d
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
__pycache__
|
||||
|
||||
*.txt
|
||||
|
||||
*.csv
|
211
HVGUI.py
211
HVGUI.py
|
@ -3,22 +3,59 @@
|
|||
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
|
||||
|
||||
ColStrList = ["Name", "Ch", 'On/Off', "Set V [V]", "Set I [uA]", "Out V [V]", "Out I [uA]"]
|
||||
|
||||
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 = []
|
||||
|
@ -26,6 +63,7 @@ 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'))
|
||||
|
@ -37,7 +75,7 @@ class MyWindow(QMainWindow):
|
|||
super().__init__()
|
||||
|
||||
self.setWindowTitle("Iseg Controller")
|
||||
self.setGeometry(100, 100, 500, 200)
|
||||
self.setGeometry(100, 100, 600, 200)
|
||||
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
@ -56,6 +94,34 @@ class MyWindow(QMainWindow):
|
|||
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)
|
||||
|
@ -74,7 +140,12 @@ class MyWindow(QMainWindow):
|
|||
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:
|
||||
|
@ -110,7 +181,7 @@ class MyWindow(QMainWindow):
|
|||
|
||||
# #------------ V out
|
||||
if j == 5:
|
||||
self.txtVOut[k][i].setText("{:.2f}".format(outVList[k][i]))
|
||||
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)
|
||||
|
@ -118,21 +189,41 @@ class MyWindow(QMainWindow):
|
|||
|
||||
# #------------ I out
|
||||
if j == 6:
|
||||
self.txtIOut[k][i].setText("{:.2f}".format(outIList[k][i]))
|
||||
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))
|
||||
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 : darkgreen;")
|
||||
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):
|
||||
|
@ -147,6 +238,15 @@ class MyWindow(QMainWindow):
|
|||
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())
|
||||
|
@ -168,31 +268,100 @@ class MyWindow(QMainWindow):
|
|||
#---------------------------------
|
||||
def updateTimer(self):
|
||||
self.time += 1
|
||||
print(f'Time: {self.time}')
|
||||
# outVList = mpod.GetAllOutputHV()
|
||||
# outIList = mpod.GetAllLC()
|
||||
# # print(outVList)
|
||||
|
||||
# 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 = []
|
||||
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("{:.2f}".format(outVList[k][i]))
|
||||
self.txtIOut[k][i].setText("{:.2f}".format(outIList[k][i]))
|
||||
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("Ch",int(chList[i] + 100 * k)).field("value",float(outVList[i])))
|
||||
# points.append(Point("LeakageCurrent").tag("Ch",int(chList[i] + 100 * k)).field("value",float(outIList[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)
|
||||
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)
|
||||
|
|
13
HVLibrary.py
13
HVLibrary.py
|
@ -98,6 +98,9 @@ class Channel:
|
|||
return get_value(self.bdCh + "PDown")
|
||||
|
||||
|
||||
def SetName(self, name : str):
|
||||
set_value(self.bdCh + "Name", name)
|
||||
|
||||
def SetV0Set(self, volt: float):
|
||||
set_value(self.bdCh + "V0Set", volt)
|
||||
|
||||
|
@ -164,3 +167,13 @@ class Board:
|
|||
for i in range(48):
|
||||
pvList.append('solarisHV:' + self.id + ":" + f"{i:03d}" + ":" + PV_Name)
|
||||
return epics.caget_many(pvList)
|
||||
|
||||
def PutPV(self, PV_Name : str, ValueList ):
|
||||
pvList = []
|
||||
for i in range(48):
|
||||
pvList.append('solarisHV:' + self.id + ":" + f"{i:03d}" + ":" + PV_Name)
|
||||
|
||||
if len(ValueList) == len(pvList):
|
||||
epics.caput_many(pvList, ValueList)
|
||||
else:
|
||||
print("PutPV: Value List size does not match channel number")
|
||||
|
|
28
README.md
Normal file
28
README.md
Normal file
|
@ -0,0 +1,28 @@
|
|||
# About
|
||||
|
||||
This is a HV controller for the python Qt6 GUI for CAEN SY4527 + A4528 CPU module. It communicate the built-in EPICS server to control and retrive parameters. It can also push the current Voltage and leakage current to influxDB via network connection.
|
||||
|
||||
# Require package
|
||||
|
||||
in Ubuntu 20+
|
||||
|
||||
~>sudo apt install python3-pyqt6 snmp snmp-mibs-downloader curl python3-pip
|
||||
~>python3 -m pip install pyqt6 influxdb-client
|
||||
|
||||
# Code
|
||||
|
||||
### HVLibrary.py
|
||||
|
||||
this is the library to setup the basic of epics. User need to modify the IP and hostName.
|
||||
|
||||
### HVGUI.py
|
||||
|
||||
this is the GUI code.
|
||||
|
||||
# DataBase connection
|
||||
|
||||
The program use the influxdb_client to push data to a influx database. In influxDB V2, a token is needed for secure connection. For security, a token should be save in INFLUX_TOKEN.txt, the program will load it for token. The IP address, org, bucket are hardcoded, so please change it as needed.
|
||||
|
||||
# Usage
|
||||
|
||||
~>./HVGUI.py
|
35
test.py
35
test.py
|
@ -52,6 +52,10 @@ import HVLibrary as hv
|
|||
# hv.epics.caput('solarisHV:03:015:Pw', 1)
|
||||
|
||||
# hv.epics.cainfo('solarisHV:03:015:Pw')
|
||||
# hv.epics.cainfo('solarisHV:03:015:VMon')
|
||||
# hv.epics.cainfo('solarisHV:03:015:V0Set')
|
||||
# hv.epics.cainfo('solarisHV:03:015:Status')
|
||||
# hv.epics.cainfo('solarisHV:03:BdStatus')
|
||||
|
||||
|
||||
# m1 = hv.epics.caget('solarisHV:03:015:Pw', use_monitor= False)
|
||||
|
@ -66,10 +70,31 @@ import HVLibrary as hv
|
|||
|
||||
# hv.epics.camonitor('solarisHV:03:015:Pw')
|
||||
|
||||
pvList = []
|
||||
for i in range(48):
|
||||
pvList.append('solarisHV:03:' + f"{i:03d}" + ":VMon")
|
||||
# pvList = []
|
||||
# pvValue = []
|
||||
# for i in range(10):
|
||||
# pvList.append('solarisHV:03:' + f"{i:03d}" + ":V0Set")
|
||||
# pvValue.append(10)
|
||||
|
||||
haha = hv.epics.caget_many(pvList)
|
||||
# # haha = hv.epics.caget_many(pvList)
|
||||
# haha = hv.epics.caput_many(pvList, pvValue)
|
||||
|
||||
# print(haha)
|
||||
|
||||
import influxdb_client
|
||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS
|
||||
|
||||
|
||||
ip = "192.168.0.200:8086"
|
||||
write_client = influxdb_client.InfluxDBClient(url=ip)
|
||||
bucket = "HV"
|
||||
write_api = write_client.write_api(write_options=ASYNCHRONOUS)
|
||||
|
||||
|
||||
points = []
|
||||
|
||||
points.append(Point("Voltage").tag("Bd", 3).tag("Ch", 0).field("value",float(10)))
|
||||
|
||||
write_api.write(bucket=bucket, record=points)
|
||||
|
||||
print(haha)
|
Loading…
Reference in New Issue
Block a user