0% found this document useful (0 votes)
6 views6 pages

Apptk 001

The document outlines a Python script for a graphical user interface (GUI) application that manages serial communication with a device, specifically an E-well Gateway. It includes configuration options for WiFi, MQTT settings, and device serial numbers, and allows users to connect and disconnect from the device, clear data, and save configurations. The application uses the Tkinter library for the GUI and handles serial port communication using the pySerial library.

Uploaded by

namkaka123306
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views6 pages

Apptk 001

The document outlines a Python script for a graphical user interface (GUI) application that manages serial communication with a device, specifically an E-well Gateway. It includes configuration options for WiFi, MQTT settings, and device serial numbers, and allows users to connect and disconnect from the device, clear data, and save configurations. The application uses the Tkinter library for the GUI and handles serial port communication using the pySerial library.

Uploaded by

namkaka123306
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 6

import threading

import serial
import serial.tools.list_ports
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
import time
import json
import re
import os
import tkinter.font as tkfont

CONFIG_FILE = 'config.json'

class SerialGUI(tk.Tk):
def __init__(self):
super().__init__()
# --- Tăng kích thước font mặc định thêm 15% ---
for name in ("TkDefaultFont", "TkTextFont", "TkFixedFont", "TkMenuFont",
"TkHeadingFont"):
try:
f = tkfont.nametofont(name)
f.configure(size=int(f.cget("size") * 1.2))
except tk.TclError:
pass

self.title("E-well Gateway")
self.state('zoomed')
self.protocol("WM_DELETE_WINDOW", self.on_close)

# --- Load saved config or defaults ---


if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
saved = json.load(f)
except Exception:
saved = {}
else:
saved = {}

# --- Config vars ---


self.wifi_ssid = tk.StringVar(value=saved.get('ssid', 'CTY VTE'))
self.wifi_pass = tk.StringVar(value=saved.get('wifi_pass', '01011984'))
self.username = tk.StringVar(value=saved.get('username', 'adminmqtt'))
self.user_pass = tk.StringVar(value=saved.get('user_pass', 'Sys123456'))
self.mqtt_broker = tk.StringVar(value=saved.get('mqtt_broker',
'160.30.136.224'))
self.mqtt_port = tk.IntVar( value=saved.get('mqtt_port', 1883))
self.gateway_sn = tk.StringVar(value=saved.get('gateway_sn', ''))
self.dev_count = tk.IntVar( value=saved.get('devices', 1))
self.sn_vars = []

# --- Command map ---


self.cmd_map = {
'tên wifi': lambda: self.wifi_ssid.get(),
'mật khẩu wifi': lambda: self.wifi_pass.get(),
'sever mqtt': lambda: self.mqtt_broker.get(),
'port': lambda: str(self.mqtt_port.get()),
'username': lambda: self.username.get(),
'password': lambda: self.user_pass.get(),
'nhập seri của gateway': lambda: self.gateway_sn.get(),
'nhập số công tơ kết nối': lambda: str(self.dev_count.get()),
'seri': lambda: ",".join(v.get() for v in self.sn_vars)
}

# --- Serial port ---


self.ser = None
self._stop_read = threading.Event()

# --- Layout ---


pw = ttk.Panedwindow(self, orient='horizontal')
pw.pack(fill='both', expand=True)

# Left pane: config with scroll


left = ttk.Labelframe(pw, text="Cấu hình & Thiết bị")
pw.add(left, weight=1)
canvas = tk.Canvas(left)
scrollbar = ttk.Scrollbar(left, orient='vertical', command=canvas.yview)
canvas.configure(yscrollcommand=scrollbar.set)
scrollbar.pack(side='right', fill='y')
canvas.pack(side='left', fill='both', expand=True)
frame_cfg = ttk.Frame(canvas)
frame_cfg.bind('<Configure>', lambda e:
canvas.configure(scrollregion=canvas.bbox('all')))
canvas.create_window((0,0), window=frame_cfg, anchor='nw')

