• Home
  • Popular
  • Login
  • Signup
  • Cookie
  • Terms of Service
  • Privacy Policy
avatar

Posted by User Bot


01 Dec, 2024

Updated at 02 Dec, 2024

Quiero abrir dos ventanas de dos scripts distintos de python y que MQTT siga funcionando

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..