Python Forum
add svg to 2 thread program and display tabel in GUI
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
add svg to 2 thread program and display tabel in GUI
#1
Hello,

at the moment my program show an GUI in a thread and in the other thread i get some data via BLE in an array. Now i want to display the data in my GUI. First i want to safe them into an svg, then display. Next step is to send it into influx DB oder mySQL. Can anyone help me to creat the svg and display them in my tkinter windows? I need first to creat the svg in my BLE thread and then writ into to svg above my print from the data? Right?

Here is my code:

import asyncio
import threading
from tkinter import *
from bleak import BleakClient
import numpy
import svgwrite



address = "CC:50:E3:9C:15:02"
MODEL_NBR_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8"


class BLEThread(threading.Thread):
    def __init__(self, address):
        threading.Thread.__init__(self)
        self.address = address

    async def handle_uuid1_notify(self, sender, data):
        spo2_value = numpy.frombuffer(data, dtype=numpy.uint32)
        print("Red: {0}".format(spo2_value))

    async def handle_uuid2_notify(self, sender, data):
        ir_value = numpy.frombuffer(data, dtype=numpy.uint32)
        print("IR: {0}".format(ir_value))

    async def read_data(self):
        UUID1 = "beb5483e-36e1-4688-b7f5-ea07361b26a8"
        UUID2 = "beb5483e-36e1-4688-b7f5-ea07361b26a9"
        async with BleakClient(self.address) as client:
            await client.start_notify(UUID1, self.handle_uuid1_notify)
            await client.start_notify(UUID2, self.handle_uuid2_notify)
            while True:
                await asyncio.sleep(1)

    def run(self):
        asyncio.run(self.read_data())


class TkinterThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        tkFenster = Tk()
        tkFenster.title('BLE MAX30102')
        tkFenster.mainloop()


def start_threads():
    ble_thread = BLEThread(address)
    tkinter_thread = TkinterThread()

    ble_thread.start()
    tkinter_thread.start()


if __name__ == '__main__':
    start_threads()
Reply
#2
I think excel is better?

At the moment this is my code, i save in in txt, but not right formated:

import asyncio
import threading
from tkinter import *
from bleak import BleakClient
import numpy
from prettytable import PrettyTable
import datetime

address = "CC:50:E3:9C:15:02"
MODEL_NBR_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8"

table = PrettyTable()
table.field_names = ["Wert 1", "Wert 2"]


def print_table():
    print(table)

class BLEThread(threading.Thread):
    def __init__(self, address):
        threading.Thread.__init__(self)
        self.address = address



    async def handle_uuid1_notify(self, sender, data):
        spo2_values = numpy.frombuffer(data, dtype=numpy.uint32)
        print("Red: {0}".format(spo2_values))
        for spo2_value in spo2_values:
            table.add_row([spo2_value, ""])
        print_table()

    async def handle_uuid2_notify(self, sender, data):
        ir_values = numpy.frombuffer(data, dtype=numpy.uint32)
        print("IR: {0}".format(ir_values))
        for ir_value in ir_values:
            table.add_row(["", ir_value])
        print_table()

    async def read_data(self):
        UUID1 = "beb5483e-36e1-4688-b7f5-ea07361b26a8"
        UUID2 = "beb5483e-36e1-4688-b7f5-ea07361b26a9"
        async with BleakClient(self.address) as client:
            await client.start_notify(UUID1, self.handle_uuid1_notify)
            await client.start_notify(UUID2, self.handle_uuid2_notify)
            while True:
                await asyncio.sleep(1)

    def run(self):
        asyncio.run(self.read_data())


class TkinterThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        tkFenster = Tk()
        tkFenster.title('BLE MAX30102')
        tkFenster.mainloop()

def save_table():
    now = datetime.datetime.now()
    filename = "table_{}.txt".format(now.strftime("%Y-%m-%d_%H-%M-%S"))
    with open(filename, 'w') as file:
        file.write(str(table))

def start_threads():
    ble_thread = BLEThread(address)
    tkinter_thread = TkinterThread()

    ble_thread.start()
    tkinter_thread.start()
    threading.Timer(60.0, save_table).start()

