Posts: 31
Threads: 7
Joined: Oct 2021
(Jan-18-2022, 12:05 PM)deanhystad Wrote: Indentation in line 64 pushes the for loop outside the scope of the getTemp() method. Look st your update clock method. How often is getTemp called. Think before you automatically say "Once every 5 seconds"
Thanks for setting me straight on that, I did notice that finally last night. I got the code working as wanted. I will post the code when I get home as I would really appreciate you looking over it to see if I have done things correctly. Honestly, going from VB.NET to Python has been a struggle for me.
Posts: 31
Threads: 7
Joined: Oct 2021
deanhystad, here is my current code. please let me know how this looks and if it looks like the correct way. Thanks
import tkinter as tk
from tkinter import *
from tkinter import messagebox
import requests
import http.client
import time
import json
path = ""
SONOFF_Temp = 'http://192.168.0.113/cm?cmnd=status+10'
sonoff_url = 'NOT_INIT'
class RelayButton(tk.Button):
"""A button that toggles a relay"""
def __init__(self, parent, url="", on_image=None, off_image=None, **kwargs):
super().__init__(parent, image=off_image, command=self.toggle)
self.url = url
self._on = False
self.on_image = on_image
self.off_image = off_image
self.label = Label(text="", fg="Black", font=("Helvetica", 12))
self.label.place(x=10,y=15)
self.update_clock()
self.templabel = Label(text="temp info", fg="Black", font=("Helvetica", 12))
self.templabel.place(x=10, y=40)
self.getTemp()
#self.master.configure(background='white') <<< Frame Color
@property
def on(self):
"""Return state of the relay"""
return self._on
@on.setter
def on(self, on):
"""Set state of the relay"""
self._on = on
if on:
requests.post(f"{self.url}cm?cmnd=Power On")
self["image"] = self.on_image
else:
requests.post(f"{self.url}cm?cmnd=Power Off")
self["image"] = self.off_image
def toggle(self):
"""Toggle state of the relay"""
self.on = not self.on
def update_clock(self):
now = time.strftime("%I:%M:%S %p " + ' - ' + "%x")
self.label.configure(text='Time/Date: ' + now)
self.after(1000, self.update_clock)
def getTemp(self):
sonoff_url = SONOFF_Temp
sonR1 = requests.get(sonoff_url)
x = json.loads(sonR1.text)
status = x["StatusSNS"]
timestamp = status["Time"]
device_names = list(status.keys())[1:-1]
temp_units = status["TempUnit"]
for name in device_names:
device = status[name]
#print(f'ID={name}, Temperature={device["Temperature"]} {temp_units}')
self.templabel.configure(text='Living Room '+f'Temperature={device["Temperature"]} {temp_units}')
self.after(5000, self.getTemp)
def new_button(name, url, parent, row, column, **kwargs):
"""Convenience functon that creates a RelayButton"""
on_image = tk.PhotoImage(file=f"{path}{name}_on.png")
off_image = tk.PhotoImage(file=f"{path}{name}_off.png")
button = RelayButton(parent, url, on_image, off_image, **kwargs)
button.grid(row=row, column=column, padx=50, pady=110)
return button
def main():
app = tk.Tk()
app.title('Home Relay Controls')
buttons = [
new_button('living', "http://192.168.0.101/", app, 0, 0),
new_button('front_porch', "http://192.168.0.113/", app, 0, 1)
]
for b in buttons:
b.on = False
app.mainloop()
if __name__ == "__main__":
main()
Posts: 6,779
Threads: 20
Joined: Feb 2020
Jan-20-2022, 05:27 PM
(This post was last modified: Jan-20-2022, 05:27 PM by deanhystad.)
When you make a widget you need to specify the parent window. That is not done here:
self.label = Label(text="", fg="Black", font=("Helvetica", 12)) and a few other places. This is probably why you earlier reported some problems with labels not appearing in your windows.
You should not be polluting the namespace by using a wildcard import (from tkinter import *). You can get away with this in toy programs, but it is a bad practice and will cause very confusing and hard to debug problems in larger programs.
RelayButton is a Button. It should act like a button and it should look like a button. It should not be updating a label to show clock time. It should not be updating a label to show the temperature.
Posts: 31
Threads: 7
Joined: Oct 2021
(Jan-20-2022, 05:27 PM)deanhystad Wrote: When you make a widget you need to specify the parent window. That is not done here:
self.label = Label(text="", fg="Black", font=("Helvetica", 12)) and a few other places. This is probably why you earlier reported some problems with labels not appearing in your windows.
You should not be polluting the namespace by using a wildcard import (from tkinter import *). You can get away with this in toy programs, but it is a bad practice and will cause very confusing and hard to debug problems in larger programs.
RelayButton is a Button. It should act like a button and it should look like a button. It should not be updating a label to show clock time. It should not be updating a label to show the temperature.
Thanks deanhystad, can you show me how/where I should properly be doing this?
Posts: 6,779
Threads: 20
Joined: Feb 2020
No. Do this on your own.
Try writing the program without the buttons and the relays. Make a label that displays the time and another that displays the temperature. Make a function that updates the labels. Call the function periodically using afer. Once you have the program working think about how you could add in some buttons that will open/close relays.
Posts: 31
Threads: 7
Joined: Oct 2021
(Jan-20-2022, 06:04 PM)deanhystad Wrote: No. Do this on your own.
Try writing the program without the buttons and the relays. Make a label that displays the time and another that displays the temperature. Make a function that updates the labels. Call the function periodically using afer. Once you have the program working think about how you could add in some buttons that will open/close relays.
Ok, well stated... I will take on the challenge and report back. Thanks for helping me on this deanhystad
Posts: 31
Threads: 7
Joined: Oct 2021
ok deanhystad, here is my newest code that I slapped together... it is messy and I know that already. It does work, and it does tell me what the current state is of the relay and starts the window with button state ON or OFF based on the status.
from tkinter import *
from tkinter import messagebox
import requests
import time
import os
import json
ws = Tk()
ws.title('Relay Control')
ws.geometry("600x400")
ws.configure(background='white')
on = PhotoImage(file = "frPorch_on.png")
off = PhotoImage(file = "frPorch_off.png")
shelly01 = 'http://shelly1-483fda82683f/status'
shURL = 'NOT_INIT'
shURL = shelly01
sh01 = requests.get(shURL)
x = json.loads(sh01.text)
status = x["relays"]
a = status
is_on = a[0]['ison']
print(is_on)
def Switch():
global is_on
if is_on:
button.config(image = off)
label.config(text = "Switch is Off", fg = "grey", bg='white')
requests.post('http://shelly1-483fda82683f/relay/0/?turn=off')
is_on = False
else:
button.config(image = on)
label.config(text = "Switch is On", fg = "green", bg='white')
requests.post('http://shelly1-483fda82683f/relay/0/?turn=on')
is_on = True
if is_on == True:
button = Button(ws, image = on, bg='white', bd = 0, command = Switch)
button.pack(pady = 30)
label = Label(ws, text = "The Switch Is On!", bg='white', fg = "green", font = ("Helvetica", 32))
label.pack(pady = 20)
else:
button = Button(ws, image = off, bg='white', bd = 0, command = Switch)
button.pack(pady = 30)
label = Label(ws, text = "The Switch Is Off!", bg='white', fg = "grey", font = ("Helvetica", 32))
label.pack(pady = 20)
ws.mainloop()
|