Working serial connection and disconnection mechanic

This commit is contained in:
2026-04-05 22:33:38 +02:00
parent fb35d6c3d4
commit 3f9a0126fa
9 changed files with 124 additions and 9 deletions

View File

@@ -19,7 +19,7 @@ def run() -> None:
app_font = dpg.add_font("./Inter-Regular.ttf", 18)
dpg.bind_font(app_font)
dataflux.ui.windows.build_windows()
dataflux.ui.windows.build_windows(state)
dpg.setup_dearpygui()
dpg.show_viewport()

View File

@@ -2,10 +2,18 @@
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
import dearpygui.dearpygui as dpg
from dataflux.ui.routines import update_global_connection_status
import dataflux.ui.routines.windows
import dataflux.ui.routines.status
import dataflux.services.serial
from dataflux.tags import WINDOW_CONNECTION_MENU
def open_connection_window(sender, app_data, user_data) -> None:
dataflux.ui.routines.windows.update_window_connection_menu_combo()
dpg.show_item(WINDOW_CONNECTION_MENU)
def menu_file_disconnect(sender, app_data, user_data) -> None:
dataflux.services.serial.disconnect_serial(user_data)
update_global_connection_status(user_data)

View File

@@ -0,0 +1,18 @@
# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
import dearpygui.dearpygui as dpg
import dataflux.services.serial
import dataflux.ui.routines
from dataflux.state import AppState
from dataflux.tags import WINDOW_CONNECTION_MENU, WINDOW_CONNECTION_MENU_COMBO
def connection_window_connect_serial(sender, app_data, user_data: AppState) -> None:
device = dpg.get_value(WINDOW_CONNECTION_MENU_COMBO)
dataflux.services.serial.connect_serial(user_data, device)
dataflux.ui.routines.update_global_connection_status(user_data)
dpg.hide_item(WINDOW_CONNECTION_MENU)

View File

@@ -2,8 +2,11 @@
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
from serial import Serial
import serial.tools.list_ports
from dataflux.state import AppState
def list_serial_ports() -> list[str]:
ports = serial.tools.list_ports.comports()
@@ -14,5 +17,17 @@ def list_serial_ports() -> list[str]:
return valid_ports
def connect_serial(state: AppState, device: str) -> None:
if state.serial_port is not None:
state.serial_port.close()
state.serial_port = None
state.serial_port = Serial(port=device, baudrate=115200)
def disconnect_serial(state: AppState) -> None:
if state.serial_port is not None:
state.serial_port.close()
state.serial_port = None

View File

@@ -6,3 +6,9 @@ MENU_FILE_CONNECT: str = "menu_file_connect"
MENU_FILE_DISCONNECT: str = "menu_file_disconnect"
WINDOW_CONNECTION_MENU: str = "window_connection_menu"
WINDOW_CONNECTION_MENU_COMBO: str = "window_connection_menu_combo"
STATUS_SERIAL_STATUS_BOX: str = "status_serial_status_box"
STATUS_SERIAL_STATUS_TEXT: str = "status_serial_status_text"
THEME_STATUS_DISCONNECTED: str = "theme_status_disconnected"
THEME_STATUS_CONNECTED: str = "theme_status_connected"

12
src/dataflux/ui/colors.py Normal file
View File

@@ -0,0 +1,12 @@
# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
STATUS_RED_DARK = (140, 35, 35, 255)
STATUS_RED_BRIGHT = (255, 70, 70, 255)
STATUS_ORANGE_DARK = (160, 90, 20, 255)
STATUS_ORANGE_BRIGHT= (255, 165, 40, 255)
STATUS_GREEN_DARK = (40, 130, 55, 255)
STATUS_GREEN_BRIGHT = (70, 255, 110, 255)

View File

@@ -0,0 +1,14 @@
# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
import dearpygui.dearpygui as dpg
import dataflux.ui.routines.menu
import dataflux.ui.routines.status
from dataflux.state import AppState
def update_global_connection_status(state: AppState):
dataflux.ui.routines.menu.update_menu_file_connection_status(state)
dataflux.ui.routines.status.update_status_connection_status(state)

View File