if __name__ == '__main__':
    start_threads()
I get this:

+--------+--------+
| Wert 1 | Wert 2 |
+--------+--------+
| 555 | |
| 554 | |
| 558 | |
| 557 | |
| 556 | |
| 553 | |
| 553 | |
| 548 | |
| 544 | |
| 556 | |
| 560 | |
| 554 | |
| | 3528 |
| | 3518 |
| | 3523 |
| | 3524 |
| | 3529 |
| | 3528 |
| | 3531 |
| | 3537 |
| | 3528 |
| | 3531 |
| | 3531 |
| | 3524 |
| | 3524 |
| | 3526 |
| | 3531 |
| | 3531 |
| | 3524 |
| | 3531 |
| | 3527 |
| | 3525 |

But i want this

+--------+--------+
| Wert 1 | Wert 2 |
+--------+--------+
| 555 | 3324 |
| 554 | 234 |
| 558 | 324 |
Reply
#3
So no more tkinter? If you want to write a spreadsheet I would use pandas. First verify that you are getting values.
import asyncio
import threading
from tkinter import *
from bleak import BleakClient
import numpy as np
import pandas as pd

 
class BLEThread(threading.Thread):
    def __init__(self, address):
        threading.Thread.__init__(self)
        self.address = address
        self.table = pd.DataFrame()
 
    async def update_table(self, column, data):
        print(f"update_table({column})")
        self.table[column] = np.frombuffer(data, dtype=np.uint32)
        print(self.table)

    async def read_data(self):
        async with BleakClient(self.address) as client:
            client.start_notify(
                "beb5483e-36e1-4688-b7f5-ea07361b26a8",
                lambda uuid, data: self.update_table("Wert 1", data)
            )
            client.start_notify(
                "beb5483e-36e1-4688-b7f5-ea07361b26a9",
                lambda uuid, data: self.update_table("Wert 2", data)
            )
            while True:
                await asyncio.sleep(1)
 
    def run(self):
        asyncio.run(self.read_data())
 
 
def start_threads(address):
    ble_thread = BLEThread(address)
    ble_thread.start()
 
if __name__ == '__main__':
    start_threads("CC:50:E3:9C:15:02")
Nietzsche likes this post
Reply
#4
(May-03-2023, 03:55 PM)deanhystad Wrote: So no more tkinter? If you want to write a spreadsheet I would use pandas. First verify that you are getting values.

Hi! First i want to safe my data in a file, then i want to dispay them in tkinter, so step by step. :)

Thanks for the tipp with pandas, i have installed them and implement them into my code:

import pandas as pd

import asyncio
import threading
from tkinter import *
from bleak import BleakClient
import numpy
from prettytable import PrettyTable
import openpyxl
from datetime import datetime


address = "CC:50:E3:9C:15:02"
MODEL_NBR_UUID = "beb5483e-36e1-4688-b7f5-ea07361b26a8"

table = PrettyTable()
table.field_names = ["Wert 1", "Wert 2"]

wb = openpyxl.Workbook() # Workbook-Objekt erzeugen
ws = wb.active #Arbeitsblatt auswählen

now = datetime.now()
dt_string = now.strftime("%d-%m-%Y_%H-%M-%S") # Variable mit Datum und Uhrzeit erzeugen

filename = f"{dt_string}.xlsx" #Datei mit Name und Datum erzeugen

ws["A1"] = "Red"
ws["B1"] = "IR" #Überschriften hinzufügen

last_red_row = 1  # Die erste Zeile ist bereits mit Überschriften belegt
last_ir_row = 1

spo2_list = []
ir_list = []






def print_table():
    print(table)

