Compare commits

..

1 Commits

3 changed files with 70 additions and 53 deletions

102
IsegGUI.py Executable file → Normal file
View File

@ -21,11 +21,16 @@ except:
token = None # Or assign a default value if needed token = None # Or assign a default value if needed
org = "FSUFoxLab" org = "FSUFoxLab"
databaseIP="https://fsunuc.physics.fsu.edu/influx/" ip = "https://fsunuc.physics.fsu.edu/influx/"
write_client = influxdb_client.InfluxDBClient(url=databaseIP, token=token, org=org) write_client = influxdb_client.InfluxDBClient(url=ip, token=token, org=org)
bucket = "ISEG" bucket = "ISEG"
# write_api = write_client.write_api(write_options=ASYNCHRONOUS) write_api = write_client.write_api(write_options=ASYNCHRONOUS)
write_api = write_client.write_api(write_options=SYNCHRONOUS)
#assign a port, to prevent the script run mulitple time
s = socket.socket()
host = socket.gethostname()
port = 4305
s.bind((host,port))
nArg = len(sys.argv) nArg = len(sys.argv)
@ -37,16 +42,9 @@ else :
#Sergio MPOD 128.186.111.101 #Sergio MPOD 128.186.111.101
#ANASEN MPOD 128.186.111.208 #ANASEN MPOD 128.186.111.208
databaseIP="128.186.111.108"
pushToDB = False pushToDB = False
#============== assign a port, to prevent the script run mulitple time
s = socket.socket()
host = socket.gethostname()
port = 4300 + int(IP[-3:])
print("using port " + str(port))
s.bind((host,port))
#===================== GUI #===================== GUI
mpod = iseg.Mpod(IP) mpod = iseg.Mpod(IP)
@ -110,7 +108,7 @@ class MyWindow(QMainWindow):
gLayout.addWidget(lbIP, 0, 0) gLayout.addWidget(lbIP, 0, 0)
self.txtIP = QLineEdit(self) self.txtIP = QLineEdit(self)
self.txtIP.setText(databaseIP) self.txtIP.setText("128.186.111.107")
self.txtIP.textChanged.connect(partial(self.TextChange, self.txtIP)) self.txtIP.textChanged.connect(partial(self.TextChange, self.txtIP))
self.txtIP.returnPressed.connect(partial(self.UnSetTextColor, self.txtIP)) self.txtIP.returnPressed.connect(partial(self.UnSetTextColor, self.txtIP))
gLayout.addWidget(self.txtIP, 0, 1) gLayout.addWidget(self.txtIP, 0, 1)
@ -132,13 +130,14 @@ class MyWindow(QMainWindow):
self.txtRefresh.returnPressed.connect(partial(self.UnSetTextColor, self.txtRefresh)) self.txtRefresh.returnPressed.connect(partial(self.UnSetTextColor, self.txtRefresh))
gLayout.addWidget(self.txtRefresh, 1, 1) gLayout.addWidget(self.txtRefresh, 1, 1)
self.AllChkOn = QPushButton("Switch all channels On.")
gLayout.addWidget(self.AllChkOn, 2, 1)
self.AllChkOn.clicked.connect(partial(self.SwitchOnAllCh))
self.AllChkOff = QPushButton("Switch all channels off.") self.AllChkOff = QPushButton("Switch all channels off.")
gLayout.addWidget(self.AllChkOff, 3, 1) gLayout.addWidget(self.AllChkOff, 2, 1)
self.AllChkOff.clicked.connect(partial(self.SwitchOffAllCh)) self.AllChkOff.clicked.connect(partial(self.SetAllOnOff))
#-------------------Jake added
self.btnReset = QPushButton("Reset Module Faults (Clear 10)")
gLayout.addWidget(self.btnReset, 2, 2)
self.btnReset.clicked.connect(self.ResetAction)
#=========== set tab #=========== set tab
self.tabWidget = QTabWidget(self) self.tabWidget = QTabWidget(self)
@ -271,11 +270,8 @@ class MyWindow(QMainWindow):
# print(str(modID) + "," + str(chID)) # print(str(modID) + "," + str(chID))
self.txtName[modID][chID].setText(row[0]) self.txtName[modID][chID].setText(row[0])
self.txtName[modID][chID].setStyleSheet("")
self.txtV[modID][chID].setText(row[2]) self.txtV[modID][chID].setText(row[2])
self.txtV[modID][chID].setStyleSheet("")
self.txtI[modID][chID].setText(row[3]) self.txtI[modID][chID].setText(row[3])
self.txtI[modID][chID].setStyleSheet("")
# print("Setting " + row[1] ) # print("Setting " + row[1] )
mpod.SetHV(int(ch[1:]), float(row[2])) mpod.SetHV(int(ch[1:]), float(row[2]))
@ -300,33 +296,25 @@ class MyWindow(QMainWindow):
self.timer.start(int(sec * 1000)) self.timer.start(int(sec * 1000))
def SetHV(self, mod, ch): def SetHV(self, mod, ch):
# Use the actual channel address from our list
ch_addr = modChList[mod][ch]
value = float(self.txtV[mod][ch].text()) value = float(self.txtV[mod][ch].text())
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(value)) print(f"Setting Ch {ch_addr} to {value} V")
mpod.SetHV( mod*100 + ch, value)
newValue = mpod.GetHV(mod*100+ch) mpod.SetHV(ch_addr, value)
newValue = mpod.GetHV(ch_addr)
self.txtV[mod][ch].setText("{:.1f}".format(newValue)) self.txtV[mod][ch].setText("{:.1f}".format(newValue))
def SetI(self, mod, ch): def SetI(self, mod, ch):
ch_addr = modChList[mod][ch]
value = float(self.txtI[mod][ch].text()) value = float(self.txtI[mod][ch].text())
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(value)) print(f"Setting Ch {ch_addr} limit to {value} mA")
mpod.SetCurrent( mod*100 + ch, value/1000.)
newValue = mpod.GetCurrent(mod*100+ch) * 1000. mpod.SetCurrent(ch_addr, value/1000.)
self.txtI[mod][ch].setText("{:.2f}".format(newValue)) newValue = mpod.GetCurrent(ch_addr)
self.txtI[mod][ch].setText("{:.1f}".format(newValue))
def SwitchOnAllCh(self): def SetAllOnOff(self):
for k in range(0, nMod):
for ch, a in enumerate(modChList[k]) :
state = self.chkON[k][ch].checkState()
if state != Qt.CheckState.Checked:
print("Switching On Mod-%d, ch-%d" % (k, ch))
mpod.SwitchOnHV( int(k) * 100 + int(ch), 1)
self.chkON[k][ch].setChecked(True)
onOffList[sum(nChPerMod[:k]) + ch] = 1
time.sleep(0.01) # wait 10 mili-sec
print("========== done")
def SwitchOffAllCh(self):
for k in range(0, nMod): for k in range(0, nMod):
for ch, a in enumerate(modChList[k]) : for ch, a in enumerate(modChList[k]) :
state = self.chkON[k][ch].checkState() state = self.chkON[k][ch].checkState()
@ -338,17 +326,30 @@ class MyWindow(QMainWindow):
time.sleep(0.01) # wait 10 mili-sec time.sleep(0.01) # wait 10 mili-sec
print("========== done") print("========== done")
#-------------Jake added
def ResetAction(self):
print("Clearing faults channel-by-channel...")
# Loop through all modules
for k in range(0, nMod):
# Loop through all channels in this module
for i, ch_addr in enumerate(modChList[k]):
# Reset each specific channel (e.g., 100, 101, 400...)
mpod.ResetChannel(ch_addr)
time.sleep(0.01) # 10ms delay to avoid flooding the SNMP bus
time.sleep(0.5)
self.updateTimer()
print("Individual channel resets sent. Check if the 'OK' LED is green.")
def SetOnOff(self, mod, ch): def SetOnOff(self, mod, ch):
ch_addr = modChList[mod][ch] # Get real address (e.g. 100)
state = self.chkON[mod][ch].checkState() state = self.chkON[mod][ch].checkState()
if state == Qt.CheckState.Checked:
if onOffList[sum(nChPerMod[:mod]) + ch] == 3 : if state == Qt.CheckState.Checked:
mpod.SwitchOnHV(mod*100 + ch, 2) # Use the address instead of the mod*100 math
mpod.SwitchOnHV( mod*100 + ch, 1) mpod.SwitchOnHV(ch_addr, 1)
onOffList[sum(nChPerMod[:mod]) + ch] = 1
else: else:
mpod.SwitchOnHV( mod*100 + ch, 0) mpod.SwitchOnHV(ch_addr, 0)
onOffList[sum(nChPerMod[:mod]) + ch] = 0
value = mpod.IsHVOn(mod*100 + ch) value = mpod.IsHVOn(mod*100 + ch)
print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(state) + " | " + str(onOffList[sum(nChPerMod[:mod]) + ch]) + " | " + str(value)) print("mod : " + str(mod) + ", ch : " + str(ch) + " | " + str(state) + " | " + str(onOffList[sum(nChPerMod[:mod]) + ch]) + " | " + str(value))
@ -385,7 +386,6 @@ class MyWindow(QMainWindow):
points.append(Point("LeakageCurrent").tag("Ch",int(chList[i] + 100 * k)).field("value",float(outIList[sum(nChPerMod[:k]) + i]))) points.append(Point("LeakageCurrent").tag("Ch",int(chList[i] + 100 * k)).field("value",float(outIList[sum(nChPerMod[:k]) + i])))
if self.chkDB.checkState() == Qt.CheckState.Checked: if self.chkDB.checkState() == Qt.CheckState.Checked:
write_api.write(bucket=bucket, org=org, record=points) write_api.write(bucket=bucket, org=org, record=points)
if __name__ == "__main__": if __name__ == "__main__":

