2 Commits

Author SHA1 Message Date
306827bcc3 added people.json, results and ordering script 2025-05-31 19:18:51 +02:00
279814a30e fixed GTK hanging 2025-04-27 21:16:41 +02:00
18 changed files with 520 additions and 519 deletions

View File

@@ -16,7 +16,7 @@ results = {}
with open(FILE,'r') as f:
file_content = f.read()
data_dict = json.loads(file_content)
for id in data_dict:
laps = int(data_dict[id]['laps'])
time = 0
@@ -26,7 +26,12 @@ for id in data_dict:
print(data_dict[id]['name'],time)
data_dict[id]['total_time'] = time
results[data_dict[id]['name']] = time
print(results)
dict(sorted(results.items(), key=lambda item: item[0]))
print(results)

View File

@@ -1,7 +0,0 @@
{
"station_id": 2,
"host": "https://beta.alkator.cz",
"login": "station_register@alkator.cz",
"password": "password_heslo",
"countdown_seconds": 60
}

View File

@@ -1 +0,0 @@
[]

View File

@@ -1,136 +1,115 @@
import gi
import threading
import time
import datetime
import usb.core
import usb.util
import requests
import json
gi.require_version('Gtk', '4.0')
from queue import Queue
from gi.repository import Gtk, Gio, Gdk
from requests.adapters import HTTPAdapter, Retry
from usbcardreader import UsbCardReader
from gi.repository import Gtk, Gio, Gdk, GLib
DEBUG = False
with open('config.json', 'r') as f:
config = json.load(f)
if DEBUG == True:
index = 2
else:
index = 1
activeCards = []
TIME = 60
activeCards = []
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in ms
USB_VENDOR = 0xffff # Vendor-ID:
USB_PRODUCT = 0x0035 # Product-ID
TIME = config['countdown_seconds']
db = {}
queue_to_send = []
session = requests.Session()
retries = Retry(total=10,
backoff_factor=1,
status_forcelist=[ 500, 502, 503, 504 ])
session.mount('https://', HTTPAdapter(max_retries=retries))
session.post(config['host'] + '/api/login', {'email':config['login'], 'password': config['password']})
def refreshDb():
global db
resp = session.get(config['host'] + '/api/racers')
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)
threading.Thread(target=refreshDbEvery3mins).start()
log = []
with open('log.json', 'r') as f:
log = json.loads(f.read())
queue = Queue()
def worker():
while True:
item = queue.get()
log.append(item)
with open('log.json', 'w') as f:
f.write(json.dumps(log))
response = session.post(item['url'], json=item['json'])
print(item, response)
threading.Thread(target=worker).start()
def callbackOnCard(card_id):
global win, activeCards, db
if card_id not in db:
refreshDb()
if card_id in db:
if card_id not in activeCards:
activeCards.append(card_id)
win.arb(db[card_id])
print('Card is active now')
else:
print('Card is already active')
else:
print(f'Card {card_id} not found in db')
with open('people.json', 'r') as f:
db = json.load(f)
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 win, activeCards, db
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 )):
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)
GLib.idle_add(win.arb, i)
else:
print("Card is active now")
except Exception as e: print(e)
receivedNumber = 0
except KeyboardInterrupt:
exit()
except:
pass
time.sleep(0.001)
class GridRow():
def __init__(self, parent, racer, index):
global queue_to_send
self.id = racer['starting_number']
def __init__(self, parent, runner, index):
self.id = runner
self.index = index
self.parent = parent
self.grid = Gtk.Grid()
if index % 2 == 0:
self.grid.set_name("lightgrid")
else:
self.grid.set_name("darkgrid")
self.runid = Gtk.Label(label=str(racer["starting_number"]), name="gridlabel")
self.runid = Gtk.Label(label=str(runner), name="gridlabel")
self.runid.set_justify(2)
self.runid.set_width_chars(10)
self.runb = Gtk.Label(label='00:00', name="gridlabel")
self.runb.set_hexpand(1)
self.grid.attach(self.runid, 0, 0, 1, 1)
self.grid.attach(self.runb, 1, 0, 1, 1)
parent.grid.attach(self.grid, 0, index, 2, 1)
countdown=threading.Thread(target=self.updateTime)
countdown.start()
queue.put({'url': config['host'] + '/api/station/register', 'json': {
'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)
def updateTime(self):
t = TIME
while t >= -10:
@@ -140,55 +119,72 @@ class GridRow():
else:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
self.runb.set_label(timer)
time.sleep(1)
GLib.idle_add(self.runb.set_label, timer)
time.sleep(1)
t -= 1
if t == 10:
if self.grid.get_name() == "lightgrid":
self.grid.set_name("lredgrid")
GLib.idle_add(self.grid.set_name, "lredgrid")
else:
self.grid.set_name("dredgrid")
GridWindow.remRow(self.parent)
GLib.idle_add(self.grid.set_name, "dredgrid")
GLib.idle_add(GridWindow.remRow, self.parent)
class GridWindow(Gtk.ApplicationWindow):
def __init__(self, **kargs):
super().__init__(**kargs, title='Alkator Clock')
css_provider = Gtk.CssProvider()
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)
self.set_default_size(640, 480)
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")
cntlabel.set_justify(2)
self.runners = []
self.grid = Gtk.Grid()
self.grid.attach(runlabel, 0, 0, 1, 1)
self.grid.attach(cntlabel, 1, 0, 2, 1)
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.set_child(self.grid)
def arb(self, racer):
self.runners.append(GridRow(self, racer, len(activeCards)))
def arb(self, personId):
global index
self.runners.append(GridRow(self, personId, index))
index += 1
def rrb(self, button):
global index
self.remRow()
def addRow(self, runner, index):
runid = Gtk.Label(label=str(runner))
runb = Gtk.Button(label='time_placeholder')
self.grid.attach(runid, 0, index, 1, 1)
self.grid.attach(runb, 1, index, 1, 1)
def remRow(self):
global activeCards
if len(activeCards) > 0:
global index, activeCards
if index > 1:
self.grid.remove_row(1)
index -= 1
del activeCards[0]
@@ -198,7 +194,7 @@ def on_activate(app):
win = GridWindow(application=app)
win.present()
UsbCardReader(callbackOnCard)
UsbCardReader()
app = Gtk.Application(application_id='com.example.App')
app.connect('activate', on_activate)

23
SW/PC/Stopwatch/order.py Normal file
View File

@@ -0,0 +1,23 @@
import operator
import json
db=""
res={}
with open('times.json', 'r') as f:
db = json.load(f)
for i in db:
try:
res[i] = db[i]["duration"]
print(i, db[i]["duration"])
except:
print(i)
pass
#print(res)
order = dict(sorted(res.items(), key=lambda item: item[1]))
with open("results.json", 'a') as f:
f.write(json.dumps(order, indent = 4))

View File

@@ -1,4 +1,102 @@
{
"1": 3619716179,
"2": 3620062547
}
"1": 1114418469,
"2": 1111554085,
"3": 1112605381,
"4": 1362080126,
"5": 1632101230,
"6": 1114533941,
"7": 1364901054,
"8": 1364587710,
"9": 1364867822,
"10": 1364554558,
"11": 1364968750,
"12": 1111614357,
"13": 1362569198,
"14": 1364867662,
"15": 1112618821,
"16": 1364967150,
"17": 1364592718,
"18": 1364487310,
"19": 458336708,
"20": 1111590293,
"21": 1114448773,
"22": 1364550814,
"23": 1112421509,
"24": 1364529422,
"25": 1364916590,
"26": 455988804,
"27": 1631963022,
"28": 1114508533,
"29": 1364590606,
"30": 1364796894,
"31": 1112489029,
"32": 1114588261,
"33": 1111733589,
"34": 1112469509,
"35": 1632521678,
"36": 1631957710,
"37": 1111682853,
"38": 1111882197,
"39": 1631960974,
"40": 1362260606,
"41": 1364521806,
"42": 1364489406,
"43": 1361969902,
"44": 1364581838,
"45": 1364520526,
"46": 1361806574,
"47": 1364581310,
"48": 1364551150,
"49": 1364916158,
"50": 1364529662,
"51": 1632026766,
"52": 1364588798,
"53": 1631955550,
"54": 1631972606,
"55": 1364797086,
"56": 1364627198,
"57": 1364556446,
"58": 1632070414,
"59": 1631951758,
"60": 1364794654,
"61": 1632101166,
"62": 1361810574,
"63": 1114573589,
"64": 1361967886,
"65": 1632544222,
"66": 1111582085,
"67": 1362569438,
"68": 1364593198,
"69": 1364761406,
"70": 1631927918,
"71": 1364544414,
"72": 1362264958,
"73": 1364767006,
"74": 1364590110,
"75": 1362082334,
"76": 1364799166,
"77": 1632028398,
"78": 1361970078,
"79": 1364485118,
"80": 1364490846,
"81": 1632150846,
"82": 1362569342,
"83": 1362599998,
"84": 1632523854,
"85": 1364765134,
"86": 1631952062,
"87": 1364559822,
"88": 1364783854,
"89": 1362081950,
"90": 1111644021,
"91": 1631959326,
"92": 1364901422,
"93": 1632100830,
"94": 1111707429,
"95": 1632026702,
"96": 1362569022,
"97": 1114560181,
"98": 1364588510,
"99": 1364785486,
"100": 1361969950
}

View File

@@ -1,184 +0,0 @@
import sys
import datetime
import requests
import threading
import json
from PyQt6 import QtWidgets, uic, QtGui, QtCore
from PyQt6.QtCore import pyqtSignal as Signal, pyqtSlot as Slot
from queue import Queue
from requests.adapters import HTTPAdapter, Retry
from usbcardreader import UsbCardReader
app = QtWidgets.QApplication(sys.argv)
with open('config.json', 'r') as f:
config = json.load(f)
session = requests.Session()
session.post(config['host'] + '/api/login', {'email':config['login'], 'password': config['password']})
retries = Retry(total=10,
backoff_factor=1,
status_forcelist=[ 500, 502, 503, 504 ],)
session.mount('https://', HTTPAdapter(max_retries=retries))
last_card = 0
last_time = datetime.datetime.now()
racers = []
log = []
with open('log.json', 'r') as f:
log = json.loads(f.read())
queue = Queue()
class Worker(QtCore.QThread):
returned_state = Signal(str)
def __init__(self):
super().__init__()
self.returned_state.connect(self.handle_returned_state)
self.worker_thread = threading.Thread(target=self.worker)
self.worker_thread.start()
def worker(self):
while True:
item = queue.get()
log.append({
'url': item['url'],
'json': item['json'],
})
with open('log.json', 'w') as f:
f.write(json.dumps(log))
response = session.post(item['url'], json=item['json'])
if response.status_code == 200:
if item.get('on_success'):
item['on_success']()
if item.get('message'):
self.returned_state.emit(f'{item['message']}')
else:
if item.get('failed'):
self.returned_state.emit(f'{item['failed']}')
print(item, response)
def handle_returned_state(self, state):
mb = QtWidgets.QMessageBox(text=f"{state}")
mb.exec()
worker = Worker()
def register_racer():
card_id = last_card
index = window.racers.currentIndex()
if not index.data():
mb = QtWidgets.QMessageBox(text='Prosím vyberte závodníka!')
mb.exec()
return
racer_id = int(index.data().split(' ')[-1])
try:
starting_number = max(filter(lambda r: r['starting_number'], racers), key=lambda racer: racer['starting_number'])['starting_number'] + 1
except ValueError:
starting_number = 1
racer = list(filter(lambda x: x['racer_id'] == racer_id, racers))[0]
def register_update_racer():
racer['card_id'] = card_id
racer['starting_number'] = starting_number
racer['started'] = False
updateRacers()
queue.put({
'url': config['host'] + '/api/card/register',
'json': {'racer_id': racer_id, 'starting_number': starting_number, 'card_id': card_id, 'time': datetime.datetime.now().strftime('%d.%m.%Y %H:%M:%S.%f')},
'message': f"Úspěšné zaregistrování závodníka {racer['first_name']} {racer['last_name']} se startovním číslem {starting_number}!",
'failed': f"Neúspěšná registrace závodníka {racer['first_name']} {racer['last_name']}",
'on_success': register_update_racer,
})
model = QtGui.QStandardItemModel()
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 reload_racers():
global racers
response = session.get(config['host'] + '/api/racers')
racers = response.json()
updateRacers()
reload_racers()
def findByCard(card_id):
for racer in racers:
if racer['card_id'] == card_id:
return racer
def updateLastCard(card_id):
global last_card, last_time
if card_id == last_card and datetime.datetime.now() - last_time < datetime.timedelta(seconds=15):
return
time = last_time = datetime.datetime.now()
last_card = card_id
window.lastCard.setText(str(card_id))
racer = findByCard(card_id)
if racer:
if racer['started']:
def finish_update_racer():
racer['card_id'] = None
queue.put({
'url': config['host'] + '/api/card/unregister',
'json': {'racer_id': racer['racer_id'], 'starting_number': racer['starting_number'], 'card_id': card_id, 'time': time.strftime('%d.%m.%Y %H:%M:%S.%f')},
'message': f"Úspěšné odhlášení závodníka {racer['starting_number']}!",
'failed': f"Neúspěšné odhlášení karty závodníka {racer['starting_number']}",
'on_success': finish_update_racer,
})
else:
def start_update_racer():
racer['started'] = True
queue.put({
'url': config['host'] + '/api/station/register',
'json': {'card_id': card_id, 'time': time.strftime('%d.%m.%Y %H:%M:%S.%f'), 'station_id': 1},
'message': f"Úspěšné odstartování závodníka {racer['starting_number']}!",
'failed': f"Núspěšné odstartování závodníka {racer['starting_number']}, prosím registraci opakujte!",
'on_success': start_update_racer,
})
UsbCardReader(updateLastCard)
window = uic.loadUi("registrace.ui")
window.racers.setModel(model)
window.register_racer.clicked.connect(register_racer)
window.reload_racers.clicked.connect(reload_racers)
window.show()
app.exec()

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Frame</class>
<widget class="QFrame" name="Frame">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>315</width>
<height>289</height>
</rect>
</property>
<property name="windowTitle">
<string>Registrace závodníků</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="register_racer">
<property name="text">
<string>Registrovat</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLineEdit" name="lastCard"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>číslo karty</string>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="5">
<widget class="QListView" name="racers"/>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="reload_racers">
<property name="text">
<string>Obnovit Závodníky</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,34 @@
{
"2": "0:35:59.818971",
"29": "1:10:52.076408",
"14": "1:11:35.670162",
"9": "1:14:40",
"10": "1:16:02.174205",
"12": "1:18:12.521345",
"26": "1:21:24.962008",
"8": "1:23:45.241021",
"5": "1:24:33.080748",
"3": "1:25:36.486060",
"25": "1:26:57.409779",
"27": "1:32:49.493213",
"18": "1:35:04.610546",
"6": "1:35:28.914085",
"21": "1:35:29.494112",
"28": "1:37:56.900763",
"13": "1:39:20.394593",
"17": "1:39:59.664271",
"4": "1:40:15.602185",
"15": "1:41:16.795669",
"20": "1:43:29.166855",
"16": "1:48:28.014745",
"19": "1:48:37.692711",
"30": "1:48:51.712639",
"11": "1:48:56.350571",
"22": "1:49:04.450512",
"31": "2:05:10.107744",
"24": "2:05:33.883454",
"7": "2:05:42.955540",
"32": "2:06:17.053222",
"23": "2:11:50.391043",
"1": "2:24:50.507501"
}

View File

@@ -1,51 +1,51 @@
import usb.core
import usb.util
import time
import requests
import usb.core
import usb.util
import time
import requests
import json
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
USB_VENDOR = 0xffff # Vendor-ID:
USB_PRODUCT = 0x0035 # Product-ID
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
USB_VENDOR = 0xffff # Vendor-ID:
USB_PRODUCT = 0x0035 # Product-ID
# Find the HID device by vender/product ID
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
# Get and store the endpoint
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
# Claim the device
usb.util.claim_interface(dev, USB_IF)
receivedNumber = 0
while True:
control = None
try:
# Read a character from the device
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
# Get and store the endpoint
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
# Claim the device
usb.util.claim_interface(dev, USB_IF)
receivedNumber = 0
while True:
control = None
try:
# Read a character from the device
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
# Here you have to analyze what's coming in.
# In my case you had to check the first byte (command)
if (control[2] != 40) & (control[2] != 0):
# Convert ascii to a number, there's probably better ways to do so.
receivedDigit = control[2] - 29
if receivedDigit == 10:
if receivedDigit == 10:
receivedDigit = 0
# Append the digit to the number
receivedNumber = 10 * receivedNumber + receivedDigit
receivedNumber = 10 * receivedNumber + receivedDigit
# Check if the received character is CRLF
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
print('cardNumber:', receivedNumber)
except KeyboardInterrupt:
except KeyboardInterrupt:
exit()
except:
pass
time.sleep(0.001) # Let CTRL+C actually exit
except:
pass
time.sleep(0.001) # Let CTRL+C actually exit

View File

@@ -12,7 +12,7 @@ if DEBUG == True:
index = 2
else:
index = 1
activeCards = []
activeCards = []
TIME = 600
@@ -53,16 +53,16 @@ class UsbCardReader():
# 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 activeCards, db, times, times_json
print("Waiting for card")
receivedNumber = 0
while True:
control = None
try:
@@ -72,7 +72,7 @@ class UsbCardReader():
if receivedDigit == 10:
receivedDigit = 0
receivedNumber = 10 * receivedNumber + receivedDigit
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not receivedNumber == 0 )):
try:
with open('people.json', 'r') as f:
@@ -99,12 +99,12 @@ class UsbCardReader():
print(times)
except Exception as e: print(e)
receivedNumber = 0
except KeyboardInterrupt:
exit()
except:
pass
time.sleep(0.001)
UsbCardReader()

