First commit, working skeleton
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.
This commit is contained in:
parent
1204dd6c4d
commit
ad4bbf52e8
138
CrateControl.py
Normal file
138
CrateControl.py
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
'''
|
||||
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()
|
||||
Loading…
Reference in New Issue
Block a user