# Inputs
inputs = [
("WiFi SSID:", self.wifi_ssid),
("WiFi Pass:", self.wifi_pass),
("Username:", self.username),
("Password:", self.user_pass),
("MQTT Server:", self.mqtt_broker),
("MQTT Port:", self.mqtt_port)
]
for i, (lbl, var) in enumerate(inputs):
ttk.Label(frame_cfg, text=lbl).grid(row=i, column=0, padx=6, pady=6,
sticky='e')
width = 32 if isinstance(var, tk.StringVar) else 12
ttk.Entry(frame_cfg, textvariable=var, width=width).grid(row=i,
column=1, padx=6, pady=6, sticky='w')

row = len(inputs)
# Gateway SN
ttk.Label(frame_cfg, text="SN Gateway:").grid(row=row, column=0, padx=6,
pady=6, sticky='e')
ttk.Entry(frame_cfg, textvariable=self.gateway_sn, width=32).grid(row=row,
column=1, padx=6, pady=6, sticky='w')
# Device count
ttk.Label(frame_cfg, text="Số lượng thiết bị:").grid(row=row+1, column=0,
padx=6, pady=6, sticky='e')
spin = tk.Spinbox(frame_cfg, from_=1, to=30, textvariable=self.dev_count,
width=6, command=self.update_sn_entries)
spin.grid(row=row+1, column=1, padx=6, pady=6, sticky='w')
# SN entries
self.sn_frame = ttk.Frame(frame_cfg)
self.sn_frame.grid(row=row+2, column=0, columnspan=2, pady=8)
self.update_sn_entries()
# Right pane: serial & log
right = ttk.Frame(pw)
pw.add(right, weight=2)

# Connection frame
conn = ttk.Labelframe(right, text="Kết nối Gateway")
conn.pack(fill='x', padx=12, pady=(12,6))
ttk.Label(conn, text="Cổng COM:").grid(row=0, column=0, padx=6)
self.cmb_port = ttk.Combobox(conn, values=self.get_ports(), width=12)
self.cmb_port.grid(row=0, column=1, padx=6)
ttk.Button(conn, text="Làm mới", command=self.refresh_ports).grid(row=0,
column=2, padx=6)
ttk.Label(conn, text="Baud rate:").grid(row=0, column=3, padx=6)
self.cmb_baud = ttk.Combobox(conn,
values=[300,1200,2400,4800,9600,19200,38400,57600,115200], width=10)
self.cmb_baud.set(9600)
self.cmb_baud.grid(row=0, column=4, padx=6)
self.btn_connect = ttk.Button(conn, text="Kết nối", command=self.connect)
self.btn_connect.grid(row=0, column=5, padx=6)
self.btn_disconnect = ttk.Button(conn, text="Ngắt",
command=self.disconnect, state='disabled')
self.btn_disconnect.grid(row=0, column=6, padx=6)

# Log frame
logf = ttk.Labelframe(right, text="Dữ liệu nhận về")
logf.pack(fill='both', expand=True, padx=12, pady=6)
self.txt_log = scrolledtext.ScrolledText(logf, wrap='none',
font=('Consolas',11))
self.txt_log.pack(fill='both', expand=True, padx=6, pady=6)

# Action frame
act = ttk.Frame(right)
act.pack(fill='x', padx=12, pady=6)
self.btn_clear_data = tk.Button(act, text="Xóa dữ liệu", bg='red',
fg='white', command=self.clear_data, state='disabled')
self.btn_clear_data.pack(side='left', padx=(0,24))
self.btn_save = tk.Button(act, text="Lưu", bg='green', fg='white',
command=self.save_config, state='disabled')
self.btn_save.pack(side='left', padx=12)
self.btn_clear_log = ttk.Button(act, text="Xóa tin nhắn",
command=self.clear_log, state='disabled')
self.btn_clear_log.pack(side='right', padx=6)

def update_sn_entries(self):
for w in self.sn_frame.winfo_children():
w.destroy()
self.sn_vars.clear()
for i in range(self.dev_count.get()):
var = tk.StringVar(value="")
self.sn_vars.append(var)
ttk.Label(self.sn_frame, text=f"SN thiết bị {i+1}:").grid(row=i,
column=0, padx=6, pady=4, sticky='e')
ttk.Entry(self.sn_frame, textvariable=var, width=32).grid(row=i,
column=1, padx=6, pady=4, sticky='w')

def get_ports(self):
return [p.device for p in serial.tools.list_ports.comports()]