View File

@@ -1,12 +1,160 @@
{
"1": {
"start": "25/02/2025, 18:06:16",
"end": "25/02/2025, 18:06:31",
"duration": "0:00:14.553644"
"start": "31/05/2025, 10:00:08",
"end": "31/05/2025, 12:24:58",
"duration": "2:24:50.507501"
},
"2": {
"start": "25/02/2025, 18:15:08",
"end": "25/02/2025, 18:15:27",
"duration": "0:00:19.543765"
"start": "31/05/2025, 10:05:37",
"end": "31/05/2025, 10:41:37",
"duration": "0:35:59.818971"
},
"3": {
"start": "31/05/2025, 10:10:09",
"end": "31/05/2025, 11:35:45",
"duration": "1:25:36.486060"
},
"4": {
"start": "31/05/2025, 10:15:14",
"end": "31/05/2025, 11:55:30",
"duration": "1:40:15.602185"
},
"5": {
"start": "31/05/2025, 10:20:08",
"end": "31/05/2025, 11:44:41",
"duration": "1:24:33.080748"
},
"6": {
"start": "31/05/2025, 10:25:01",
"end": "31/05/2025, 12:00:30",
"duration": "1:35:28.914085"
},
"7": {
"start": "31/05/2025, 10:30:01",
"end": "31/05/2025, 12:35:44",
"duration": "2:05:42.955540"
},
"8": {
"start": "31/05/2025, 10:35:05",
"end": "31/05/2025, 11:58:50",
"duration": "1:23:45.241021"
},
"9": {
"start": "31/05/2025, 10:39:57"
},
"10": {
"start": "31/05/2025, 10:42:01",
"end": "31/05/2025, 11:58:03",
"duration": "1:16:02.174205"
},
"11": {
"start": "31/05/2025, 10:45:03",
"end": "31/05/2025, 12:33:59",
"duration": "1:48:56.350571"
},
"12": {
"start": "31/05/2025, 10:49:58",
"end": "31/05/2025, 12:08:10",
"duration": "1:18:12.521345"
},
"13": {
"start": "31/05/2025, 10:55:01",
"end": "31/05/2025, 12:34:21",
"duration": "1:39:20.394593"
},
"14": {
"start": "31/05/2025, 10:59:57",
"end": "31/05/2025, 12:11:33",
"duration": "1:11:35.670162"
},
"15": {
"start": "31/05/2025, 11:05:09",
"end": "31/05/2025, 12:46:25",
"duration": "1:41:16.795669"
},
"16": {
"start": "31/05/2025, 11:10:01",
"end": "31/05/2025, 12:58:29",
"duration": "1:48:28.014745"
},
"17": {
"start": "31/05/2025, 11:15:00",
"end": "31/05/2025, 12:55:00",
"duration": "1:39:59.664271"
},
"18": {
"start": "31/05/2025, 11:20:01",
"end": "31/05/2025, 12:55:05",
"duration": "1:35:04.610546"
},
"19": {
"start": "31/05/2025, 11:25:00",
"end": "31/05/2025, 13:13:38",
"duration": "1:48:37.692711"
},
"20": {
"start": "31/05/2025, 11:29:58",
"end": "31/05/2025, 13:13:27",
"duration": "1:43:29.166855"
},
"21": {
"start": "31/05/2025, 11:35:30",
"end": "31/05/2025, 13:11:00",
"duration": "1:35:29.494112"
},
"22": {
"start": "31/05/2025, 11:40:02",
"end": "31/05/2025, 13:29:06",
"duration": "1:49:04.450512"
},
"23": {
"start": "31/05/2025, 11:44:59",
"end": "31/05/2025, 13:56:49",
"duration": "2:11:50.391043"
},
"24": {
"start": "31/05/2025, 11:50:45",
"end": "31/05/2025, 13:56:19",
"duration": "2:05:33.883454"
},
"25": {
"start": "31/05/2025, 11:55:04",
"end": "31/05/2025, 13:22:02",
"duration": "1:26:57.409779"
},
"26": {
"start": "31/05/2025, 12:00:00",
"end": "31/05/2025, 13:21:24",
"duration": "1:21:24.962008"
},
"27": {
"start": "31/05/2025, 12:05:01",
"end": "31/05/2025, 13:37:51",
"duration": "1:32:49.493213"
},
"28": {
"start": "31/05/2025, 12:10:03",
"end": "31/05/2025, 13:48:00",
"duration": "1:37:56.900763"
},
"29": {
"start": "31/05/2025, 12:14:58",
"end": "31/05/2025, 13:25:50",
"duration": "1:10:52.076408"
},
"30": {
"start": "31/05/2025, 12:20:02",
"end": "31/05/2025, 14:08:54",
"duration": "1:48:51.712639"
},
"31": {
"start": "31/05/2025, 12:50:10",
"end": "31/05/2025, 14:55:20",
"duration": "2:05:10.107744"
},
"32": {
"start": "31/05/2025, 12:50:13",
"end": "31/05/2025, 14:56:30",
"duration": "2:06:17.053222"
}
}

