self_demo_gui.py

self_demo_gui.py
# This File : self_demo_gui.py
# Date      : 12/28/2022
# Rev       : 1.0

# https://www.pythontutorial.net/tkinter/tkinter-grid/
# https://realpython.com/python-gui-tkinter/

# widget relief : tk.FLAT SUNKEN RAISED GROOVE RIDGE


import serial
import serial.tools.list_ports

import tkinter as tk

global ser
global ser_open

ser_open = False



# text terminal
global term_numl
global term_num
term_numl = 25
term_num  =  0

def  term_addLine(lstr):
  global term_numl
  global term_num
  global ser
  global ser_open

  txt_uart.configure(state='normal')

  if (term_num == term_numl):
    txt_uart.delete("1.0", "2.0")
  else:
    term_num += 1

  if (term_num > 1):
    jstr = '\n' + lstr[0:80].rstrip()
  else:
    jstr = lstr[0:80].rstrip()

  txt_uart.insert(str(float(term_num)), jstr)
  txt_uart.configure(state='disabled')

dcnt = 0
dumpStr = ""
def ser_dump(event = None):
  global ser
  global ser_open
  global dcnt
  global dumpStr

  if (ser_open):
    try:
      dumpStr = dumpStr + ser.read(100).decode('utf-8')
    except:
      dumpStr = ""

    while (True):
      bdx = dumpStr.find('\n\r\n')
      if (bdx < 0):
        break
      jstr = dumpStr[0:bdx]
      dumpStr = dumpStr[bdx+3:]
      term_addLine("%4d - " % dcnt + jstr)

    dcnt += 1
    if (dcnt >= 9999):
      dcnt = 0

    mwin.after(100, ser_dump)

# **************************************************************
# *** Begin : Button Event Handler Functions
# **************************************************************
def handle_keypress(evnt):
  print("Key Hit : ", evnt.char)


def handle_cnct(event):
  global ser
  global ser_open
  global term_numl
  global term_num

  portStr = ent_port.get()
  rateStr = ent_rate.get()
  rateVal = int(rateStr)
  print("Ok - connect to %s @ %d" % (portStr, rateVal))
  ser = serial.Serial(port=portStr, baudrate=rateVal)
  ser.timeout = 0
  ser.write(b'@Hello World#')
  ser_open = ser.is_open

  # clear term
  txt_uart.configure(state='normal')
  txt_uart.delete("1.0", tk.END)
  txt_uart.configure(state='disabled')
  term_num = 0
  
  if (ser_open):
    term_addLine("")
    term_addLine("********************************")
    term_addLine("Connect to %s @ %d SUCCESSFUL" % (portStr, rateVal))
    term_addLine("********************************")
    term_addLine("")

    lbl_cflg.config(text='Connected', bg= "pale green", fg= "black")
    ser_dump()
  else:
    term_addLine("")
    term_addLine("********************************")
    term_addLine("Connect to %s @ %d FAILED" % (portStr, rateVal))
    term_addLine("********************************")
    term_addLine("")


def handle_msgo(event):
  global ser
  global ser_open

  msgo = "@" + ent_msgo.get() + "#"
  print("Ok - sending <%s>" % msgo)
  if (ser_open and ser.is_open):
    term_addLine('SEND : ' + msgo)
    ser.write(msgo.encode())
  else:
    term_addLine("")
    term_addLine("********************************")
    term_addLine("SEND FAILED - NOT CONNECTED")
    term_addLine("********************************")
    term_addLine("")
  



def handle_meas(event):
  print("Ok - Acquiring ADC")


def handle_quit(event):
  print("Ok - Quit")
  if (ser_open):
    term_addLine("")
    term_addLine("********************************")
    term_addLine("Please Disconnect before quiting")
    term_addLine("********************************")
    term_addLine("")
  else:
    mwin.quit()

def handle_dscn(event):
  global ser
  global ser_open

  if (ser_open and ser.is_open):
    ser.close()

  ser_open = False

  lbl_cflg.config(text='Disconnected', bg= "gray95", fg= "black")

  print("Ok - Disconnect")

def handle_actn(event):
  print("Ok - Action")

# **************************************************************
# *** End   : Button Event Handler Functions
# **************************************************************

def self_intro(event = None):
  term_addLine("")
  term_addLine("********************************")
  term_addLine("Welcome to selfcircuits.com demo")
  term_addLine("********************************")
  term_addLine("")

  for prt in serial.tools.list_ports.comports():
    term_addLine(str(prt))




  
  

# *****************************************************
# *** create main window and frames
# *****************************************************
mwin = tk.Tk()


mwin.after(1000, self_intro)

mwin.bind("<Key>", handle_keypress)

frm0 = tk.Frame(mwin, bd=4, relief=tk.RIDGE)
frm1 = tk.Frame(mwin, bd=4, relief=tk.RIDGE)
frm2 = tk.Frame(mwin, bd=4, relief=tk.RIDGE)
frm3 = tk.Frame(mwin, bd=4, relief=tk.RIDGE)
# *****************************************************

# *****************************************************
# *** create widgets
# *****************************************************
# frm0 : title
lbl_titl = tk.Label(frm0, text="selfcircuits.com", height=2)

# frm1 : buttons in column 0
btn_cnct = tk.Button(frm1, text="Connect", relief=tk.RAISED)
btn_msgo = tk.Button(frm1, text="Send",    relief=tk.RAISED)
btn_meas = tk.Button(frm1, text="Measure", relief=tk.RAISED)

btn_cnct.bind("<Button-1>", handle_cnct)
btn_msgo.bind("<Button-1>", handle_msgo)
btn_meas.bind("<Button-1>", handle_meas)

# frm1 : labels in column 1
lbl_port = tk.Label(frm1, text="Port")
lbl_rate = tk.Label(frm1, text="Rate")
lbl_msgo = tk.Label(frm1, text="Msg")
lbl_eadc = tk.Label(frm1, text="ADC")

# frm1 : text in column 2
ent_port = tk.Entry(frm1, width=10, relief=tk.SUNKEN)
ent_rate = tk.Entry(frm1, width=10, relief=tk.SUNKEN)
ent_msgo = tk.Entry(frm1, width=80, relief=tk.SUNKEN)
lbl_meas = tk.Label(frm1, width=10, relief=tk.SUNKEN, text="*****")

ent_port.insert(0, "COM3")
ent_rate.insert(0, "9600")
ent_msgo.insert(0, "(type message here)")

# frm1 : text in column 3
lbl_cflg = tk.Label(frm1, width=14, relief=tk.SUNKEN, text="Disconnected", bg='gray95', fg='black')

# frm2 : text box (read only)
txt_uart = tk.Text(frm2, height=term_numl, width=80)

# frm3 : bottom row of buttons
btn_quit = tk.Button(frm3, text="Quit", relief=tk.RAISED)
btn_dscn = tk.Button(frm3, text="Disconnect",    relief=tk.RAISED)
btn_actn = tk.Button(frm3, text="Action", relief=tk.RAISED)

btn_quit.bind("<Button-1>", handle_quit)
btn_dscn.bind("<Button-1>", handle_dscn)
btn_actn.bind("<Button-1>", handle_actn)

# *****************************************************


# *****************************************************
# *** place widgets into grid
# *****************************************************
lbl_titl.grid(row=0, column=0)

btn_cnct.grid(row=0, column=0, rowspan=2, sticky="nsew", padx=4,  pady=0, ipady=4)
btn_msgo.grid(row=2, column=0, rowspan=1, sticky="nsew", padx=4,  pady=4)
btn_meas.grid(row=3, column=0, rowspan=1, sticky="nsew", padx=4,  pady=4)

lbl_port.grid(row=0, column=1)
lbl_rate.grid(row=1, column=1)
lbl_msgo.grid(row=2, column=1)
lbl_eadc.grid(row=3, column=1)

ent_port.grid(row=0, column=2, sticky="w")
ent_rate.grid(row=1, column=2, sticky="w")
ent_msgo.grid(row=2, column=2, columnspan=2, sticky="w")
lbl_meas.grid(row=3, column=2, columnspan=2, sticky="w")

lbl_cflg.grid(row=0, column=3, rowspan=2, columnspan=1, sticky="w", padx=12, pady=12, ipadx=0, ipady=0)

txt_uart.grid(row=0, column=0)

btn_quit.grid(row=0, column=0, padx=4,  pady=4)
btn_dscn.grid(row=0, column=1, padx=4,  pady=4)
btn_actn.grid(row=0, column=2, padx=4,  pady=4)


frm0.grid(row=0, column=0, sticky="nsew") 
frm1.grid(row=1, column=0, sticky="nsew")
frm2.grid(row=2, column=0, sticky="nsew")
frm3.grid(row=3, column=0, sticky="nsew")

frm0.columnconfigure(0, weight=1)
frm1.columnconfigure(3, weight=1)
# frm2.columnconfigure(0, weight=1)
# frm3.columnconfigure(0, weight=1)
# *****************************************************

mwin.mainloop()
mwin.destroy()