Simple serial monitor implementation
This commit is contained in:
@@ -5,12 +5,25 @@
|
||||
import dearpygui.dearpygui as dpg
|
||||
|
||||
from dataflux.state import AppState
|
||||
from dataflux.tags import MENU_FILE_CONNECT, MENU_FILE_DISCONNECT
|
||||
from dataflux.tags import (
|
||||
MENU_IO_CONNECT_LORA,
|
||||
MENU_IO_CONNECT_SERIAL,
|
||||
MENU_IO_DISCONNECT_LORA,
|
||||
MENU_IO_DISCONNECT_SERIAL,
|
||||
)
|
||||
|
||||
|
||||
def update_menu_file_connection_status(state: AppState) -> None:
|
||||
if state.serial_port is None:
|
||||
dpg.enable_item(MENU_FILE_CONNECT)
|
||||
dpg.disable_item(MENU_FILE_DISCONNECT)
|
||||
if state.lora_port is None:
|
||||
dpg.enable_item(MENU_IO_CONNECT_LORA)
|
||||
dpg.disable_item(MENU_IO_DISCONNECT_LORA)
|
||||
else:
|
||||
dpg.disable_item(MENU_FILE_CONNECT)
|
||||
dpg.enable_item(MENU_FILE_DISCONNECT)
|
||||
dpg.disable_item(MENU_IO_CONNECT_LORA)
|
||||
dpg.enable_item(MENU_IO_DISCONNECT_LORA)
|
||||
|
||||
if state.serial_port is None:
|
||||
dpg.enable_item(MENU_IO_CONNECT_SERIAL)
|
||||
dpg.disable_item(MENU_IO_DISCONNECT_SERIAL)
|
||||
else:
|
||||
dpg.disable_item(MENU_IO_CONNECT_SERIAL)
|
||||
dpg.enable_item(MENU_IO_DISCONNECT_SERIAL)
|
||||
|
||||
@@ -4,10 +4,26 @@
|
||||
|
||||
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_CONNECTED_BRIGHT, THEME_STATUS_DISCONNECTED
|
||||
from dataflux.tags import (
|
||||
STATUS_LORA_STATUS_BOX,
|
||||
STATUS_LORA_STATUS_TEXT,
|
||||
STATUS_SERIAL_STATUS_BOX,
|
||||
STATUS_SERIAL_STATUS_TEXT,
|
||||
THEME_STATUS_CONNECTED,
|
||||
THEME_STATUS_CONNECTED_BRIGHT,
|
||||
THEME_STATUS_DISCONNECTED,
|
||||
)
|
||||
from time import sleep
|
||||
|
||||
|
||||
def update_status_connection_status(state: AppState):
|
||||
if state.lora_port is None:
|
||||
dpg.bind_item_theme(STATUS_LORA_STATUS_BOX, THEME_STATUS_DISCONNECTED)
|
||||
dpg.set_value(STATUS_LORA_STATUS_TEXT, "LoRa: Disconnected")
|
||||
else:
|
||||
dpg.bind_item_theme(STATUS_LORA_STATUS_BOX, THEME_STATUS_CONNECTED)
|
||||
dpg.set_value(STATUS_LORA_STATUS_TEXT, "LoRa: Connected")
|
||||
|
||||
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")
|
||||
@@ -15,7 +31,8 @@ def update_status_connection_status(state: AppState):
|
||||
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_CONNECTED)
|
||||
dpg.set_value(STATUS_SERIAL_STATUS_TEXT, "Serial: Connected")
|
||||
|
||||
|
||||
def flash_status_connection_status(duration: float) -> None:
|
||||
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_CONNECTED_BRIGHT)
|
||||
sleep(duration)
|
||||
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_CONNECTED)
|
||||
dpg.bind_item_theme(STATUS_LORA_STATUS_BOX, THEME_STATUS_CONNECTED_BRIGHT)
|
||||
sleep(duration)
|
||||
dpg.bind_item_theme(STATUS_LORA_STATUS_BOX, THEME_STATUS_CONNECTED)
|
||||
|
||||
@@ -5,21 +5,47 @@ import dearpygui.dearpygui as dpg
|
||||
|
||||
import dataflux.config
|
||||
from dataflux.services.serial import list_serial_ports
|
||||
from dataflux.tags import PAGE_LAP_RECAP, PAGE_LIVE_DATA, SUB_PAGE_DATA_GRAPHS, SUB_PAGE_MAP, WINDOW_CONNECTION_MENU_COMBO
|
||||
from dataflux.state import AppState
|
||||
from dataflux.tags import (
|
||||
PAGE_LAP_RECAP,
|
||||
PAGE_LIVE_DATA,
|
||||
PAGE_SERIAL_CONSOLE,
|
||||
SUB_PAGE_DATA_GRAPHS,
|
||||
SUB_PAGE_MAP,
|
||||
WINDOW_LORA_CONNECTION_MENU_COMBO,
|
||||
WINDOW_SERIAL_CONNECTION_MENU_COMBO,
|
||||
)
|
||||
|
||||
def update_window_connection_menu_combo() -> None:
|
||||
|
||||
def update_window_lora_connection_menu_combo(state: AppState) -> None:
|
||||
ports: list[str] = list_serial_ports()
|
||||
dpg.configure_item(WINDOW_CONNECTION_MENU_COMBO, items=ports)
|
||||
if state.serial_port is not None and state.serial_thread_running:
|
||||
port_name = state.serial_port.name
|
||||
|
||||
if port_name in ports:
|
||||
ports.remove(port_name)
|
||||
dpg.configure_item(WINDOW_LORA_CONNECTION_MENU_COMBO, items=ports)
|
||||
|
||||
|
||||
def update_window_serial_connection_menu_combo(state: AppState) -> None:
|
||||
ports: list[str] = list_serial_ports()
|
||||
if state.lora_port is not None and state.lora_thread_running:
|
||||
port_name = state.lora_port.name
|
||||
|
||||
if port_name in ports:
|
||||
ports.remove(port_name)
|
||||
dpg.configure_item(WINDOW_SERIAL_CONNECTION_MENU_COMBO, items=ports)
|
||||
|
||||
|
||||
def hide_all_but(tag: str) -> None:
|
||||
arr = [PAGE_LIVE_DATA, PAGE_LAP_RECAP]
|
||||
arr = [PAGE_LIVE_DATA, PAGE_LAP_RECAP, PAGE_SERIAL_CONSOLE]
|
||||
for item in arr:
|
||||
if tag == item:
|
||||
dpg.show_item(item)
|
||||
else:
|
||||
dpg.hide_item(item)
|
||||
|
||||
|
||||
def toggle_window(tag: str) -> None:
|
||||
if tag == SUB_PAGE_DATA_GRAPHS:
|
||||
dpg.show_item(SUB_PAGE_DATA_GRAPHS)
|
||||
@@ -31,6 +57,3 @@ def toggle_window(tag: str) -> None:
|
||||
hide_all_but(PAGE_LIVE_DATA)
|
||||
else:
|
||||
hide_all_but(tag)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -22,21 +22,29 @@ from dataflux.tags import (
|
||||
LIVE_DATA_VBAT_VALUE,
|
||||
LIVE_DATA_VEHICLE_TIME_VALUE,
|
||||
LIVE_DATA_SPEED_VALUE,
|
||||
MENU_FILE_CONNECT,
|
||||
MENU_FILE_DISCONNECT,
|
||||
MENU_IO_CONNECT_LORA,
|
||||
MENU_IO_DISCONNECT_LORA,
|
||||
MENU_FILE_DUMP_BUFFERS,
|
||||
MENU_IO_CONNECT_SERIAL,
|
||||
MENU_IO_DISCONNECT_SERIAL,
|
||||
PAGE_LAP_RECAP,
|
||||
PAGE_LIVE_DATA,
|
||||
PAGE_SERIAL_CONSOLE,
|
||||
STATUS_LORA_STATUS_BOX,
|
||||
STATUS_LORA_STATUS_TEXT,
|
||||
STATUS_SERIAL_STATUS_BOX,
|
||||
STATUS_SERIAL_STATUS_TEXT,
|
||||
SUB_PAGE_DATA_GRAPHS,
|
||||
SUB_PAGE_MAP,
|
||||
TEXT_SERIAL_CONSOLE,
|
||||
THEME_STATUS_CONNECTED,
|
||||
THEME_STATUS_CONNECTED_BRIGHT,
|
||||
THEME_STATUS_DISCONNECTED,
|
||||
WINDOW_CONNECTION_MENU,
|
||||
WINDOW_CONNECTION_MENU_COMBO,
|
||||
WINDOW_LORA_CONNECTION_MENU,
|
||||
WINDOW_LORA_CONNECTION_MENU_COMBO,
|
||||
WINDOW_FILE_DIALOG_DUMP_BUFFERS,
|
||||
WINDOW_SERIAL_CONNECTION_MENU,
|
||||
WINDOW_SERIAL_CONNECTION_MENU_COMBO,
|
||||
)
|
||||
from dataflux.ui.colors import STATUS_GREEN_BRIGHT, STATUS_GREEN_DARK, STATUS_RED_DARK
|
||||
|
||||
@@ -57,19 +65,6 @@ def build_windows(state: AppState) -> None:
|
||||
dpg.set_global_font_scale(0.5)
|
||||
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,
|
||||
callback=dataflux.callbacks.menu.menu_file_disconnect,
|
||||
user_data=state,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Dump Buffers",
|
||||
enabled=True,
|
||||
@@ -77,6 +72,35 @@ def build_windows(state: AppState) -> None:
|
||||
callback=dataflux.callbacks.menu.menu_file_dump_buffers,
|
||||
)
|
||||
dpg.add_menu_item(label="Quit")
|
||||
with dpg.menu(label="IO"):
|
||||
dpg.add_menu_item(
|
||||
label="Connect LoRa",
|
||||
enabled=True,
|
||||
tag=MENU_IO_CONNECT_LORA,
|
||||
callback=dataflux.callbacks.menu.open_lora_connection_window,
|
||||
user_data=state,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Disonnect LoRa",
|
||||
enabled=False,
|
||||
tag=MENU_IO_DISCONNECT_LORA,
|
||||
callback=dataflux.callbacks.menu.menu_io_disconnect_lora,
|
||||
user_data=state,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Connect Serial",
|
||||
enabled=True,
|
||||
tag=MENU_IO_CONNECT_SERIAL,
|
||||
callback=dataflux.callbacks.menu.open_serial_connection_window,
|
||||
user_data=state,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Disonnect Serial",
|
||||
enabled=False,
|
||||
tag=MENU_IO_DISCONNECT_SERIAL,
|
||||
callback=dataflux.callbacks.menu.menu_io_disconnect_serial,
|
||||
user_data=state,
|
||||
)
|
||||
with dpg.menu(label="Window"):
|
||||
dpg.add_menu_item(
|
||||
label="Live Graphs",
|
||||
@@ -93,6 +117,11 @@ def build_windows(state: AppState) -> None:
|
||||
user_data=PAGE_LAP_RECAP,
|
||||
callback=dataflux.callbacks.menu.menu_window_select,
|
||||
)
|
||||
dpg.add_menu_item(
|
||||
label="Serial Console",
|
||||
user_data=PAGE_SERIAL_CONSOLE,
|
||||
callback=dataflux.callbacks.menu.menu_window_select,
|
||||
)
|
||||
with dpg.menu(label="Data"):
|
||||
with dpg.menu(label="Timeframe"):
|
||||
dpg.add_menu_item(
|
||||
@@ -255,6 +284,18 @@ def build_windows(state: AppState) -> None:
|
||||
dpg.add_text("Lap Recap")
|
||||
dpg.add_separator()
|
||||
|
||||
with dpg.group(tag=PAGE_SERIAL_CONSOLE, show=False):
|
||||
with dpg.child_window(
|
||||
width=-1,
|
||||
height=-40,
|
||||
border=True,
|
||||
horizontal_scrollbar=False,
|
||||
):
|
||||
dpg.add_text(tag=TEXT_SERIAL_CONSOLE, wrap=0)
|
||||
with dpg.group(horizontal=True):
|
||||
dpg.add_input_text(width=-100)
|
||||
dpg.add_button(label="Send", width=100)
|
||||
|
||||
with dpg.theme(tag=THEME_STATUS_CONNECTED):
|
||||
with dpg.theme_component(dpg.mvChildWindow):
|
||||
dpg.add_theme_color(dpg.mvThemeCol_ChildBg, STATUS_GREEN_DARK)
|
||||
@@ -275,6 +316,33 @@ def build_windows(state: AppState) -> None:
|
||||
no_scrollbar=True,
|
||||
):
|
||||
with dpg.group(horizontal=True):
|
||||
with dpg.child_window(
|
||||
width=200, height=28, border=False, tag=STATUS_LORA_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(
|
||||
"LoRa: Disconnected",
|
||||
tag=STATUS_LORA_STATUS_TEXT,
|
||||
)
|
||||
with dpg.table_cell():
|
||||
pass
|
||||
with dpg.child_window(
|
||||
width=200, height=28, border=False, tag=STATUS_SERIAL_STATUS_BOX
|
||||
):
|
||||
@@ -295,27 +363,43 @@ def build_windows(state: AppState) -> None:
|
||||
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_LORA_STATUS_BOX, THEME_STATUS_DISCONNECTED)
|
||||
dpg.bind_item_theme(STATUS_SERIAL_STATUS_BOX, THEME_STATUS_DISCONNECTED)
|
||||
|
||||
with dpg.window(
|
||||
label="Connection Menu",
|
||||
tag=WINDOW_CONNECTION_MENU,
|
||||
label="LoRa Connection Menu",
|
||||
tag=WINDOW_LORA_CONNECTION_MENU,
|
||||
show=False,
|
||||
modal=True,
|
||||
no_collapse=True,
|
||||
width=300,
|
||||
width=400,
|
||||
no_resize=True,
|
||||
):
|
||||
dpg.add_combo([], tag=WINDOW_CONNECTION_MENU_COMBO)
|
||||
dpg.add_combo([], tag=WINDOW_LORA_CONNECTION_MENU_COMBO)
|
||||
dpg.add_button(
|
||||
label="Connect",
|
||||
callback=dataflux.callbacks.serial.connection_window_connect_lora,
|
||||
user_data=state,
|
||||
)
|
||||
|
||||
with dpg.window(
|
||||
label="Serial Connection Menu",
|
||||
tag=WINDOW_SERIAL_CONNECTION_MENU,
|
||||
show=False,
|
||||
modal=True,
|
||||
no_collapse=True,
|
||||
width=400,
|
||||
no_resize=True,
|
||||
):
|
||||
dpg.add_combo([], tag=WINDOW_SERIAL_CONNECTION_MENU_COMBO)
|
||||
dpg.add_button(
|
||||
label="Connect",
|
||||
callback=dataflux.callbacks.serial.connection_window_connect_serial,
|
||||
|
||||
@@ -8,7 +8,17 @@ import time
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from dataflux.state import AppState
|
||||
from dataflux.tags import GRAPH_SERIES_SPEED, GRAPH_SERIES_TENG, GRAPH_SERIES_VBAT, GRAPH_X_AXIS_SPEED, LIVE_DATA_TENG_VALUE, LIVE_DATA_UTC_TIME_VALUE, LIVE_DATA_VBAT_VALUE, LIVE_DATA_VEHICLE_TIME_VALUE, LIVE_DATA_SPEED_VALUE
|
||||
from dataflux.tags import (
|
||||
GRAPH_SERIES_SPEED,
|
||||
GRAPH_SERIES_TENG,
|
||||
GRAPH_SERIES_VBAT,
|
||||
GRAPH_X_AXIS_SPEED,
|
||||
LIVE_DATA_TENG_VALUE,
|
||||
LIVE_DATA_UTC_TIME_VALUE,
|
||||
LIVE_DATA_VBAT_VALUE,
|
||||
LIVE_DATA_VEHICLE_TIME_VALUE,
|
||||
LIVE_DATA_SPEED_VALUE,
|
||||
)
|
||||
|
||||
|
||||
def ui_worker(state: AppState):
|
||||
@@ -18,15 +28,15 @@ def ui_worker(state: AppState):
|
||||
last_vbat: str = ""
|
||||
last_teng: str = ""
|
||||
no_data_written = False
|
||||
while state.running:
|
||||
while state.running:
|
||||
now = datetime.now(timezone.utc)
|
||||
formatted = now.strftime("%H:%M:%S")
|
||||
|
||||
|
||||
if formatted != last_datetime:
|
||||
dpg.set_value(LIVE_DATA_UTC_TIME_VALUE, formatted)
|
||||
last_datetime = formatted
|
||||
|
||||
if state.serial_thread_running and state.telemetry_valid:
|
||||
|
||||
if state.lora_thread_running and state.telemetry_valid:
|
||||
x_common: list[float] | None = None
|
||||
speed_y: list[float] | None = None
|
||||
vbat_y: list[float] | None = None
|
||||
@@ -59,7 +69,6 @@ def ui_worker(state: AppState):
|
||||
dpg.set_value(LIVE_DATA_SPEED_VALUE, formatted)
|
||||
last_veh_speed = formatted
|
||||
|
||||
|
||||
# VBAT
|
||||
formatted = f"{vbat:05.2f}"
|
||||
if formatted != last_vbat:
|
||||
@@ -87,7 +96,3 @@ def ui_worker(state: AppState):
|
||||
no_data_written = True
|
||||
|
||||
time.sleep(0.05)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user