View File

@@ -1,52 +0,0 @@
import usb.core
import usb.util
import threading
import time
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in ms
USB_VENDOR = 0xffff # Vendor-ID:
USB_PRODUCT = 0x0035 # Product-ID
class UsbCardReader:
def __init__(self, callback):
#fn called on found card
self.callback = callback
# 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):
receivedNumber = 0
while True:
control = None
try:
control = self.dev.read(self.endpoint.bEndpointAddress, self.endpoint.wMaxPacketSize, USB_TIMEOUT)
if (control[2] != 40) and (control[2] != 0):
receivedDigit = control[2] - 29
if receivedDigit == 10:
receivedDigit = 0
receivedNumber = 10 * receivedNumber + receivedDigit
if ( control[0] == 0 ) and ( control[2] == 40 ) and ( not receivedNumber == 0 ):
self.callback(receivedNumber)
receivedNumber = 0
except KeyboardInterrupt:
exit()
except:
receivedNumber = 0
pass
time.sleep(0.001)

View File

@@ -29,12 +29,12 @@ class UsbCardReader():
# Claim the device
usb.util.claim_interface(self.dev, USB_IF)
self.receivedNumber = 0
def read(self):
global activeCards
print("Priloz kartu")
while True:
control = None
try:
@@ -44,7 +44,7 @@ class UsbCardReader():
if receivedDigit == 10:
receivedDigit = 0
self.receivedNumber = 10 * self.receivedNumber + receivedDigit
if (( control[0] == 0 )) & (( control[2] == 40 )) & (( not self.receivedNumber == 0 )):
try:
cardPresent = False
@@ -60,24 +60,24 @@ class UsbCardReader():
self.receivedNumber = 0
print("Priloz kartu")
except Exception as e: print(e)
except KeyboardInterrupt:
exit()
except:
pass
time.sleep(0.001)
def assign(self):
global activeCards
n = input("Cislo zavodnika: ")
activeCards[str(n)] = self.receivedNumber
with open('people.json', 'w') as f:
f.write(json.dumps(activeCards, indent = 4))
self.receivedNumber = 0
print("Ulozeno, priloz kartu")
if __name__ == "__main__":
reader = UsbCardReader()
print("Zapis zavodniku ready")