class BLEThread(threading.Thread):
    def __init__(self, address):
        threading.Thread.__init__(self)
        self.address = address


    async def handle_uuid1_notify(self, sender, data):
        spo2_values = numpy.frombuffer(data, dtype=numpy.uint32)
        print("Red: {0}".format(spo2_values))
        for spo2_value in spo2_values:
            table.add_row([spo2_value, ""])
            ws.append([spo2_value, ""])  # Zeile hinzufügen
            spo2_list.append(spo2_value)  # füge den empfangenen Wert der Liste hinzu

        # wenn alle Werte empfangen wurden, erstelle einen Pandas DataFrame und gib ihn aus
        if len(spo2_list) == 100:
            pythonDaten = pd.DataFrame(spo2_list)
            print(pythonDaten.head())
            wb.save(filename)


    async def handle_uuid2_notify(self, sender, data):

        ir_values = numpy.frombuffer(data, dtype=numpy.uint32)
        print("IR: {0}".format(ir_values))
        for ir_value in ir_values:
            if ir_value:
                table.add_row(["", ir_value])
                ws.append(["", ir_value])  # Zeile hinzufügen
                ir_list.append(ir_value)  # füge den empfangenen Wert der Liste hinzu


        # wenn alle Werte empfangen wurden, erstelle einen Pandas DataFrame und gib ihn aus
        if len(ir_list) == 100:
            pythonDaten2 = pd.DataFrame(ir_list)
            print(pythonDaten2.head())
            wb.save(filename)

    async def read_data(self):
        UUID1 = "beb5483e-36e1-4688-b7f5-ea07361b26a8"
        UUID2 = "beb5483e-36e1-4688-b7f5-ea07361b26a9"
        async with BleakClient(self.address) as client:
            await client.start_notify(UUID1, self.handle_uuid1_notify)
            await client.start_notify(UUID2, self.handle_uuid2_notify)
            while True:
                await asyncio.sleep(1)

    def run(self):
        asyncio.run(self.read_data())


class TkinterThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        tkFenster = Tk()
        tkFenster.title('BLE MAX30102')
        tkFenster.mainloop()


def start_threads():
    ble_thread = BLEThread(address)
    tkinter_thread = TkinterThread()

    ble_thread.start()
    tkinter_thread.start()


if __name__ == '__main__':
    start_threads()

wb.save(filename)
But at the moment i also need to synchonizat them, the data are not side by side.
Reply
#5
Get rid of the pretty table. It doesn't have the right temperament for adding columns piecemeal and is causing most of your problems. Use pandas to display the data. It is pretty enough for your purposes. Eventually you plan to display the data in a tkinter table, right?

You only need one handle function like I showed in my last example. The lambda expression used to bind the handler will pass the column name associated with the data. When you get data from "beb5483e-36e1-4688-b7f5-ea07361b26a8" it will place it in the "Wert 1" column, and data from "beb5483e-36e1-4688-b7f5-ea07361b26a9" will be placed in the "Wert 2" column. Whenever you look at the table it will have the most recent values for each column.

Do not use openpyxl to write an excel spreadsheet. Use pandas. It has a function for directly writing a dataframe to an excel spreadsheet.

Currently you are doing nothing with tkinter. Leave that out until you have the other parts working. I would start by getting the data into a DataFrame and printing. From there it is simple to write the DataFrame to a spreadsheet. When that is all working it will be easier to write the tkinter app. Since pandas and tkinter are so widely used I'm sure someone has documented a way to connect a dataframe to the data model for a tkinter table.
Reply
#6
(May-05-2023, 04:03 PM)deanhystad Wrote: Get rid of the pretty table. It doesn't have the right temperament for adding columns piecemeal and is causing most of your problems. Use pandas to display the data.
I followed your tip and got it now, thanks!
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to display <IPython.core.display.HTML object>? pythopen 3 45,918 May-06-2023, 08:14 AM
Last Post: pramod08728
  Writing on an lcd display gives problems to the program Idontknowany 1 1,401 Nov-15-2021, 10:46 PM
Last Post: Larz60+
Information Unable to display joystick's value from Python onto display box MelfoyGray 2 2,226 Nov-11-2020, 02:23 AM
Last Post: MelfoyGray
  Error SQLite objects created in a thread can only be used in that same thread. binhduonggttn 3 15,560 Jan-31-2020, 11:08 AM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020