@@ -0,0 +1,15 @@
# Copyright (C) 2026 Hector van der Aa <hector@h3cx.dev>
# Copyright (C) 2026 Association Exergie <association.exergie@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
import dearpygui.dearpygui as dpg
from dataflux.state import AppState
from dataflux.tags import STATUS_SERIAL_STATUS_BOX, STATUS_SERIAL_STATUS_TEXT, THEME_STATUS_CONNECTED, THEME_STATUS_DISCONNECTED
def update_status_connection_status(state: AppState):
if state.serial_port is None:
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_DISCONNECTED)
dpg.set_value(STATUS_SERIAL_STATUS_TEXT, "Serial: Disconnected")
else:
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_CONNECTED)
dpg.set_value(STATUS_SERIAL_STATUS_TEXT, "Serial: Connected")

View File

@@ -4,26 +4,26 @@
import dearpygui.dearpygui as dpg
import dataflux.callbacks.menu
import dataflux.callbacks.serial
from dataflux.tags import MENU_FILE_CONNECT, MENU_FILE_DISCONNECT, WINDOW_CONNECTION_MENU, WINDOW_CONNECTION_MENU_COMBO
from dataflux.state import AppState
from dataflux.tags import MENU_FILE_CONNECT, MENU_FILE_DISCONNECT, STATUS_SERIAL_STATUS_BOX, STATUS_SERIAL_STATUS_TEXT, THEME_STATUS_CONNECTED, THEME_STATUS_DISCONNECTED, WINDOW_CONNECTION_MENU, WINDOW_CONNECTION_MENU_COMBO
from dataflux.ui.colors import STATUS_GREEN_DARK, STATUS_RED_DARK
def build_windows() -> None:
def build_windows(state: AppState) -> None:
with dpg.window(label='DataFlux',tag="main_window", no_collapse=True):
with dpg.menu_bar():
with dpg.menu(label='File'):
dpg.add_menu_item(label="Connect", enabled=True, tag=MENU_FILE_CONNECT, callback=dataflux.callbacks.menu.open_connection_window)
dpg.add_menu_item(label="Disonnect", enabled=False, tag=MENU_FILE_DISCONNECT)
dpg.add_menu_item(label="Disonnect", enabled=False, tag=MENU_FILE_DISCONNECT, callback=dataflux.callbacks.menu.menu_file_disconnect, user_data=state)
dpg.add_menu_item(label="Quit")
with dpg.menu(label='Window'):
dpg.add_menu_item(label="Live Data", user_data="page_live_data")
dpg.add_menu_item(label="Lap Recap", user_data="page_lap_recap")
with dpg.child_window(tag="content_area", autosize_x=True, autosize_y=True, border=False):
with dpg.child_window(tag="content_area", autosize_x=True, height=-32, border=False):
with dpg.group(tag="page_live_data", show=True):
dpg.add_text("Live Data")
dpg.add_separator()
with dpg.group(horizontal=True):
with dpg.child_window(tag="realtime_stats", width=250, autosize_y=True, border=True):
dpg.add_text("Speed: 25kmh")
@@ -40,6 +40,33 @@ def build_windows() -> None:
dpg.add_text("Lap Recap")
dpg.add_separator()
with dpg.theme(tag=THEME_STATUS_CONNECTED):
with dpg.theme_component(dpg.mvChildWindow):
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, STATUS_GREEN_DARK)
with dpg.theme(tag=THEME_STATUS_DISCONNECTED):
with dpg.theme_component(dpg.mvChildWindow):
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, STATUS_RED_DARK)
with dpg.child_window(tag="footer_bar", autosize_x=True, height=28, border=False, no_scrollbar=True):
with dpg.group(horizontal=True):
with dpg.child_window(width=200, height=28, border=False, tag=STATUS_SERIAL_STATUS_BOX):
with dpg.table(header_row=False, resizable=False, policy=dpg.mvTable_SizingStretchProp, borders_innerV=False, borders_innerH=False, borders_outerH=False, borders_outerV=False, no_host_extendX=False, no_pad_innerX=True):
dpg.add_table_column(init_width_or_weight=1.0)
dpg.add_table_column(width_fixed=True)
dpg.add_table_column(init_width_or_weight=1.0)
with dpg.table_row():
with dpg.table_cell():
pass
with dpg.table_cell():
dpg.add_text("Serial: Disconnected", tag=STATUS_SERIAL_STATUS_TEXT)
with dpg.table_cell():
pass
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_DISCONNECTED)
with dpg.window(label="Connection Menu", tag=WINDOW_CONNECTION_MENU, show=False, modal=True, no_collapse=True, width=300):
dpg.add_combo([], tag=WINDOW_CONNECTION_MENU_COMBO)
dpg.add_button(label="Connect")
dpg.add_button(label="Connect", callback=dataflux.callbacks.serial.connection_window_connect_serial, user_data=state)