def refresh_ports(self):
self.cmb_port['values'] = self.get_ports()

def connect(self):
port = self.cmb_port.get()
baud = int(self.cmb_baud.get() or 0)
if not port or not baud:
messagebox.showwarning("Thiếu thông tin", "Chọn cổng và baudrate!")
return
try:
self.ser = serial.Serial(port, baud, timeout=0.1)
self.ser.dtr = False
time.sleep(0.05)
self.ser.dtr = True
self.ser.reset_input_buffer()
except Exception as e:
messagebox.showerror("Kết nối lỗi", str(e))
return
for b in [self.btn_clear_data, self.btn_clear_log, self.btn_disconnect]:
b.config(state='normal')
self.btn_connect.config(state='disabled')
self._stop_read.clear()
threading.Thread(target=self._read_thread, daemon=True).start()
self.log(f"✔ Đã kết nối {port} @ {baud}")

def disconnect(self):
if self.ser and self.ser.is_open:
self._stop_read.set()
self.ser.close()
for b in [self.btn_clear_data, self.btn_clear_log, self.btn_disconnect]:
b.config(state='disabled')
self.btn_connect.config(state='normal')
self.log("✖ Đã ngắt kết nối")

def clear_data(self):
if self.ser:
msg = "Đang xóa dữ liệu trước đó vui lòng không thao tác thêm ..."
self.ser.write((msg + "\n").encode('utf-8'))
self.log(f"{msg}")

def save_config(self):
if self.ser and self.ser.is_open:
self.ser.write(("y\n").encode('utf-8'))
self.log("y")
self.btn_save.config(state='disabled')
cfg = {
'ssid': self.wifi_ssid.get(),
'wifi_pass': self.wifi_pass.get(),
'username': self.username.get(),
'user_pass': self.user_pass.get(),
'mqtt_broker': self.mqtt_broker.get(),
'mqtt_port': self.mqtt_port.get(),
'gateway_sn': self.gateway_sn.get(),
'devices': self.dev_count.get(),
'serials': [v.get() for v in self.sn_vars]
}
try:
with open(CONFIG_FILE, 'w', encoding='utf-8') as f:
json.dump(cfg, f, ensure_ascii=False, indent=2)
except Exception as e:
messagebox.showerror("Lưu lỗi", str(e))

def clear_log(self):
self.txt_log.delete('1.0', tk.END)

def send_config(self):
cfg = {
'ssid': self.wifi_ssid.get(),
'wifi_pass': self.wifi_pass.get(),
'username': self.username.get(),
'user_pass': self.user_pass.get(),
'mqtt_broker': self.mqtt_broker.get(),
'mqtt_port': self.mqtt_port.get(),
'gateway_sn': self.gateway_sn.get(),
'devices': self.dev_count.get(),
'serials': [v.get() for v in self.sn_vars]
}
msg = json.dumps(cfg)
self.ser.write((msg + "\n").encode('utf-8'))
self.log(f"{msg}")

def _read_thread(self):
while not self._stop_read.is_set():
try:
raw = self.ser.readline()
if not raw:
continue
line = raw.decode('utf-8', errors='ignore').strip()
self.log(line)
# strip parentheses
key = re.sub(r"\(.*\)", "", line.lower()).rstrip(':').strip()
if key == 'xác nhận lưu cấu hình':
self.btn_save.config(state='normal')
continue
if key == 'seri gateway':
resp = self.gateway_sn.get()
elif re.match(r'nhập số công.*kết nối', key):
resp = str(self.dev_count.get())
elif m := re.match(r'số seri của công tơ\s*(\d+)', key):
idx = int(m.group(1)) - 1
resp = self.sn_vars[idx].get() if 0 <= idx < len(self.sn_vars)
else ''
elif key in self.cmd_map:
resp = self.cmd_map[key]()
elif key == 'getconfig':
self.send_config()
continue
else:
continue
self.ser.write((resp + "\n").encode())
self.log(f"➡ {resp}")
except:
break

def log(self, msg):


self.txt_log.insert('end', msg + '\n')
self.txt_log.see('end')

def on_close(self):
self.disconnect()
self.destroy()

if __name__ == '__main__':
app = SerialGUI()
app.mainloop()

You might also like