17
IsegLibrary.py Executable file → Normal file
View File

@ -232,6 +232,20 @@ class Mpod:
except: except:
print("either ch is not int or rate is not float") print("either ch is not int or rate is not float")
#-------------------------Jake added functions for a channel reset:
def ResetChannel(self, ch):
"""Sends the clear events signal (10) to a specific channel."""
if (self.isConnected == False): return 0
# 10 is the magic number to clear latched trips/errors
return self.SendCmd(1, "outputSwitch.u" + str(ch) + " i " + str(10))
def ResetModule(self, modIndex):
"""Sends the clear events signal to an entire module group."""
if (self.isConnected == False): return 0
# Try removing the 'u' prefix which is specific to output channels
# and using modIndex + 1 since SNMP tables are 1-indexed.
return self.SendCmd(1, "groupsSwitch." + str(modIndex + 1) + " i " + str(10))
#===================== Auxliary function #===================== Auxliary function
def SplitChList(chList): def SplitChList(chList):
@ -249,6 +263,9 @@ def SplitChList(chList):
for i in range(0, len(sep)-1): for i in range(0, len(sep)-1):
newChList.append( chList[sep[i]:sep[i+1]] ) newChList.append( chList[sep[i]:sep[i+1]] )
return newChList return newChList
#===================== SandBox #===================== SandBox
#mpod = Mpod("128.186.111.101") #mpod = Mpod("128.186.111.101")

View File

@ -2,7 +2,7 @@
in Ubuntu 20+ in Ubuntu 20+
~>sudo apt install python3-pyqt6 snmp snmp-mibs-downloader curl python3-pip libxcb-cursor0 ~>sudo apt install python3-pyqt6 snmp snmp-mibs-downloader curl python3-pip
~>python3 -m pip install pyqt6 influxdb-client ~>python3 -m pip install pyqt6 influxdb-client
also, download the https://fsunuc.physics.fsu.edu/wiki/images/5/53/WIENER-CRATE-MIB.txt and put in /usr/share/snmp/mibs/ also, download the https://fsunuc.physics.fsu.edu/wiki/images/5/53/WIENER-CRATE-MIB.txt and put in /usr/share/snmp/mibs/
@ -18,4 +18,4 @@ for influxDB V1, simply put the database IP. since 2024, we upgraded to influxDB
# old GUI using PySimpleGUI # old GUI using PySimpleGUI
Since the PySimpleGUI think user should register, so We use Qt6. The IsegHVController.py is no longer maintain. Since the PySimpleGUI think user should register, so We use Qt6. The IsegHVController.py is no longer maintain.