View File

@@ -46,17 +46,17 @@ def read(ser):
lap += 1
data_dict[data[0]]['laps'] = lap
data_dict[data[0]]['time'] = get_seconds()
except:
data_dict[data[0]] = {'name': data[1]}
data_dict[data[0]]['time'] = get_seconds()
data_dict[data[0]]['laps'] = 0
data_json = json.dumps(data_dict, indent=4)
print(data_json)
with open(JSON_PATH, 'w') as file:
file.write(data_json)
def write(ser):
while True:
data = input('ID:')
@@ -77,10 +77,10 @@ def write(ser):
def main():
s = serial.Serial(port="/dev/ttyACM3", parity=serial.PARITY_EVEN, stopbits=serial.STOPBITS_ONE, timeout=1)
s.flush()
rw = input('Read or Write tags? [R/w]')
rw = rw.lower()
if rw == 'w':
s.write('w\r'.encode())
write(s)
@@ -90,11 +90,12 @@ def main():
elif rw == '':
s.write('r\r'.encode())
read(s)
else:
print('Invalid option')
if __name__ == "__main__":
if __name__ == "__main__":
main()

View File

@@ -56,13 +56,13 @@ def loop_neopixel():
led_strip.fill(color)
led_strip.write()
time.sleep(1)
neopix_loop_dot_pos = 0
def neopixel_loop_dot():
global neopix_loop_dot_pos
color = (255, 0, 0)
black = (0, 0, 0)
color = set_neopixel_brightness(color)
led_strip[neopix_loop_dot_pos] = black
neopix_loop_dot_pos += 1
@@ -71,16 +71,16 @@ def neopixel_loop_dot():
led_strip[neopix_loop_dot_pos] = color
led_strip.write()
time.sleep(0.2)
def lightup_led(index, color):
led_strip[index] = color
led_strip.write()
def blink_and_beep(times):
global pushbutton_pressed, blink_interrupted
blink_delay = 0.2
#insert beep
buzzer.value(1)
for i in range(0, times):
@@ -97,20 +97,20 @@ def blink_and_beep(times):
buzzer.value(0)
return
buzzer.value(0)
ten_min_timer = 0
ten_min_timer_led_index = 11
def count_10_min():
global ten_min_timer, ten_min_timer_led_index, pushbutton_pressed, blink_interrupted
red = (255, 0, 0)
red = set_neopixel_brightness(red)
green = (0, 255, 0)
green = set_neopixel_brightness(green)
if ten_min_timer_led_index == 11:
return
if (ten_min_timer % 60) == 0:
if ten_min_timer_led_index == 10:
pushbutton_pressed = 0
@@ -128,7 +128,7 @@ def count_10_min():
return
lightup_led(ten_min_timer_led_index, red)
ten_min_timer_led_index += 1
ten_min_timer += 1
def button_callback(push_button):

