Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
7.0 kB
1
Indexable
Never
import threading
import time
import tkinter as tk
import tkinter.ttk as ttk
import serial
import serial.tools.list_ports
from tkinter.scrolledtext import ScrolledText


class SerialChat:
    def __init__(self, master):
        
        self.master = master
        self.puerto = "COM1"  # Puerto vacío    
        self.puerto_conectado = True   # Verificar si ya se conectó
        self.master.title(f"Serial Chat")
        self.master.geometry("+50+50")
        self.master.resizable(0, 0)        
        self.conexion = tk.StringVar() 
        self.conexion.set("Conectar")
        # ---------------------- SERIAL PORT --------------------------
        
        ports = serial.tools.list_ports.comports() 
        
        for port in ports:  # Puertos disponibles
            print(port)
            
        self.puertos = []
        
        for port in ports:  
            p1, p2 = str(port).split('-') 
            p1 = p1.replace(' ','') 
            self.puertos.append(p1) 
                
        # ------------------------ FRAMES -----------------------------
        frm1 = tk.LabelFrame(self.master, text="Conexion")
        frm2 = tk.Frame(self.master)
        frm3 = tk.LabelFrame(self.master, text="Enviar mensaje")
        frm1.pack(padx=5, pady=5, anchor=tk.W)
        frm2.pack(padx=5, pady=5, fill='y', expand=True)
        frm3.pack(padx=5, pady=5)
        
        # ------------------------ FRAME 1 ----------------------------
        self.lblCOM = tk.Label(frm1, text="Puerto COM:") 
        self.cboPort = ttk.Combobox(frm1, values=self.puertos)
        self.lblSpace = tk.Label(frm1, text="")
        self.btnConnect = ttk.Button(frm1, textvariable=self.conexion,command=self.seleccionar_puertos, width=16)
        self.lblCOM.grid(row=0, column=0, padx=5, pady=5)
        self.cboPort.grid(row=0, column=1, padx=5, pady=5)
        self.lblSpace.grid(row=0,column=2, padx=30, pady=5)
        self.btnConnect.grid(row=0, column=3, padx=5, pady=5)
        
        # ------------------------ FRAME 2 ---------------------------
        self.txtChat = ScrolledText(frm2, height=25, width=50, wrap=tk.WORD, state='disable')
        self.txtChat.grid(row=0, column=0, columnspan=3, padx=5, pady=5)
                
        # ------------------------ FRAME 3 --------------------------
        self.lblText = tk.Label(frm3, text="Texto:")
        self.inText = tk.Entry(frm3, width=45, state='disable')
        self.btnSend = ttk.Button(frm3, text="Enviar", width=12, state='disable',command=self.enviar_mensaje)
        self.lblText.grid(row=0, column=0, padx=5, pady=5)
        self.inText.grid(row=0, column=1, padx=5, pady=5)
        self.btnSend.grid(row=0, column=2, padx=5, pady=5)
               
        # --------------------------- StatusBar -----------------------
        self.statusBar = tk.Label(self.master, bd=1, relief=tk.SUNKEN, anchor=tk.W)
        self.statusBar.pack(side=tk.BOTTOM, fill=tk.X)
        
        # ------------- Control del boton "X" de la ventana -----------
        self.master.protocol("WM_DELETE_WINDOW", self.cerrar_puertos)
        
        # ------------- Recibe el mensaje del emisor -----------
        self.master.after(1000, self.recibir_mensaje)
    
    def cerrar_puertos(self):
        try:
            self.serial.close()
        except:
            pass
        self.master.destroy()
                
    def seleccionar_puertos(self):
        self.puerto = self.cboPort.get()  # Uso get para recibir el valor del combobox
            
        if self.puerto_conectado:  # Si ya se conectó, no se puede conectar de nuevo
            self.puerto_conectado = False
            self.cboPort.config(state='disabled')
            self.conexion.set("Desconectar") 
            self.inText.config(state='normal')  
            self.btnSend.config(state='normal')
            
        else:  # Si no está conectado, se mantiene igual
            self.conexion.set("Conectar")
            self.puerto_conectado = True
            self.puerto = "COM1" 
            self.ser.close()
            
            self.inText.config(state='disabled')
            self.btnSend.config(state='disabled')
            self.cboPort.config(state='normal') 
            self.statusBar.config(text="")
            return
            
        try:
            self.statusBar.config(text="Conectado al " + self.puerto + " a 9600") 
            self.ser = serial.Serial(port=self.puerto, 
                                baudrate=9600, 
                                bytesize=8, 
                                timeout=2, 
                                stopbits=serial.STOPBITS_ONE)
        
        except:
            self.conexion.set("Conectar")
            self.puerto_conectado = True
            
            self.inText.config(state='disabled')
            self.btnSend.config(state='disabled')
            self.cboPort.config(state='normal')
            self.statusBar.config(text="Error al conectarse a " + self.puerto)
            self.puerto = "COM1"    # Puerto vacío          
            
    def enviar_mensaje(self):
        texto = self.inText.get()  # Texto del mensaje enviado
        texto = self.puerto + ": " + texto  # COM2: AEA
        texto_encode = texto.encode("utf-8")  # "COM2:AEA"
        self.ser.write(texto_encode)    
        self.txtChat.config(state='normal')
        self.txtChat.insert(tk.INSERT, str(texto) + "\n", 'verde')
        
        th1sec = threading.Thread(target=self.tiempo, args=(1, 0,), daemon=True)  # Threading
        th1sec.start()
        
        self.txtChat.tag_config('verde', foreground='green')  # Color de letra
        self.inText.delete(0, 'end')
        self.txtChat.config(state='disabled')
        return 
    
    def recibir_mensaje(self):
        
        if self.puerto in self.puertos:
            
            if self.ser.in_waiting > 0:
                mensaje = self.ser.readline()
                mensaje = mensaje.decode('utf-8')
                self.txtChat.config(state='normal')
                
                th2sec = threading.Thread(target=self.tiempo, args=(1, 1,), daemon=True)  # Threading
                th2sec.start()
                
                self.txtChat.insert(tk.INSERT, str(mensaje) + "\n", 'red')  # Color de letra

                self.txtChat.tag_config('red', foreground='red')
                self.txtChat.config(state='disabled')
                
        self.master.after(1000, self.recibir_mensaje)
        
    def tiempo(self, sec, n):
        time.sleep(sec)  
        self.txtChat.config(state='normal')  
        self.txtChat.tag_remove('red', '1.0', 'end')  # Color de letra
        self.txtChat.tag_remove('verde', '1.0', 'end')  # Color de letra
        self.txtChat.config(state='disabled')
        

root = tk.Tk()
SerialChat(root)
root.mainloop()