Dokumentace – main.py - Tkinter GUI aplikace s BLE komunikací

Aktuální popis Tkinter GUI propojeného s BLE backendem, vícevláknovým řízením, historií a grafy.

← Zpět na hlavní dokumentaci

1. Přehled aplikace

Aplikace tvoří kompletní řídicí rozhraní pro balancer LTC3300-2. Součásti systému:

Aplikace používá dva typy grafů: mini-grafy (krátká historie) a velký graf (full history).

2. Moduly a jejich role

ModulÚčel
ui_radiobuttonsVytváří radiobuttony, poskytuje callback, umožňuje jejich změny z programu
ui_rectanglesBarevné obdélníky + legenda barev
ui_entriesVstupní pole a historie v 2. řádku
ui_buttonsTlačítka Run/Send + jejich vizuální indikace
ui_checkbuttonsFiltrace grafu – zapínání/vypínání jednotlivých křivek
ui_plotsMini grafy + full-history graf, aktualizace
Ble.pyAsynchronní BLE komunikace, zpracování GATT notifikací
thread_worker.pyWorker thread – doplňkové logiky a reakce na události
gui_helpersZpracování fronty → bezpečný výpis do GUI
globals.pyUkládá sdílené stavy jako user_changed_radio, lower_than_3...
my_tools.pyRAM-disk soubory, Sresp a Uresp parser, ukládání CSV

3. Dvě komunikační fronty

Aplikace nově používá dva oddělené Queue objekty:

GUI zpracovává fronty pomocí:

process_queue(root, text, queue_to_main, queue_from_main)

Tím je zajištěna úplná separace toků zpráv.

4. Vlákna

4.1 BLE vlákno


ble_thread = threading.Thread(
    target=lambda: start_call_ble(ADDRESS, queue_to_main)
)
ble_thread.start()

4.2 Periodické vlákno


thread = threading.Thread(
    target=run_periodically,
    args=(5, '1', radio_vars),
    daemon=True
)
thread.start()

4.3 Worker vlákno


Th_work_start(queue_to_main, queue_from_main)

Toto vlákno komunikuje přes obě fronty a provádí pomocné logiky.

4.4 Uzavření programu

Bezpečné ukončení


stop_event.set()
stop_call_ble()
Th_work_stop()
root.destroy()

5. GUI prvky

GUI inicializuje:

Kritická část: GUI komponenty musí být vytvořeny v hlavním vlákně Tkinteru.

6. Radiobutton logika

Radiobuttony slouží jako vstupní stavové hodnoty (0-4). Nová logika:


def radio_event_handler(row, value):
    if Initialized < 2:
        return
    if not globals.not_user_changed_radio:
        globals.user_changed_radio = True
        set_send_button_color(True)

Přijaté hodnoty Sresp mohou radiobuttony přepsat:


radio_vars[i].set(v)
ui.on_radio_change(i, v)
set_rectangle_color(i, v)

7. Grafy

Mini grafy (7 hodnot):


historyU = [deque(maxlen=100) for _ in range(7)]
init_plots(frame_plots, historyU)
update_plots(historyU)

Full-history graf:


fig_full_history, axes_full_history = init_full_history_plot(historyU)
canvas_full_history = FigureCanvasTkAgg(fig, master=frame)
update_full_history_plot(historyU, canvas_full_history)

Filtrace grafů pomocí checkbuttonů:


create_checkbuttons(root, historyU, canvas_full_history)

8. Periodická logika

Funkce run_periodically běží každých 5 sekund.

Fáze:

1️⃣ Odeslání S


create_file_to_send('S')
RunProcess = -1

2️⃣ Po obdržení souboru Sresp


values = DataFromSresp(...)
radio_vars[i].set(...)
set_rectangle_color(...)

3️⃣ Odeslání U

4️⃣ Po obdržení Uresp


valuesU = DataFromUresp(historyU)
lower_than_3 = any(v < 3.200 ...)
higher_than_4_2 = any(v > 4.200 ...)
root.after(0, set_entries)
update_plots(...)
update_full_history_plot(...)
save_full_state_to_csv(...)
Th_set_history(historyU)

9. Tok programu

Start Tkinter GUI
   ↓
Vytvoření obdélníků, entry, radiobuttonů, grafů, checkbuttonů
   ↓
Spuštění BLE vlákna
   ↓
Spuštění worker threadu
   ↓
Spuštění periodického vlákna
   ↓
Každých 5 sekund:
    - odešli S → načti → aktualizuj radiobuttony + barvy
    - odešli U → načti → aktualizuj hodnoty + grafy
   ↓
Uživatel může měnit radiobuttony → aktivuje tlačítko Send
   ↓
Kliknutí Run/Send zapisuje příkaz do RAM disk souboru
   ↓
Zavření okna → stop_event → ukončení všech vláken

Stavový diagram – main.py

Následující schéma zobrazuje kompletní architekturu main.py – včetně GUI vlákna (Tkinter), BLE vlákna, worker vlákna, obousměrných front a hlavní smyčky run_periodically() s řízením stavů RunProcess = 1 → -1 → 2 → -2 → 1….

Stavový diagram – main.py (GUI, BLE, Worker, run_periodically) GUI THREAD Tkinter mainloop process_queue() + root.after() BLE THREAD start_call_ble() WORKER THREAD thread_worker.py run_periodically() cyklický režim RunProcess 1 → -1 → 2 → -2 → 1 RunProcess state loop RunProcess == 1 → create_file_to_send('S') → čekám na Sresp RunProcess == -1 → If_FileExist(1)? → DataFromSresp() → nastavení radiobuttonů RunProcess == 2 → create_file_to_send('U') → čekám na Uresp RunProcess == -2 → If_FileExist(2)? → DataFromUresp() → update GUI + plots queue_to_main.put() queue_from_main.put() start thread root.after() create_file_to_send() Sresp/Uresp