From 5653972b8d0cc964b95f7fccd9de241fbcee012b Mon Sep 17 00:00:00 2001 From: Martin Quarda Date: Thu, 27 Mar 2025 14:37:40 +0100 Subject: [PATCH] creation of registrace.py application, upload time to website in StopWatch --- SW/PC/Stopwatch/config.json | 10 +++ SW/PC/Stopwatch/main.py | 124 +++++++++++++++++++------------ SW/PC/Stopwatch/registrace.py | 134 ++++++++++++++++++++++++++++++++++ SW/PC/Stopwatch/registrace.ui | 71 ++++++++++++++++++ 4 files changed, 294 insertions(+), 45 deletions(-) create mode 100644 SW/PC/Stopwatch/config.json create mode 100644 SW/PC/Stopwatch/registrace.py create mode 100644 SW/PC/Stopwatch/registrace.ui diff --git a/SW/PC/Stopwatch/config.json b/SW/PC/Stopwatch/config.json new file mode 100644 index 0000000..dfe962a --- /dev/null +++ b/SW/PC/Stopwatch/config.json @@ -0,0 +1,10 @@ +{ + "url": "https://beta.alkator.cz/api/station/register", + "station_id": "1", + "login_url": "https://beta.alkator.cz/api/login", + "racers_url": "https://beta.alkator.cz/api/racers", + "card_register": "https://beta.alkator.cz/api/card/register", + "card_unregister": "https://beta.alkator.cz/api/card/card_unregister", + "login": "station_register@alkator.cz", + "password": "password_heslo" +} \ No newline at end of file diff --git a/SW/PC/Stopwatch/main.py b/SW/PC/Stopwatch/main.py index 69ef23d..f213418 100644 --- a/SW/PC/Stopwatch/main.py +++ b/SW/PC/Stopwatch/main.py @@ -1,6 +1,8 @@ import gi import threading import time +import datetime +import collections import usb.core import usb.util import requests @@ -9,12 +11,6 @@ import json gi.require_version('Gtk', '4.0') from gi.repository import Gtk, Gio, Gdk -DEBUG = False - -if DEBUG == True: - index = 2 -else: - index = 1 activeCards = [] TIME = 600 @@ -24,8 +20,56 @@ USB_TIMEOUT = 5 # Timeout in ms USB_VENDOR = 0xffff # Vendor-ID: USB_PRODUCT = 0x0035 # Product-ID -with open('people.json', 'r') as f: - db = json.load(f) +db = {} + +queue_to_send = [] + +with open('config.json', 'r') as f: + config = json.load(f) + +session = requests.Session() +session.post(config['login_url'], {'email':config['login'], 'password': config['password']}) + +def refreshDb(): + global db + resp = session.get(config['racers_url']) + if resp.status_code == 200: + json = resp.json() + db = {} + for racer in json: + if racer["card_id"]: + db[racer["card_id"]] = racer + + +def refreshDbEvery3mins(): + while True: + refreshDb() + time.sleep(3 * 60) + + +Thread(target=refreshDbEvery3mins).start() + + +def sendQueueToSend(): + global queue_to_send + while True: + if len(queue_to_send) > 0: + to_send = queue_to_send.pop() + + response = session.post(config['url'], + to_send, 'application/json' + ) + if response.status_code != 200: + if response.status_code == 400: + continue + queue_to_send.append(to_send) #try again later + time.sleep(1) + else: + time.sleep(1) + + +Thread(target=sendQueueToSend).start() + class UsbCardReader(): def __init__(self, **kargs): @@ -59,17 +103,17 @@ class UsbCardReader(): receivedNumber = 10 * receivedNumber + receivedDigit if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )): - try: - with open('people.json', 'r') as f: - db = json.load(f) - for i in db: - if db[i] == receivedNumber: - if i not in activeCards: - activeCards.append(i) - win.arb(i) - else: - print("Card is active now") - except Exception as e: print(e) + if receivedNumber not in db: + refreshDb() + if receivedNumber in db: + if receivedNumber not in activeCards: + activeCards.append(receivedNumber) + win.arb(db[receivedNumber]) + print('Card is active now') + else: + print('Card is already active') + else: + print(f'Card {receivedNumber} not found in db') receivedNumber = 0 except KeyboardInterrupt: @@ -80,9 +124,9 @@ class UsbCardReader(): time.sleep(0.001) class GridRow(): - def __init__(self, parent, runner, index): - self.id = runner - self.index = index + def __init__(self, parent, racer, index): + global queue_to_send + self.id = racer['starting_number'] self.parent = parent self.grid = Gtk.Grid() @@ -92,7 +136,7 @@ class GridRow(): else: self.grid.set_name("darkgrid") - self.runid = Gtk.Label(label=str(runner), name="gridlabel") + self.runid = Gtk.Label(label=str(racer["starting_number"]), name="gridlabel") self.runid.set_justify(2) self.runid.set_width_chars(10) @@ -107,6 +151,12 @@ class GridRow(): countdown=threading.Thread(target=self.updateTime) countdown.start() + queue_to_send.append({ + 'card_id': racer['card_id'], + 'station_id': config['station_id'], + 'time': datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S.%f') + }) + def printIndex(self, button): print(self.index) @@ -138,12 +188,6 @@ class GridWindow(Gtk.ApplicationWindow): css_provider.load_from_file(Gio.File.new_for_path("style.css")) Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) - button1 = Gtk.Button(label='addrow') - button2 = Gtk.Button(label='rmrow') - - button1.connect("clicked", self.arb) - button2.connect("clicked", self.rrb) - runlabel = Gtk.Label(label="ID", name="gridlabel") runlabel.set_justify(2) cntlabel = Gtk.Label(label="Countdown", name="gridlabel") @@ -152,24 +196,15 @@ class GridWindow(Gtk.ApplicationWindow): self.runners = [] self.grid = Gtk.Grid() - if DEBUG == True: - self.grid.attach(button1, 0, 0, 1, 1) - self.grid.attach(button2, 1, 0, 2, 1) - self.grid.attach(runlabel, 0, 1, 1, 1) - self.grid.attach(cntlabel, 1, 1, 2, 1) - else: - self.grid.attach(runlabel, 0, 0, 1, 1) - self.grid.attach(cntlabel, 1, 0, 2, 1) + self.grid.attach(runlabel, 0, 0, 1, 1) + self.grid.attach(cntlabel, 1, 0, 2, 1) self.set_child(self.grid) - def arb(self, personId): - global index - self.runners.append(GridRow(self, personId, index)) - index += 1 + def arb(self, racer): + self.runners.append(GridRow(self, racer, len(activeCards))) def rrb(self, button): - global index self.remRow() def addRow(self, runner, index): @@ -180,10 +215,9 @@ class GridWindow(Gtk.ApplicationWindow): self.grid.attach(runb, 1, index, 1, 1) def remRow(self): - global index, activeCards - if index > 1: + global activeCards + if len(activeCards) > 0: self.grid.remove_row(1) - index -= 1 del activeCards[0] diff --git a/SW/PC/Stopwatch/registrace.py b/SW/PC/Stopwatch/registrace.py new file mode 100644 index 0000000..948f6a7 --- /dev/null +++ b/SW/PC/Stopwatch/registrace.py @@ -0,0 +1,134 @@ +import sys +import datetime +import requests +import json +import usb.core +import usb.util +from PyQt6 import QtWidgets, uic, QtGui + +app = QtWidgets.QApplication(sys.argv) + +TIME = 600 + +USB_IF = 0 # Interface +USB_TIMEOUT = 5 # Timeout in ms +USB_VENDOR = 0xffff # Vendor-ID: +USB_PRODUCT = 0x0035 # Product-ID + +with open('config.json', 'r') as f: + config = json.load(f) + +session = requests.Session() +session.post(config['login_url'], {'email':config['login'], 'password': config['password']}) + + +last_card = 1111 +last_time = datetime.datetime.now() + + +response = session.get(config['racers_url']) + +racers = response.json() + + +def register_racer(): + card_id = last_card + index = window.racers.currentIndex() + racer_id = int(index.data().split(' ')[-1]) + try: + starting_number = int(window.starting_number.text()) + except Exception: + raise + + response = session.post(config['card_register'], json={'racer_id': racer_id, 'starting_number': starting_number, 'card_id': last_card}) + if response.status_code != 200: + raise Exception(response.status_code, response.content) + + racer = list(filter(lambda x: x['racer_id'] == racer_id, racers))[0] + racer['card_id'] = card_id + racer['starting_number'] = starting_number + updateRacers() + + +def unregister_racer(): + card_id = last_card + time = last_time + + response = session.post(config['url'], json={'card_id': card_id, 'time': time.strftime('%d.%m.%Y %H:%M:%S.%f'), 'station_id': config['station_id']}) + + + + +window = uic.loadUi("registrace.ui") +window.register_racer.clicked.connect(register_racer) +window.unregister_racer.clicked.connect(unregister_racer) +window.show() + + +model = QtGui.QStandardItemModel() +window.racers.setModel(model) + +def updateRacers(): + model.clear() + for racer in racers: + if racer['starting_number'] or racer['card_id']: + continue + item = QtGui.QStandardItem(f"{racer['last_name']} {racer['first_name']} {racer['date_of_birth']} {racer['racer_id']}") + model.appendRow(item) + + +updateRacers() + + +def updateLastCard(card_id): + window.lastCard.setText(str(card_id)) + + +class UsbCardReader(): + def __init__(self, **kargs): + # Find the HID device by vendor/product ID + self.dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT) + # Get and store the endpoint + self.endpoint = self.dev[0][(0,0)][0] + if self.dev.is_kernel_driver_active(USB_IF) is True: + self.dev.detach_kernel_driver(USB_IF) + # Claim the device + usb.util.claim_interface(self.dev, USB_IF) + self.receivedNumber = 0 + + cardread=threading.Thread(target=self.read) + cardread.start() + + def read(self): + global last_card, last_time + + print("Waiting for card") + receivedNumber = 0 + + while True: + control = None + try: + control = self.dev.read(self.endpoint.bEndpointAddress, self.endpoint.wMaxPacketSize, USB_TIMEOUT) + if (control[2] != 40) & (control[2] != 0): + receivedDigit = control[2] - 29 + if receivedDigit == 10: + receivedDigit = 0 + receivedNumber = 10 * receivedNumber + receivedDigit + + if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )): + updateLastCard(receivedNumber) + if last_card != receivedNumber: + last_time = datetime.datetime.now() + last_card = receivedNumber + receivedNumber = 0 + + except KeyboardInterrupt: + exit() + except: + pass + + time.sleep(0.001) + +UsbCardReader() + +app.exec() \ No newline at end of file diff --git a/SW/PC/Stopwatch/registrace.ui b/SW/PC/Stopwatch/registrace.ui new file mode 100644 index 0000000..190b48a --- /dev/null +++ b/SW/PC/Stopwatch/registrace.ui @@ -0,0 +1,71 @@ + + + Frame + + + + 0 + 0 + 315 + 289 + + + + Registrace závodníků + + + + + + + + + Registrovat + + + + + + + Dokončit + + + + + + + + + + startovní číslo + + + + + + + číslo karty + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + +