Tested to perform smoothly over a 'ssh -XYC' connection. Hard-coded /dev/ttyUSBn location, ideally it isn't changed too often for a given setup.
139 lines
5.0 KiB
Python
139 lines
5.0 KiB
Python
'''
|
|
v0.1 notes
|
|
---------
|
|
Relies on /dev/ttyUSB<N> channel being available to the user. Do it by running the command
|
|
|
|
sudo adduser <username> dialout
|
|
|
|
and logging out, then logging back in. Look at the output of ls /dev/ttyUSB* on a terminal before
|
|
and after plugging in the USB cable to the PC, to find out which channel to use in the input below.
|
|
|
|
'''
|
|
|
|
import serial
|
|
import time
|
|
import tkinter as tk
|
|
import ttkbootstrap as ttk
|
|
from ttkbootstrap.constants import *
|
|
|
|
port_name = '/dev/ttyUSB0'
|
|
baud_rate = 9600
|
|
timeout = 2
|
|
|
|
commands = {
|
|
"turn on": "$CMD:SET,CH:8,PAR:ON\n".encode('utf-8'),
|
|
"turn off": "$CMD:SET,CH:8,PAR:OFF\n".encode('utf-8'),
|
|
"get name": "$CMD:MON,CH:8,PAR:CRNAME\n".encode('utf-8')
|
|
}
|
|
|
|
class CrateControl(ttk.Frame):
|
|
def __init__(self,master):
|
|
super().__init__(master, padding=20)
|
|
try:
|
|
self.ser = serial.Serial(port=port_name,baudrate=baud_rate,timeout=timeout)
|
|
except serial.SerialException as e:
|
|
print(f"Error opening serial port: {e}")
|
|
self.destroy()
|
|
quit()
|
|
except Exception as e:
|
|
print(f"An unexpected error occurred: {e}")
|
|
self.destroy()
|
|
quit()
|
|
print(self.ser)
|
|
|
|
self.freeze_frame=False
|
|
self.last_return_string=""
|
|
self.style = ttk.Style()
|
|
self.style.configure('big.success-round-toggle.TCheckbutton',font=('Verdana',18),indicatorsize=40,padding=10)
|
|
|
|
self.name_of_crate = self.poll(8,"CRNAME","")
|
|
|
|
self.onoff_status = tk.IntVar(value=0)
|
|
self.status_label = ttk.Label(self, text="Ready",bootstyle="info",justify=LEFT)
|
|
self.onoff_button = ttk.Checkbutton(self,
|
|
text=self.name_of_crate,
|
|
variable=self.onoff_status,
|
|
onvalue=1,
|
|
offvalue=0,
|
|
width=20,
|
|
#style='success-round-toggle.Checkbutton',
|
|
command=self.toggle_onoff,
|
|
bootstyle='big success-round-toggle')
|
|
self.status_label.pack(expand=YES,fill=X,pady=10)
|
|
self.onoff_button.pack(expand=YES,fill=X,pady=10)
|
|
self.refresh_monitors()
|
|
|
|
#print('test')
|
|
#self.after(200,self.eventloop)
|
|
#self.refresh_monitors()
|
|
|
|
def poll(self, channel, polstring,replystring=""):
|
|
#while(self.ser.in_waiting > 0):
|
|
# self.ser.readline()
|
|
self.ser.write(str("$CMD:MON,CH:"+str(channel)+",PAR:"+polstring+"\n").encode('utf-8'))
|
|
retval = self.ser.readline().decode("utf-8").rstrip()
|
|
#retval = self.read_reply()
|
|
retval = retval.replace("#CMD:OK,VAL:","")
|
|
return "%s\t%s\t"%(retval,replystring)
|
|
#return self.read_reply()
|
|
|
|
def refresh_monitors(self):
|
|
#fullstatus="name: "
|
|
fullstatus="name\t\tset1\t\tmon1\t\tmon2\n"
|
|
for i in range(0,3):
|
|
reply=""
|
|
name = self.poll(i,"NAME")
|
|
setv = self.poll(i,"VSET","V")
|
|
monv = self.poll(i,"VMON","V")
|
|
moni = self.poll(i,"IMON","A")
|
|
#reply = name #.replace("#CMD:OK,VAL:"," ")
|
|
#reply = reply+"\n"
|
|
fullstatus += (name+setv+monv+moni+"\n")
|
|
fullstatus+="\t"
|
|
fullstatus+=self.poll(8,"FAN1","rpm\n")
|
|
fullstatus+=self.poll(8,"FAN2","rpm\n")
|
|
fullstatus+=self.poll(8,"FAN3","rpm\n")
|
|
fullstatus+=self.poll(8,"FUTEMP","C\n")
|
|
fullstatus+=self.poll(8,"PSTEMP","C\n")
|
|
status = self.poll(8,"CRST","\n")
|
|
fanstat = (int(status)&0x200==512)
|
|
crstat = int(status)&0x1
|
|
fullstatus+=("fan: %d\t crate: %d"%(fanstat,crstat))
|
|
if(crstat == 1 and fanstat == 1 and self.onoff_status.get() == 0):
|
|
self.onoff_status.set(1)
|
|
self.onoff_button.state(['selected'])
|
|
while(self.freeze_frame):
|
|
fullstatus = fullstatus
|
|
#print(fullstatus,self.freeze_frame)
|
|
self.status_label.config(text=fullstatus, bootstyle="info")
|
|
self.after(4000,self.refresh_monitors)
|
|
|
|
def read_reply(self):
|
|
totresp = ""
|
|
while(self.ser.in_waiting > 0):
|
|
response = self.ser.readline().decode('utf-8').rstrip() #rstrip gets rid of trailing whitespace
|
|
totresp = totresp+response
|
|
self.last_return_string=totresp
|
|
return totresp
|
|
|
|
def toggle_onoff(self):
|
|
self.freeze_frame=True
|
|
if(self.onoff_status.get()==1):
|
|
print("Turn ON")
|
|
self.ser.write(commands['turn on'])
|
|
time.sleep(0.2)
|
|
elif(self.onoff_status.get()==0):
|
|
print("Turn OFF")
|
|
self.ser.write(commands['turn off'])
|
|
time.sleep(0.2)
|
|
#print(self.read_reply())
|
|
while(self.ser.in_waiting > 0):
|
|
self.ser.readline()
|
|
self.freeze_frame=False
|
|
|
|
if __name__ == "__main__":
|
|
root = ttk.Window(themename='flatly',title="CrateControl")
|
|
app = CrateControl(root) #ttk.Window("Crate Control")
|
|
app.pack(expand=True,fill=BOTH)
|
|
root.mainloop()
|