Aplikacja webowa do odczytu i monitorowania danych z timerów strzeleckich SG Timer poprzez Bluetooth Low Energy (BLE).
Strona: timer.pifpaf.fun | GitHub: enclude/www.timer.pifpaf.fun
- Instalacja jako aplikacja (PWA) - strone mozna zainstalowac na telefonie/tablecie ("Dodaj do ekranu glownego" / "Zainstaluj aplikacje"); uruchamia sie wtedy w osobnym oknie, bez paska adresu
- Dziala bez internetu - po pierwszym otwarciu aplikacja startuje offline: polaczenie z timerem, podglad na zywo, cache sesji i kody tymczasowe dzialaja bez sieci; internet jest potrzebny wylacznie do zapisu w bazie kalkulatora
- Kody tymczasowe - kazda zakonczona sesja dostaje lokalny kod (np.
3-0147) odtwarzany tonami do kamery, nawet bez internetu; po kodzie mozna pozniej odnalezc wynik - Polaczenie Bluetooth - laczenie z timerem przez Web Bluetooth API
- Podglad na zywo - biezacy czas i liczba strzalow w czasie rzeczywistym
- Sterowanie sesja - Start / Stop sesji strzeleckiej
- Start z opoznieniem - Start PAR z losowym opoznieniem 1-4s (PAR_SETUP)
- Ustawienia PAR - limit czasu i limit strzalow zapisywane do timera (karta "Ustawienia PAR"); timer sam konczy sesje po osiagnieciu limitu; limity sa tez wysylane do bazy kalkulatora w osobnych polach (bez zmiany opisu)
- Historia sesji - przegladanie sesji zapisanych w urzadzeniu z liczba strzalow i czasem trwania
- Cache sesji - pobranie sesji z dzisiaj (lub z ostatnich 24h — do wyboru) wraz z listami strzalow do pamieci przegladarki (localStorage); pobrane sesje mozna przegladac i wysylac do kalkulatora bez polaczenia BLE — timer pozostaje wolny dla innych
- Hurtowa wysylka do bazy - przycisk "Wyslij wszystkie do bazy" w karcie "Sesje z cache" zapisuje jednym kliknieciem wszystkie sesje z cache w bazie kalkulatora (bez toru i uczestnika — uzupelnia sie je pozniej w kalkulatorze); sesje, ktore juz sa w bazie (ten sam numer seryjny timera i ID sesji), nie sa dublowane, tylko oznaczane "w bazie #ID" wraz z torem/uczestnikiem pobranymi z bazy; wpisy zapisane z tej przegladarki maja link "edytuj w bazie"; opcja "Nadpisz sesje juz zapisane w bazie" aktualizuje istniejace wpisy danymi z timera (punktacja i wpisane w kalkulatorze tor/uczestnik zostaja)
- Etykiety sesji w cache - kazdej sesji w cache mozna przypisac nazwe toru i uczestnika (ikona olowka); etykiety sa zapamietywane i uzywane przy wysylaniu do kalkulatora (maja pierwszenstwo nad formularzem "Dane do kalkulatora")
- Auto-zapis po Stop - jesli nazwa toru i uczestnik sa wypelnione w "Dane do kalkulatora", zakonczona sesja (czasy, strzaly, splity) automatycznie zapisuje sie w cache z tymi etykietami — idealne przy obsludze kolejnych uczestnikow na tym samym torze
- Lista strzalow - czasy i splity dla wybranej sesji
- Wyslij do kalkulatora - przesyla dane serii do piro-kalkulator.pifpaf.fun — dostepne zarowno po zakonczeniu biezacej sesji, jak i z poziomu historii
- Zapisz w bazie - zapisuje wynik (czas i liczba strzalow) bezposrednio do bazy kalkulatora bez przechodzenia przez formularz; po zapisie wyswietla ID wpisu — przyda sie gdy nie liczymy A/C/D, a sam czas i liczba strzalow wystarczy
- Eksport i import cache - cala pamiec sesji mozna zapisac do pliku JSON i wczytac na innym urzadzeniu (import scala dane, nie kasuje tego, co juz jest)
- Baner synchronizacji - informuje o trybie offline i o liczbie sesji czekajacych na wyslanie do bazy; przycisk "Wyslij zalegle do bazy" wysyla je jednym kliknieciem, gdy wroci internet
- Wersja w stopce - hash commitu z linkiem do GitHub, generowany automatycznie przez CI
Aplikacja wymaga przegladarki wspierajacej Web Bluetooth API:
- Google Chrome
- Microsoft Edge
- Opera
Uwaga: Firefox i Safari nie sa wspierane.
- SG Timer Sport
- SG Timer GO
Aplikacja jest kompatybilna z BLE API w wersji 3.2.
- Otworz aplikacje w kompatybilnej przegladarce (opcjonalnie zainstaluj ja: menu przegladarki → "Zainstaluj aplikacje" / "Dodaj do ekranu glownego")
- Kliknij "Polacz z timerem" i wybierz urzadzenie (nazwa zaczyna sie od "SG-SST4")
- Po polaczeniu mozesz:
- Rozpoczac sesje przyciskiem "Start" (natychmiastowy) lub "Start z opoznieniem" (losowe 1-4s)
- Zatrzymac sesje przyciskiem "Stop"
- Po zakonczeniu sesji kliknac "Wyslij do kalkulatora"
- Przegladac zapisane sesje — lista wyswietla liczbe strzalow i czas trwania
- Kliknac sesje historyczna, obejrzec strzaly i wyslac do kalkulatora (opis zawiera date sesji)
- Kliknac "Pobierz sesje do cache" (zakres: "z dzisiaj" lub "z ostatnich 24h") — sesje zapisza sie w przegladarce; po rozlaczeniu mozna je dalej przegladac w karcie "Sesje z cache" i wysylac do kalkulatora
- Po zawodach: "Wyslij wszystkie do bazy" — wszystkie sesje z cache trafiaja do bazy kalkulatora bez dublowania juz zapisanych; tor i uczestnika mozna uzupelnic pozniej linkiem "edytuj w bazie" lub w panelu kalkulatora
- Kliknac "Zapisz w bazie" — zapisuje wynik wprost do bazy kalkulatora (bez A/C/D) i wyswietla ID wpisu
- Ustawic "Nr stanowiska" w karcie "Dane do kalkulatora" — po kazdej sesji aplikacja nada i zagra kod tymczasowy (np.
3-0147), takze bez internetu - "Eksportuj do pliku" / "Wczytaj z pliku" w karcie "Sesje z cache" — kopia zapasowa sesji i przenoszenie ich miedzy urzadzeniami
7520ffff-14d2-4cda-8b6b-697c554c9311
| Charakterystyka | UUID | Wlasciwosci | Opis |
|---|---|---|---|
| Command | 75200000-... | W, N | Wysylanie komend; odpowiedzi jako notyfikacje |
| Event | 75200001-... | N | Odbieranie zdarzen z urzadzenia |
| Session List | 75200002-... | R, W | Lista zapisanych sesji |
| Reserved | 75200003-... | R | Zarezerwowany — nie zapisywac |
| Shot List | 75200004-... | R, W | Lista strzalow w sesji |
| PAR Setup | 75200005-... | R, W | Konfiguracja startu PAR (opoznienie, limit czasu, limit strzalow) |
| Unix Time | 75200006-... | R, W | Czas urzadzenia (czas lokalny bez strefy) |
| API Version | 7520fffe-... | R | Wersja API (ASCII) |
| ID | Nazwa | Opis |
|---|---|---|
| 0x00 | SESSION_START | Rozpocznij sesje |
| 0x01 | SESSION_SUSPEND | Wstrzymaj sesje |
| 0x02 | SESSION_RESUME | Wznow sesje |
| 0x03 | SESSION_STOP | Zakoncz sesje |
| ID | Nazwa | Opis |
|---|---|---|
| 0x00 | SESSION_STARTED | Sesja rozpoczeta |
| 0x01 | SESSION_SUSPENDED | Sesja wstrzymana |
| 0x02 | SESSION_RESUMED | Sesja wznowiona |
| 0x03 | SESSION_STOPPED | Sesja zakonczona |
| 0x04 | SHOT_DETECTED | Wykryto strzal |
| 0x05 | SESSION_SET_BEGIN | Poczatek setu sesji |
Urzadzenie wysyla shotNum od 0. Aplikacja wyswietla strzaly od 1 (shotNum + 1).
Pierwszy strzal (shotNum === 0) wyswietlany jest bez splitu (-).
Urzadzenie zapisuje czas lokalny jako Unix timestamp (bez informacji o strefie).
Wyswietlanie uzywa timeZone: 'UTC', aby uniknac podwojnego dodania offsetu przez przegladarke.
Przycisk "Wyslij do kalkulatora" otwiera piro-kalkulator.pifpaf.fun z parametrami GET:
| Parametr | Opis |
|---|---|
liczba_strzalow |
Liczba strzalow w serii |
czas_bazowy |
Czas ostatniego strzalu w sekundach (np. 15.80) |
opis |
Opoznienie startu + lista strzalow z czasami i splitami (URL-encoded) |
nazwa_toru |
Nazwa toru z pola "Dane do kalkulatora" (tylko gdy wypelnione) |
uczestnik |
Uczestnik z pola "Dane do kalkulatora" (tylko gdy wypelnione) |
Dostepny w dwoch trybach:
- Biezaca sesja — pojawia sie po zakonczeniu sesji (SESSION_STOPPED),
opiszaczyna sie od opoznienia startu (np.opoznienie startu 2.3s), dalej lista strzalow - Sesja historyczna — pojawia sie pod lista strzalow wybranej sesji,
opiszaczyna sie od daty i godziny sesji, a nastepnie opoznienia startu (jesli zapisane w cache)
Opoznienie startu (delay od naciśniecia "Start") pochodzi ze zdarzenia SESSION_STARTED i jest
dolaczane do opis dla sesji live oraz sesji z cache (gdzie jest trwale zapisywane). Sesje wczytane
bezposrednio przez BLE ("Wczytaj sesje") nie zawieraja tej informacji — SHOT_LIST jej nie przekazuje.
Po polaczeniu z timerem widoczna jest karta "Dane do kalkulatora" z polami "Nazwa toru" i "Uczestnik".
Nazwa toru jest zapamietywana w przegladarce (localStorage) i przywracana przy kolejnej wizycie;
uczestnik jest wpisywany kazdorazowo. Oba pola sa opcjonalne — puste nie sa dolaczane do URL.
Przycisk "Zapisz w bazie" pozwala zapisac wynik sesji wprost do bazy piro-kalkulator.pifpaf.fun bez otwierania kalkulatora i recznego wpisywania A/C/D. Przyda sie gdy interesuje nas sam czas i liczba strzalow, bez pelnej punktacji IPSC.
| Przycisk | Dostepnosc |
|---|---|
| "Zapisz w bazie" (biezaca sesja) | pojawia sie po zakonczeniu sesji (razem z "Wyslij do kalkulatora") |
| "Zapisz w bazie" (historia/cache) | pojawia sie pod lista strzalow wybranej sesji |
Po kliknieciu:
- Przycisk blokuje sie i wyswietla "Zapisywanie..."
- Dane (liczba strzalow, czas, opis z lista strzalow i splitami, nazwa toru, uczestnik) sa wysylane przez
POSTnahttps://piro-kalkulator.pifpaf.fun/api_save.php - Po sukcesie wyswietlane jest "Zapisano! ID: #123" — identyfikator wpisu w bazie kalkulatora
- W razie bledu komunikat pokazuje przyczyne i przycisk odblokowuje sie
Wynik zapisuje sie z zerami dla trafien A/C/D i wszystkich kar (hit_factor = 0). Pelne dane (lista strzalow z czasami i splitami) trafiaja do pola opis. Jesli sesja ma kod tymczasowy, jest on wysylany razem z wynikiem (pole temp_id) — po nim mozna potem odnalezc wpis.
Gdy zapis nie powiedzie sie z powodu braku internetu, komunikat brzmi "Brak internetu — sesja czeka w cache": nic nie ginie, sesje wysyla sie pozniej przyciskiem "Wyslij zalegle do bazy".
Aplikacja jest Progressive Web App — mozna ja zainstalowac i uzywac bez zasiegu.
Instalacja:
- Android/Chrome: menu (trzy kropki) → "Zainstaluj aplikacje" lub "Dodaj do ekranu glownego"
- Desktop Chrome/Edge: ikona instalacji w pasku adresu
- Po instalacji aplikacja otwiera sie w osobnym oknie, w pionie, z wlasna ikona
Co dziala bez internetu:
- otwarcie aplikacji (strona jest zapamietana przez service worker
sw.js) - polaczenie z timerem, start/stop, podglad na zywo, historia sesji z timera
- cache sesji w przegladarce, etykiety (tor/uczestnik), eksport do pliku
- kody tymczasowe i ich sygnal tonowy
Czego bez internetu nie ma:
- zapisu do bazy kalkulatora i wysylki do kalkulatora (te sesje czekaja w cache)
- sygnalu tonowego z ID wpisu w bazie (ID powstaje dopiero przy zapisie)
Baner na gorze strony pokazuje tryb offline oraz liczbe sesji w cache, ktore nie maja jeszcze wpisu w bazie. Gdy internet wroci, baner daje przycisk "Wyslij zalegle do bazy" — nic nie jest wysylane samo z siebie, wysylka zawsze wymaga klikniecia.
Po wdrozeniu nowej wersji aplikacja aktualizuje sie sama przy kolejnym otwarciu z internetem (wersja w stopce pokazuje, ktory commit jest uruchomiony).
Sygnal z ID wpisu wymaga zapisu w bazie, czyli internetu. Na stanowisku strzeleckim zasiegu zwykle nie ma, dlatego kazda zakonczona sesja moze dostac kod tymczasowy nadawany lokalnie w telefonie i od razu odtwarzany tonami do kamery.
- Kod ma postac
S-NNNN, np.3-0147: pierwsza cyfra to numer stanowiska, dalej licznik sesji w tej przegladarce. Dzieki numerowi stanowiska kody z roznych stanowisk sie nie powtarzaja. - Nr stanowiska ustawia sie raz, w karcie "Dane do kalkulatora" (wartosci 1-9, zapamietywane w przegladarce).
- Checkbox "Zagraj kod tymczasowy po zakonczeniu sesji (dziala bez internetu)" jest domyslnie wlaczony. Po komendzie Stop kod pojawia sie przy sesji i jest odtwarzany; przycisk "🔊 Zagraj kod …" pozwala puscic go ponownie (np. gdy kamera wtedy nie nagrywala).
- Sesja z nadanym kodem zawsze zapisuje sie w cache — takze gdy tor i uczestnik nie sa wypelnione (kod na nagraniu bez listy strzalow nie mialby wartosci).
- Kod jest widoczny przy sesji w karcie "Sesje z cache" i trafia do bazy razem z wynikiem, wiec Piro Overlay potrafi po nim odnalezc wpis — nawet jesli ID wpisu nigdy nie zagralo.
- Drugi checkbox, "Zapisz w bazie i zagraj sygnal ID po zakonczeniu sesji (wymaga internetu)", dziala jak wczesniej: po Stop sesja zapisuje sie w bazie i odtwarzany jest sygnal z ID wpisu. Oba sygnaly moga byc wlaczone naraz — nigdy nie nakladaja sie na siebie, graja po kolei.
Cache sesji zyje w pamieci jednej przegladarki na jednym urzadzeniu — wyczyszczenie danych witryny skasowaloby caly dzien zawodow. W karcie "Sesje z cache" sa dwa przyciski:
- "Eksportuj do pliku" — zapisuje wszystkie sesje (ze strzalami, etykietami, kodami
tymczasowymi i numerami wpisow w bazie) do pliku
sgtimer-cache-RRRR-MM-DD.json - "Wczytaj z pliku" — scala zawartosc pliku z tym, co juz jest w przegladarce: nowe sesje dopisuje, a w istniejacych uzupelnia tylko brakujace dane. Wlasne poprawki (np. poprawione nazwisko) i przypisane numery wpisow w bazie nie sa nadpisywane. Dzieki temu mozna scalic sesje z kilku tabletow na jednym urzadzeniu.
Telefon moze odtworzyc identyfikator sesji jako sekwencje tonow - aplikacja Piro Overlay, nakladajaca info o strzalach na wideo, odczytuje ten sygnal z mikrofonu kamery i uzupelnia sesje automatycznie, bez recznego wpisywania.
Protokol (wersja 3): marker + cyfra kanalu + 4 cyfry wartosci + cyfra kontrolna, pasmo 5000-7000 Hz, kazdy ton 0,3 s, cala sekwencja powtarzana dwa razy.
| Kanal | Wartosc | Kiedy |
|---|---|---|
0 |
ID wpisu w bazie kalkulatora | po zapisie w bazie (wymaga internetu) |
1-9 |
kod tymczasowy (kanal = nr stanowiska) | zaraz po zakonczeniu sesji, takze offline |
- Checkbox "Zapisz w bazie i zagraj sygnal ID po zakonczeniu sesji (wymaga internetu)" (karta "Dane do kalkulatora", domyslnie wylaczony, zapamietywany w przegladarce) - gdy zaznaczony, sesja po Stop zapisuje sie w bazie, a sygnal z ID gra automatycznie.
- Przycisk "🔊 Zagraj sygnal ID" pojawia sie zawsze przy komunikacie "Zapisano!" (obok "Zapisz w bazie", tak przy sesji zywej, jak i historii/cache) - pozwala puscic sygnal jeszcze raz, np. gdy kamera nie nagrywala w danym momencie.
- Dziala tylko dla wartosci 0-9999 (limit 4-cyfrowego protokolu) - dla wiekszych ID sygnal nie jest odtwarzany (zamiast odtworzyc ucieta, blednie wygladajaca wartosc).
- Gdy graja oba sygnaly (kod tymczasowy i ID), ida jeden po drugim - nigdy sie nie nakladaja.
Uwaga dla integratorow: wersja 3 nie jest zgodna z wersja 2 (bez cyfry kanalu). Aplikacja, dekoder w Piro Overlay i kalkulator musza uzywac tych samych czestotliwosci i czasow.
Charakterystyka 75200005-… (R, W), format: [start_delay(2), time_limit(2), shot_limit(2)]
| Pole | Wartosc | Znaczenie |
|---|---|---|
start_delay |
jednostki 0.1s | 0x0000 = natychmiastowy, 0xFFFF = losowe 1.0–4.0s |
time_limit |
jednostki 0.1s | 0x0000 = bez limitu czasu |
shot_limit |
liczba strzalow | 0x0000 = bez limitu strzalow |
Przycisk "Start" zapisuje PAR z zerowym opoznieniem, przycisk "Start z opoznieniem" z losowym opoznieniem 1.0–3.0s (losowanym w JS). W obu przypadkach time_limit i shot_limit pochodza z karty "Ustawienia PAR" (0 = bez limitu). Przycisk "Zapisz PAR w timerze" zapisuje same limity, zachowujac start_delay odczytany z urzadzenia. Przycisk "Zresetuj PAR" zeruje oba pola i zapisuje 0/0 do timera (usuwa limity). Po zapisie PAR_SETUP wymagane jest oddzielne wyslanie komendy SESSION_START.
Stopka czyta wersje bezposrednio z katalogu .git (serwer jest wdrazany przez git pull
w cronie): hash commitu z HEAD/refs jako klikalny link do GitHub oraz date wdrozenia
(filemtime refa). Dostep HTTP do .git jest zablokowany w .htaccess. Gdy katalogu
.git brak, wersja nie jest wyswietlana.
Ten sam hash steruje trybem offline: service worker jest rejestrowany jako sw.js?v=<hash>,
wiec kazde wdrozenie to nowy adres workera i nowa kopia strony w pamieci offline (stare kopie
sa kasowane). Pliki sw.js i manifest.json sa serwowane z Cache-Control: no-cache, zeby
przegladarka nie trzymala w nieskonczonosc starej wersji aplikacji.
| Urzadzenie | Firmware |
|---|---|
| SG-SST4B00000 | BLE API 3.2 |
- Urządzenie: SG-SST4B00000, API 3.2
- Sesje 8-strzalowe
- Odkryte bledy:
shotNum0-indexed — strzaly wyswietlane od 0 zamiast od 1parseBigEndianzwracal -1 dla0xFFFFFFFF(signed 32-bit overflow) — sentinel nie byl wykrywany, lista sesji ladowala 100 pustych wpisow z ID -1 i data 01.01.1970formatDatebeztimeZone:'UTC'— czas urzadzenia wyswietlany o 1h za duzo (CET podwojnie naliczany)
- Sesja 30 strzalow, czas 38.20s
- Czas urzadzenia: 26.02.2026, 10:40:42 (telefon: 10:41) — zgodny po poprawce strefy
- Licznik i komunikat "Sesja zakonczona (30 strzalow)" / "Strzaly: 30" — zgodne po poprawce numerowania
- Przycisk "Wyslij do kalkulatora" pojawil sie poprawnie po zakonczeniu sesji
- Dane przekazane do piro-kalkulator.pifpaf.fun:
czas_bazowy=38.2,liczba_strzalow=30opisz pelna lista 30 strzalow z czasami i splitami, np.1: 16.05s | 2: 19.23s (+3.18s) | ...
- Kalkulator poprawnie wyswietlil wynik: czas koncowy 38.20s, 0 kar