View File

@@ -406,3 +406,4 @@ class PN532:
_COMMAND_INDATAEXCHANGE, params=params, response_length=1
)
return response[0] == 0x00

View File

@@ -84,12 +84,12 @@ def read_nfc_loop():
# Try again if no card is available.
if uid is not None:
break
set_neopixel_color(255,255,0)
ntag_string = 'Data: '
sys.stdout.write('Reading ntag \r')
leds_on = 0
for page in range(20,40):
try:
@@ -105,7 +105,7 @@ def read_nfc_loop():
if leds_on > 7:
leds_on = 7
led_strip.write()
if ntag2xx_page is not None:
for char in ntag2xx_page:
ntag_string += chr(char)
@@ -115,11 +115,11 @@ def read_nfc_loop():
except:
sys.stdout.write('Error reading card\r')
return 1
set_neopixel_color(0,255,0)
sys.stdout.write(ntag_string + '\r')
time.sleep(3)
return 0
#print('PAGE ',page,': ',[chr(x) for x in ntag2xx_page])
@@ -138,14 +138,14 @@ def write_nfc_loop(data):
# Try again if no card is available.
if uid is not None:
break
set_neopixel_color(255,255,0)
sys.stdout.write('Erasing card\r')
for page in range(20,41):
content_erase = b'\x00\x00\x00\x00'
pn532.ntag2xx_write_block(page, content_erase)
sys.stdout.write('Writing card\r')
for page in range(20,20 + pages):
content_slice = bytearray(4)
@@ -157,7 +157,7 @@ def write_nfc_loop(data):
#content_slice.append(content[i + 4 * (page - 20)])
print(content_slice)
pn532.ntag2xx_write_block(page, content_slice)
sys.stdout.write('Write done\r')
set_neopixel_color(0,255,0)