Python Forum
Making my way back into programming and need a little help.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Making my way back into programming and need a little help.
#1
Hey guys, my name is James I'm from Houston, TX, it's been roughly 22yrs since I last tried any programming in college. I recently decided to try and duplicate a switch panel that is made for off road (called a spod and has touchscreen control), it's almost $1200 to buy it and I'm about trying to make things my way cheaper, with more functionality. Over the last 3 weeks I have been writing this code to work in conjunction with a raspberry pi and touchscreen to operate different things on my 18 jeep jku, as well as my tuning software(HP Tuners). so far, I'm in about ~$80 and 3 weeks of tinkering and I feel like I have roughly 80% of the functionality of the $1200 unit. it's been a process getting here, make one change and have to completely rewrite the program to work with that change. Was wondering if anyone could look at what I have so far and make some suggestions to make it shorter and more elegant? A rundown of the program thus far. from a fresh boot I have 8 GUI switches that will control 1-8 relays( I have all the GPIO stuff removed for windows, but it works), I have it to where the text and color changes based off the state of the output that controls the relay. I also have an all off button that kills the output to all relays when pushed. as well as an exit button that closes the program, and a shutdown button that shuts down the rasberry pi. I have right now an all on relay that turns all the relays on, but I want to change this to user selectable vis check boxes or radio buttons. I have a setup button that goes to a different window where you can name the buttons whatever you want. There are some things I want to change as well as see if I can shorten any of these up. I will attach my program and attachments from my git hub account here https://github.com/joegibbstruck/Start-o...relays.git I know some of this will be strictly rasberry pi, and some of them are straight GUI but I'll take any help I can get, these are all notes in my code as well, not looking for someone to write all my code just pointers on how to modify it from here without having to rewrite the entire thing.

Things I would like a little help / direction with
1) How would I go about using radio buttons or check boxes to link certain switches together rather than having to list each switch individually via code?
for example, open a new window select 1-8 buttons and refence that back to the code for the main switch to operate.
2) Right now, to label the switches I am writing to individual text files. this works but I have to create 8 text files before I start the program. this is a 2-part question, how do I make a new file if one does not exist, and can I refence 8 items from 1 text file in say a list or dictionary? if so, what would the steps be to make that happen?
3)by writing to the .txt files it stores my information as well as changes the text on the buttons, but if you don't restart the text goes back to the previous state when pressed. how would I force a restart when the submit button is pressed?
4) if I change the name of one or two buttons but leave the others blank, then when you restart everything goes back to "factory", what would I use to write to the .txt file if there is a change present but not overwrite the file if left blank?
5)Right now I have to use 17 globals from my second setup window, is there a way to make a global list, and just 1 global variable to refence all of the others?
6)similar to number 2 right now I have to read from 8 .txt files to pull the data from to maintain the button labels, anyway, to reference a list or something in 1 .txt file for all 8?
7) how would I force this program to run on start up?
8) anyway, to remove the close and minimize button on the main window?
9) potentially I would have up to 24 relays controlled by this, how would I hide the code from 9-24 until needed? say a check box in the setup menu to unlock another main page with more buttons?

I appreciate any help anyone is willing to give, like I said I'm just looking for direction. I make notes as I go and work on my issues one at a time I figured this way at least maybe I can get directions for multiple issues.
Reply
#2
Some things to think about.
import tkinter as tk


relays = []
setup_file = "switches.txt"


def set_relay_state(relay, state):
    """Set relay button value."""
    relay.state = state
    relay["text"] = relay.name + (" ON" if state else " OFF")
    relay["bg"] = "red" if state else "green"


def set_relay_name(relay, name):
    """Set the name of the relay"""
    relay.name = name
    set_relay_state(relay, relay.state)


def toggle_relay(relay):
    """Toggle a relay button."""
    set_relay_state(relay, not relay.state)


def set_relays(state):
    """Set all relays to some state."""
    for relay in relays:
        set_relay_state(relay, state)


def submit(window, entries):
    """Callback for set_relays Commit button.  Set relay
    names and save names in config file.
    """
    with open(setup_file, "w") as file:
        for switch, relay in zip(entries, relays):
            print(switch.get(), file=file)
            set_relay_name(relay, switch.get())
    window.destroy()


def edit_relays():
    """Create setup window for entering relay names"""
    window = tk.Toplevel()
    window.title("SETUP")
    entries = []
    for i, relay in enumerate(relays):
        row = i % 4
        col = (i // 4) * 2
        label = tk.Label(window, text="Switch #" + str(i + 1))
        label.grid(row=row, column=col, padx=5, pady=5)
        var = tk.StringVar(window, relay.name)
        entries.append(var)
        entry = tk.Entry(window, textvariable=var, width=15)
        entry.grid(row=row, column=col + 1, padx=5, pady=5)
    button = tk.Button(window, text="Submit", command=lambda: submit(window, entries))
    button.grid(row=5, column=0, columnspan=2, padx=5, pady=5, sticky="news")
    button = tk.Button(window, text="Cancel", command=window.destroy)
    button.grid(row=5, column=2, columnspan=2, padx=5, pady=5, sticky="news")


# Opening files may fail.  Don't let that crash the program.
try:
    with open(setup_file, "r") as file:
        names = [line.strip() for line in file]
except FileNotFoundError:
    pass

# If the file is messed up or missing provide some default names.
if len(names) != 8:
    names = ["Switch #" + str(i) for i in range(1, 9)]

root = tk.Tk()
menubar = tk.Menu(root)
menu = tk.Menu(menubar, tearoff=False)
menubar.add_cascade(label="Options", menu=menu)
menu.add_command(label="Edit Relays", command=edit_relays)
menu.add_command(label="All Off", command=lambda: set_relays(False))
menu.add_command(label="All On", command=lambda: set_relays(True))
root.config(menu=menubar)

for i, name in enumerate(names):
    row = i % 4
    col = i // 4
    relay = tk.Button(root, width=15)
    relay.configure(command=lambda arg=relay: toggle_relay(arg))
    relay.grid(row=i % 4, column=i // 4, padx=5, pady=5)
    relay.name = name
    set_relay_state(relay, False)
    relays.append(relay)

root.mainloop()
I know I left things out (where are the LED's?). This is not meant to replace your code, only to provide some ideas on how you could organize your code,

Notice that global() is nowhere to be seen. Lots of global variables make it difficult to track what your program is doing.

Notice there are no functions that do the same thing. Write generic functions and make them specific by passing arguments.

Do not use wildcard imports (from tkinter import *). When doing a wildcard import you import all the names from the module. Some of those names may be the same as names for variables or functions in your code. This can lead to really odd behaviors that are difficult to track down. Wildcard imports also make it difficult to find where a name was defined. The wildcard provides no clues. tk.Button leaves no doubt where the Button comes from.

If this is on a small screen, you should think about making it a single window/full screen application that has interchangeable frames that appear in root window instead of independent toplevel windows.. 

I have no idea how to force a program to run on a raspberry pi. That sounds like a good question for a raspberry pi forum.
Reply
#3
So, the LEDs refer to my GPIO pins on the rasberry pi( it's a list of all 8 and I pull from that list which relay I want to do what) this is what I run to control the output for the relays( turn them on and off) I have to use what's called the LED board config on the PI because I need to be able to control multiple GPIO pins at once. I took all the LED stuff out , because without the GPIOzero library from the PI windows can't run this program.


I see what you are doing on most of this, I will check it out and try some of these suggestions. Thanks for that help and giving me a few things to try.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020