This commit is contained in:
2025-04-19 23:06:54 +02:00
parent e4663df500
commit 05abcca6f5
5 changed files with 143 additions and 59 deletions

View File

@@ -3,30 +3,42 @@ from tkinter import ttk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import asyncio
from .filter import *
from .gui.device import Device
from .gui.slider import Slider
class FilterDevApp(tk.Tk):
def __init__(self, loop: asyncio.EventLoop):
super().__init__()
self.loop = loop
self.protocol("WM_DELETE_WINDOW", self.close)
self.tasks = []
self.tasks.append(loop.create_task(self.updater(1./2)))
self.tasks.append(loop.create_task(self.update_plot(1./20)))
self.tasks.append(loop.create_task(self.read_values(1./100)))
class FilterDevApp:
def __init__(self, root):
self.filter = None
self.root = root
self.root.title("JannTers Filter Evaluation Tool")
self.title("JannTers Filter Evaluation Tool")
# Create a frame for the plot and sliders
self.frame = tk.Frame(self.root)
self.frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
self.frame = tk.Frame(self)
self.frame.pack(side=tk.LEFT, fill=tk.BOTH)
# Create a figure for plotting
self.fig, self.ax = plt.subplots()
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH)
# Create a frame for sliders
self.toolbar = tk.Frame(self.root)
self.toolbar = tk.Frame(self, width=200, padx=10)
self.toolbar.pack(side=tk.RIGHT, fill=tk.Y)
# Device Settings
self.connect_button = ttk.Button(self.toolbar, text="Connect", command=self.connect_disconnect)
self.connect_button.pack(pady=10)
self.device_label = ttk.Label(self.toolbar, text="Device Name:")
self.device_label.pack(pady=10)
self.device_name = ttk.Entry(self.toolbar)
@@ -35,9 +47,6 @@ class FilterDevApp:
self.device = Device(self.device_name)
self.connect_button = ttk.Button(self.toolbar, text="Connect Device", command=self.device.connect)
self.connect_button.pack(pady=10)
# Filter Settings
self.filter_type_label = ttk.Label(self.toolbar, text="Filter:")
self.filter_type_label.pack(pady=10)
@@ -48,14 +57,13 @@ class FilterDevApp:
self.change_filter.pack(pady=10)
# Objects
self.filter = MovAvg(self.device, self.toolbar, self.update_plot)
self.filter = MovAvg(self.device, self.toolbar, lambda: None)
self.filter.pack()
# Initial plot
self.update_plot()
def update_plot(self, *args):
async def update_plot(self, interval):
while await asyncio.sleep(interval, True):
if self.filter is None:
return
continue
# Clear the current plot
self.ax.clear()
@@ -85,7 +93,45 @@ class FilterDevApp:
self.update_plot()
def connect_disconnect(self):
if self.device.is_connected:
self.device_label.pack(pady=10)
self.device_name.pack(pady=10)
self.connect_button.config(text="Connect")
self.connect_button.pack(pady=10)
self.device.disconnect()
else:
task = self.loop.create_task(self.device.connect())
task.add_done_callback(self.connected)
def connected(self, *args):
if self.device.is_connected:
self.device_label.pack_forget()
self.device_name.pack_forget()
self.connect_button.config(text="Disconnect")
self.filter.pack()
async def read_values(self, interval):
await self.device.read_values(interval)
async def updater(self, interval):
while await asyncio.sleep(interval, True):
self.update()
def close(self):
for task in self.tasks:
task.cancel()
self.loop.stop()
self.destroy()
if __name__ == "__main__":
root = tk.Tk()
app = FilterDevApp(root)
root.mainloop()
loop = asyncio.new_event_loop()
app = FilterDevApp(loop)
loop.run_forever()
loop.close()

View File

@@ -6,8 +6,13 @@ import pandas as pd
from argparse import ArgumentParser
from tqdm.auto import tqdm
from config import MILLIS_UUID, WEIGHT_UUID
READING_TIME = 30
async def read_ble(reading_time=READING_TIME):
device = await BleakScanner.find_device_by_name("Smaage")
assert device is not None, "No device found"
timestamps = []
raw_weights = []
@@ -45,3 +50,11 @@ async def read_ble(reading_time=READING_TIME):
print(df['weights'].describe())
plt.plot(timestamps, raw_weights)
plt.show()
if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument('-t', default=READING_TIME, type=int, help="reading time in sec")
args = parser.parse_args()
asyncio.run(read_ble(args.t))

View File

@@ -34,3 +34,11 @@ class Filter:
def filter(self, df: pd.DataFrame) -> pd.Series:
raise NotImplementedError()
def pack(self):
for k, v in self.param_map.items():
v.pack()
def pack_forget(self):
for k, v in self.param_map.items():
v.pack_forget()

View File

@@ -1,6 +1,7 @@
from bleak import BleakClient, BleakScanner
import pandas as pd
from tkinter.ttk import Entry
import asyncio
from ..config import MILLIS_UUID, WEIGHT_UUID
@@ -26,11 +27,16 @@ class Device:
async def connect(self):
self.device = await BleakScanner.find_device_by_name(self.device_name.get())
assert self.device is not None, "No Device found!"
return self.device is not None
async def read_values(self):
assert self.is_connected, "Not connected"
def disconnect(self):
self.device = None
async def read_values(self, interval):
while await asyncio.sleep(interval, True):
if self.is_connected:
async with BleakClient(self.device.address) as client:
while await asyncio.sleep(interval, True):
millis = await client.read_gatt_char(MILLIS_UUID)
millis = int.from_bytes(millis, byteorder='little') # Adjust based on your data format
weight = await client.read_gatt_char(WEIGHT_UUID)
@@ -38,3 +44,11 @@ class Device:
self.timestamps.append(millis)
self.weights.append(weight)
if not self.is_connected:
break
def clear_data(self):
self.timestamps = []
self.weights = []

View File

@@ -9,15 +9,10 @@ class Slider:
command):
self.command = command
self.frame = ttk.Frame(parent)
self.frame.pack(pady=10)
self.label = ttk.Label(parent, text=f"{label_text}: {int(initial_value)}")
self.label = ttk.Label(self.frame, text=f"{label_text}: {int(initial_value)}")
self.label.pack()
self.slider = ttk.Scale(self.frame, from_=from_, to=to, orient='horizontal', command=self.update)
self.slider = ttk.Scale(parent, from_=from_, to=to, orient='horizontal', command=self.update)
self.slider.set(initial_value)
self.slider.pack()
def update(self, event=None):
value = self.slider.get()
@@ -26,3 +21,11 @@ class Slider:
def get_value(self):
return self.slider.get()
def pack(self, **kwargs):
self.label.pack(**kwargs)
self.slider.pack(**kwargs)
def pack_forget(self):
self.label.pack_forget()
self.slider.pack_forget()