estoy armando un proyecto, el cual consiste en usar Mosquitto y mediante dos script en python ambos estan suscriptos y publican en MQTT. Tengo una ventana que abriria despues de un login, aun no termine el login, pero ese no es el problema. Lo que quiero es poder abrir la ventana principal, y luego que abra la secundaria, por llamarla de una forma, pero las dos necesitan estar activas y que cada una siga mandando y recibiendo datos de una y de otra. Probe subprocess, exec(open()). He logrado que abran las dos, pero no sepuede enviar datos de una a otra.
Codigo de la primer ventana, la que se abriria ejecuntandola directamente:
"""
# Leer antes de Ejecutar
# Requisito: instalar la libreria curl_cffi
# pip install curl_cffi --upgrade
# Sitio Oficial: https://github.com/lexiforest/curl_cffi
para ventana sobre otra
top level , focus grab
"""
import paho.mqtt.client as mqtt
from curl_cffi import requests
import json
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import random
from tkinter import messagebox
from datetime import datetime
import csv
import subprocess
# import sensores
import threading
import os
topic_temp = "sensor/temperatura"
topic_hum = "sensor/humedad"
topic_pres= "sensor/presion"
topic_led= "sensor/led"
temperatura =0
humedad =0
presion=0
viento= 0
def main():
pass
def conectar_smn ():
#Se conecta a la pagina del SMN
r = requests.get("https://www.smn.gob.ar", impersonate="chrome110")
srcPagina=str(r.content)
#Del código fuente de la página, se busca un token
inicio=srcPagina.find("localStorage.setItem(")
tokenSMN=srcPagina[(inicio + 34): (inicio+390)]
# Con el token, establecer una conexión a la API del SMN (esta oculta)
pico=8803
quemu=8860
san_rosa=8861
# response = requests.get('http://api.open-notify.org/iss-pass.json',
# params=params)
#
try:
response = requests.get(
url="https://ws1.smn.gob.ar/v1/weather/location/8803", impersonate="chrome110",
headers={
"Authorization":"JWT "+tokenSMN+" "
},
)
climaJSON = json.loads(response.text)
global temperatura, humedad, presion, viento
temp_entry.delete(0,'end')
temp_entry.insert(tk.END, climaJSON['temperature'])
hum_entry.delete(0,'end')
hum_entry.insert(tk.END, climaJSON['humidity'])
vien_entry.delete(0,'end')
vien_entry.insert(tk.END, climaJSON['wind']['speed'])
pres_entry.delete(0,'end')
pres_entry.insert(tk.END, climaJSON['pressure'])
except Exception as e:
messagebox.showinfo("ERROR", "No se pudo conectar al SMN")
# hilo2 = threading.Thread(target=exec(open("sensores.py").read()))
# ----aca separo los datos en cada variable------
# -----print para ir viendo que datos obtengo---
# print("Temperatrura: ",temperatura, "ºC")
# print("Humedad: ",humedad,"%")
# print("Presion: ",presion, "hPa")
# print("Viento: ", viento, "KM/H")
# ------------------ HASTA ACA LO DEL SMN--------------------
# ----- aca los distintos topicos que subcribe al mosquito-------
def exportar(tipo):
"""
Funcion para esportar , ya sea en formato json o csv.
Segun el parametro pasado sera uno u otro formato
"""
if tipo == 'json':
datos={}
datos["Estado_Sensores"]=[]
datos["Estado_Sensores"].append({
"Temperatura": temp_sen_entry.get(),
"Humedad": hum_sen_entry.get(),
"Presion": pres_sen_entry.get()
})
with open ("export_json.json", "w") as exp_json:
json.dump(datos, exp_json, indent=2)
exp_json.close()
elif tipo=='csv':
with open('export_csv.csv', 'w', newline='') as exp_csv:
fieldnames = ['Temperatura', 'Humedad', 'Presion']
writer = csv.DictWriter(exp_csv, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'Temperatura':temp_sen_entry.get(),
'Humedad': hum_sen_entry.get(),
'Presion':pres_sen_entry.get(),
})
exp_csv.close()
def actualizar_archivo(topic, data):
"""
Funcion que actualiza el archivo datos.txt
Segun el sensor que cambie de valor, es el dato que se
graba el archivo, con fecha y hora, actualizandolo.
"""
fecha =(datetime.now()).strftime("%d-%m-%Y %H:%M:%S")
with open("datos.txt", "a" ) as archivo:
match topic:
case "topic_temp":
archivo.write("Fecha y Hora :"+fecha + "\n")
archivo.write("Temperatura :"+data +"°C\n")
archivo.write("----------------------------------\n")
case "topic_hum":
archivo.write("Fecha y Hora :"+fecha + "\n")
archivo.write("Humedad :"+data + "%\n")
archivo.write("----------------------------------\n")
case "topic_pres":
archivo.write("Fecha y Hora :"+fecha + "\n")
archivo.write("Presion Atmos:"+data + "hPa\n")
archivo.write("----------------------------------\n")
archivo.close()
# ------- AHORA LA JODA DE RECIBIR LOS DATOS-------------
def publicar(topic, valor):
cliente.publish(topic, valor)
def activar_led(*args):
publicar(topic_led, 1)
def fn_conectar_al_broker():
def fn_on_connect(client, userdata, flags, reason_code):
if reason_code == 0:
client.subscribe(topic_temp, 0)
client.subscribe(topic_hum, 0)
client.subscribe(topic_pres, 0)
else:
messagebox.showwarning("Advertencia", f"Algo salió mal: {reason_code}")
def fn_on_message(client, userdata, msg):
print(f"Mensaje recibido - {msg.topic}: {msg.payload.decode('utf-8')}")
dato = (msg.payload.decode('utf-8'))
if topic_temp == msg.topic:
temp_sen_entry.delete(0,'end')
temp_sen_entry.insert(0, dato)
actualizar_archivo("topic_temp", dato)
elif topic_hum == msg.topic:
hum_sen_entry.delete(0,'end')
hum_sen_entry.insert(0, dato)
actualizar_archivo("topic_hum", dato)
elif topic_pres == msg.topic:
pres_sen_entry.delete(0,'end')
pres_sen_entry.insert(0, dato)
actualizar_archivo("topic_pres", dato)
# ----- ACA LA CONEXION AL BROKER ----------------
try:
with open("host.json", "r") as host:
datos = json.load(host)
broker= datos["broker"]
port=datos["port"]
print(broker,port)
host.close()
except Exception:
messagebox.showinfo("ERROR", "No se pudo abrir host.json")
cid = f'python-mqtt-{random.randint(0, 1000)}'
global cliente
cliente = mqtt.Client()
cliente.on_connect = fn_on_connect
cliente.on_message = fn_on_message
try:
cliente.connect(broker, port)
info_label.config(text=f"Conexión establecida con el Broker",foreground="green")
except Exception:
messagebox.showinfo("ERROR", "Fallo conexión al Broker")
cliente.loop_start()
# -----------------Ventana principal-------------------
app = tk.Tk()
app.title("Proyecto Final")
app.grid_columnconfigure((0), weight=1)
#------------------Frame de los sensores----------------
cmd_frame = ttk.LabelFrame(app, text="Estado Sensores", relief=tk.RIDGE)
cmd_frame.grid(row=1, column=1, sticky=tk.E + tk.W + tk.N + tk.S, padx=5,pady=5)
#------------Las etiquetas con humedad, temperatura, etc. ---------------
temp_sen_label = ttk.Label(cmd_frame, text="Temperatura:")
temp_sen_label.grid(row=3, column=1, sticky=tk.W, pady=3)
grad_sen_label = ttk.Label(cmd_frame, text="°C")
grad_sen_label.grid(row=3, column=3, sticky=tk.W, pady=3)
temp_sen_entry = ttk.Entry(cmd_frame, width=5)
temp_sen_entry.grid(row=3, column=2, sticky=tk.W, padx=5,pady=5)
temp_sen_entry.insert(tk.END, 0)
hum_sen_label = ttk.Label(cmd_frame, text="Humedad: ")
hum_sen_label.grid(row=4, column=1, sticky=tk.W, pady=3)
porcen_sen_label = ttk.Label(cmd_frame, text="%")
porcen_sen_label.grid(row=4, column=3, sticky=tk.W, pady=3)
hum_sen_entry = ttk.Entry(cmd_frame, width=5)
hum_sen_entry.grid(row=4, column=2, sticky=tk.W, padx=5,pady=5)
hum_sen_entry.insert(tk.END, 50)
pres_sen_label = ttk.Label(cmd_frame, text="Presion: ")
pres_sen_label.grid(row=5, column=1, sticky=tk.W, pady=3)
hpa_sen_label = ttk.Label(cmd_frame, text="hPa")
hpa_sen_label.grid(row=5, column=3, sticky=tk.W, pady=3)
pres_sen_entry = ttk.Entry(cmd_frame, width=5)
pres_sen_entry.grid(row=5, column=2, sticky=tk.W, padx=5,pady=5)
pres_sen_entry.insert(tk.END, 990)
btn_led = ttk.Button(cmd_frame, text="LED")
btn_led.place(x=50, y=100)
btn_led.bind("", activar_led)
# ----------------Frame del SMN----------------------------
fromlist_frame = ttk.LabelFrame(app, text="Clima actual", relief=tk.RIDGE)
fromlist_frame.grid(row=1, column=2, sticky=tk.E + tk.W + tk.N + tk.S, padx=5,pady=5)
combobox_label = tk.Label(fromlist_frame, text="Ciudad")
combobox_label.grid(row=1, column=1, sticky=tk.W + tk.N)
combobox_value = tk.StringVar()
my_combobox = ttk.Combobox(fromlist_frame, height=4, textvariable=combobox_value)
my_combobox.grid(row=1, column=3,padx=5,pady=5)
my_combobox['values'] = ("General Pico", "Quemu Quemu", "Santa Rosa", "Realico")
my_combobox.current(0)
label1 = ttk.Label(fromlist_frame, text="Temperatura: ")
label1.grid(row=3, column=1, sticky=tk.W, pady=3)
temp_entry = ttk.Entry(fromlist_frame, width=5)
temp_entry.grid(row=3, column=2, sticky=tk.W, padx=5,pady=5)
label2 = ttk.Label(fromlist_frame, text="Humedad: ")
label2.grid(row=4, column=1, sticky=tk.W, pady=3)
hum_entry = ttk.Entry(fromlist_frame, width=5)
hum_entry.grid(row=4, column=2, sticky=tk.W, padx=5,pady=5)
label3 = ttk.Label(fromlist_frame, text="Viento: ")
label3.grid(row=5, column=1, sticky=tk.W, pady=3)
vien_entry = ttk.Entry(fromlist_frame, width=5)
vien_entry.grid(row=5, column=2, sticky=tk.W, padx=5,pady=5)
label4 = ttk.Label(fromlist_frame, text="Presion: ")
label4.grid(row=6, column=1, sticky=tk.W, pady=3)
pres_entry = ttk.Entry(fromlist_frame, width=5)
pres_entry.grid(row=6, column=2, sticky=tk.W, padx=5,pady=5)
# -------------------Frame avisos---------------------
info_frame = ttk.LabelFrame(app, text="", relief=tk.RIDGE)
info_frame.grid(row=2, column=0, sticky=tk.E + tk.W + tk.N + tk.S, padx=5,pady=5)
info_label = tk.Label(app, text="")
info_label.grid(row=5, column=1, sticky=tk.W, pady=3)
# Menus
menubar = tk.Menu(app)
app.config(menu= menubar)
sub_menu_export=tk.Menu(menubar,tearoff=0)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Abrir", command=filedialog.asksaveasfilename)
sub_menu_export = tk.Menu(menubar)
filemenu.add_cascade(label="Exportar", menu =sub_menu_export)
sub_menu_export.add_command(label="JSON", command= lambda: exportar("json"))
sub_menu_export.add_command(label="CSV", command= lambda: exportar("csv"))
filemenu.add_separator()
filemenu.add_command(label="Salir", accelerator="Alt+F4", command=app.destroy, compound=tk.LEFT)
menubar.add_cascade(label="Archivo", menu=filemenu)
app.config(menu=menubar)
# - - - - - - - - - - - - - - - - - - - - -
# Quit button in the lower right corner
quit_button = ttk.Button(app, text="Salir", command=app.destroy)
#quit_button.grid(row=1, column=3)
quit_button.grid(row=3, column=1, padx=20, pady=20, sticky="ew", columnspan=2)
conectar_smn()
fn_conectar_al_broker()
app.mainloop()
# t1 = threading.Thread(target=main, name='t1')
# t1.start()
# subprocess.run('python.exe sensores.py', shell=True)
# exec(open("sensores.py").read())
Y aca el codigo de la ventana que quiero que abra automaticamente una vez abeirta la anterior:
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import paho.mqtt.client as mqtt
import json
broker = '127.0.0.1'
puerto = 1883
topic_temp = "sensor/temperatura"
topic_hum = "sensor/humedad"
topic_pres= "sensor/presion"
topic_led= "sensor/led"
flag_led=False
cliente = mqtt.Client()
# ---------Publicar al BROKER-------------------
def publicar(topic, valor):
cliente.publish(topic, valor)
def actualizar_temperatura(*args):
publicar(topic_temp, temp_scale.get())
def actualizar_humedad(*args):
publicar(topic_hum, hum_scale.get())
def actualizar_presion(*args):
publicar(topic_pres, pres_scale.get())
#-------------Conectar al BROKER----------------
def conectar_broker():
def fn_on_connect(client, userdata, flags, reason_code):
if reason_code == 0:
client.subscribe(topic_led, 0)
info_topic_label.config(text=f"Suscripto al topico Led",foreground="green")
info_topic_label.grid(row=2, column=1, sticky=tk.W, pady=3)
else:
messagebox.showinfo("Error al suscribirse a topico Led",foreground="red")
def fn_on_message(client, userdata, msg):
global flag_led
if (topic_led == msg.topic) and (flag_led==False):
info_label.config(text=f" Led encendido ",foreground="green")
flag_led=True
else:
info_label.config(text=f" Led apagado ",foreground="blue")
flag_led=False
try:
with open("host.json", "r") as host:
datos = json.load(host)
broker= datos["broker"]
port=datos["port"]
host.close()
except Exception:
# print("Error al querer abrir host.json")
messagebox.showinfo("ERROR", "No se pudo abrir host.json\r\n")
cliente.on_connect = fn_on_connect
cliente.on_message = fn_on_message
try:
cliente.connect(broker,port)
info_label.config(text=f"Conexión establecida con el Broker",foreground="green")
info_label.grid(row=1, column=1)
except Exception:
messagebox.showinfo("ERROR", "No se pudo conectar al Broker")
# info_label.config(text=f"Fallo conexión al Broker",foreground="red")
cliente.loop_start()
# info_label.config(text=f"Fallo conexión al Broker",foreground="red")
# -------------Inicio inteface---------------------
windows_master = tk.Tk()
windows_master.grid_columnconfigure((0), weight=1)
windows_master.geometry("220x230+500+300")
windows_master.grid_columnconfigure((0), weight=1)
# -------------Frame y Scale de Sensores ------------------------
scale_frame = tk.Frame(windows_master)
scale_frame = ttk.LabelFrame(windows_master, text="Sensores", relief=tk.RIDGE)
scale_frame.grid(row=1, column=0, padx=1,pady=1)
temp_scale = tk.Scale(scale_frame, from_=50, to=-50)
actualizar_temperatura()
temp_scale.set(0)
temp_scale.bind("", actualizar_temperatura)
temp_scale.bind("", actualizar_temperatura)
temp_scale.grid(row=1, column=1, pady=3,padx=8)
temp_label = tk.Label(scale_frame, text="Temperatura")
temp_label.grid(row=2, column=1, pady=3)
hum_scale = tk.Scale(scale_frame, from_=100, to=0)
actualizar_humedad()
hum_scale.set(50)
hum_scale.bind("", actualizar_humedad)
hum_scale.bind("", actualizar_humedad)
hum_scale.grid(row=1, column=2, pady=3, padx=8)
hum_label = tk.Label(scale_frame, text="Humedad")
hum_label.grid(row=2, column=2, pady=3)
pres_scale = tk.Scale(scale_frame, from_=1040, to=940)
actualizar_presion()
pres_scale.set(990)
pres_scale.bind("", actualizar_presion)
pres_scale.bind("", actualizar_presion)
pres_scale.grid(row=1, column=3, pady=3, padx=8)
pres_label = tk.Label(scale_frame, text="Pres Atm")
pres_label.grid(row=2, column=3, pady=1)
# ----------------------------------------------------
info_frame = tk.Frame(windows_master)
info_frame = ttk.LabelFrame(windows_master, text="Info")
info_frame.grid(row=2, column=0, padx=0,pady=0)
info_label = tk.Label(info_frame, text=" ")
info_label.grid(row=1, column=1, pady=0, padx=10)
info_topic_label=tk.Label(info_frame, text=" ")
info_topic_label.grid(row=2, column=1, pady=5, padx=10)
conectar_broker()
windows_master.mainloop()
# ------------Fin Interface----------------------
Se que el codigo tiene un monton de cosas a mejorar, se agradecen tambien sugerencias para mejorarlo. Desde ya Muchas gracias de antemano..