Added graph timeframe option
This commit is contained in:
@@ -11,7 +11,13 @@ import dataflux.ui.routines.status
|
|||||||
import dataflux.services.serial
|
import dataflux.services.serial
|
||||||
import dataflux.services.telemetry
|
import dataflux.services.telemetry
|
||||||
|
|
||||||
from dataflux.tags import WINDOW_CONNECTION_MENU, WINDOW_FILE_DIALOG_DUMP_BUFFERS
|
from dataflux.tags import (
|
||||||
|
GRAPH_X_AXIS_SPEED,
|
||||||
|
GRAPH_X_AXIS_TENG,
|
||||||
|
GRAPH_X_AXIS_VBAT,
|
||||||
|
WINDOW_CONNECTION_MENU,
|
||||||
|
WINDOW_FILE_DIALOG_DUMP_BUFFERS,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def open_connection_window(sender, app_data, user_data) -> None:
|
def open_connection_window(sender, app_data, user_data) -> None:
|
||||||
@@ -39,3 +45,11 @@ def window_file_dialog_dump_buffers_ok(sender, app_data, user_data: AppState) ->
|
|||||||
|
|
||||||
def menu_window_select(sender, app_data, user_data: str) -> None:
|
def menu_window_select(sender, app_data, user_data: str) -> None:
|
||||||
dataflux.ui.routines.windows.toggle_window(user_data)
|
dataflux.ui.routines.windows.toggle_window(user_data)
|
||||||
|
|
||||||
|
|
||||||
|
def menu_data_timeframe(sender, app_data, user_data: tuple[AppState, int]) -> None:
|
||||||
|
app_state, timeframe = user_data
|
||||||
|
app_state.live_buffer_len = timeframe
|
||||||
|
dpg.set_axis_limits(GRAPH_X_AXIS_SPEED, ymin=-(timeframe), ymax=0)
|
||||||
|
dpg.set_axis_limits(GRAPH_X_AXIS_VBAT, ymin=-(timeframe), ymax=0)
|
||||||
|
dpg.set_axis_limits(GRAPH_X_AXIS_TENG, ymin=-(timeframe), ymax=0)
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ import time
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import csv
|
import csv
|
||||||
|
|
||||||
LIVE_BUFFER_WINDOW_CS = 30 * 100
|
|
||||||
|
|
||||||
def telemetry_worker(state: AppState):
|
def telemetry_worker(state: AppState):
|
||||||
while state.telemetry_thread_running:
|
while state.telemetry_thread_running:
|
||||||
if state.serial_thread_running == False:
|
if not state.serial_thread_running:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
@@ -23,8 +22,6 @@ def telemetry_worker(state: AppState):
|
|||||||
state.latest_telemetry = dataframe
|
state.latest_telemetry = dataframe
|
||||||
state.telemetry_valid = True
|
state.telemetry_valid = True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
with state.lock:
|
with state.lock:
|
||||||
state.raw_buffers.timestamp.append(dataframe["time_stamp"])
|
state.raw_buffers.timestamp.append(dataframe["time_stamp"])
|
||||||
state.raw_buffers.speed.append(dataframe["speed"])
|
state.raw_buffers.speed.append(dataframe["speed"])
|
||||||
@@ -45,12 +42,14 @@ def telemetry_worker(state: AppState):
|
|||||||
return
|
return
|
||||||
|
|
||||||
last_timestamp = state.raw_buffers.timestamp[-1]
|
last_timestamp = state.raw_buffers.timestamp[-1]
|
||||||
cutoff = last_timestamp - LIVE_BUFFER_WINDOW_CS
|
cutoff = last_timestamp - (state.live_buffer_len * 100)
|
||||||
|
|
||||||
i = len(state.raw_buffers.timestamp) - 1
|
i = len(state.raw_buffers.timestamp) - 1
|
||||||
|
|
||||||
while i >= 0 and state.raw_buffers.timestamp[i] >= cutoff:
|
while i >= 0 and state.raw_buffers.timestamp[i] >= cutoff:
|
||||||
elapsed_seconds = (state.raw_buffers.timestamp[i] - last_timestamp) / 100.0
|
elapsed_seconds = (
|
||||||
|
state.raw_buffers.timestamp[i] - last_timestamp
|
||||||
|
) / 100.0
|
||||||
state.live_buffers.timestamp.append(elapsed_seconds)
|
state.live_buffers.timestamp.append(elapsed_seconds)
|
||||||
state.live_buffers.speed.append(state.raw_buffers.speed[i])
|
state.live_buffers.speed.append(state.raw_buffers.speed[i])
|
||||||
state.live_buffers.vbat.append(state.raw_buffers.vbat[i])
|
state.live_buffers.vbat.append(state.raw_buffers.vbat[i])
|
||||||
@@ -66,8 +65,9 @@ def telemetry_worker(state: AppState):
|
|||||||
state.live_buffers.lat.reverse()
|
state.live_buffers.lat.reverse()
|
||||||
state.live_buffers.lng.reverse()
|
state.live_buffers.lng.reverse()
|
||||||
|
|
||||||
|
|
||||||
def buffer_dump(state: AppState, path: str):
|
def buffer_dump(state: AppState, path: str):
|
||||||
save_path = Path(path)
|
save_path = Path(path)
|
||||||
if save_path.is_dir():
|
if save_path.is_dir():
|
||||||
save_path = save_path / "output.csv"
|
save_path = save_path / "output.csv"
|
||||||
|
|
||||||
@@ -86,9 +86,14 @@ def buffer_dump(state: AppState, path: str):
|
|||||||
|
|
||||||
writer.writerow(["timestamp", "speed", "vbat", "teng", "lat", "lng"])
|
writer.writerow(["timestamp", "speed", "vbat", "teng", "lat", "lng"])
|
||||||
|
|
||||||
for row in zip(local_raw_buffers.timestamp, local_raw_buffers.speed, local_raw_buffers.vbat, local_raw_buffers.teng, local_raw_buffers.lat, local_raw_buffers.lng):
|
for row in zip(
|
||||||
|
local_raw_buffers.timestamp,
|
||||||
|
local_raw_buffers.speed,
|
||||||
|
local_raw_buffers.vbat,
|
||||||
|
local_raw_buffers.teng,
|
||||||
|
local_raw_buffers.lat,
|
||||||
|
local_raw_buffers.lng,
|
||||||
|
):
|
||||||
writer.writerow(row)
|
writer.writerow(row)
|
||||||
|
|
||||||
state.buffer_dump_thread = None
|
state.buffer_dump_thread = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from threading import Lock, Thread
|
|||||||
from serial import Serial
|
from serial import Serial
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Buffers:
|
class Buffers:
|
||||||
timestamp: list[int] = field(default_factory=list)
|
timestamp: list[int] = field(default_factory=list)
|
||||||
@@ -16,6 +17,7 @@ class Buffers:
|
|||||||
lat: list[float] = field(default_factory=list)
|
lat: list[float] = field(default_factory=list)
|
||||||
lng: list[float] = field(default_factory=list)
|
lng: list[float] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class AppState:
|
class AppState:
|
||||||
running: bool = True
|
running: bool = True
|
||||||
@@ -39,6 +41,7 @@ class AppState:
|
|||||||
raw_buffers: Buffers = field(default_factory=Buffers)
|
raw_buffers: Buffers = field(default_factory=Buffers)
|
||||||
live_buffers: Buffers = field(default_factory=Buffers)
|
live_buffers: Buffers = field(default_factory=Buffers)
|
||||||
live_buffers_updated: bool = False
|
live_buffers_updated: bool = False
|
||||||
|
live_buffer_len: int = 30
|
||||||
|
|
||||||
buffer_dump_thread: Thread | None = None
|
buffer_dump_thread: Thread | None = None
|
||||||
|
|
||||||
|
|||||||
@@ -95,8 +95,46 @@ def build_windows(state: AppState) -> None:
|
|||||||
)
|
)
|
||||||
with dpg.menu(label="Data"):
|
with dpg.menu(label="Data"):
|
||||||
with dpg.menu(label="Timeframe"):
|
with dpg.menu(label="Timeframe"):
|
||||||
dpg.add_menu_item(label="30s")
|
dpg.add_menu_item(
|
||||||
dpg.add_menu_item(label="60s")
|
label="30s",
|
||||||
|
user_data=(state, 30),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="60s",
|
||||||
|
user_data=(state, 60),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="5m",
|
||||||
|
user_data=(state, 60 * 5),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="10m",
|
||||||
|
user_data=(state, 60 * 10),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="15m",
|
||||||
|
user_data=(state, 60 * 15),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="30m",
|
||||||
|
user_data=(state, 60 * 30),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="1h",
|
||||||
|
user_data=(state, 60 * 60),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
dpg.add_menu_item(
|
||||||
|
label="2h",
|
||||||
|
user_data=(state, 60 * 120),
|
||||||
|
callback=dataflux.callbacks.menu.menu_data_timeframe,
|
||||||
|
)
|
||||||
|
|
||||||
with dpg.child_window(
|
with dpg.child_window(
|
||||||
tag="content_area", autosize_x=True, height=-32, border=False
|
tag="content_area", autosize_x=True, height=-32, border=False
|
||||||
|
|||||||
Reference in New Issue
Block a user