Devblog - Powered by Gunpowder & Coffee

Vývojářský deníček #1 – Magická hůlka, zoom a jeden výživnej bug

Posledních pár dní mne nepěkně potrápil jeden bug. A ukažme si na něj prstem, může za to vlastně @Murphy :smiley: Přišel s opravdu dobrým nápadem, že by bylo skvělé, kdyby AI rozpoznávalo zásahy jen v aktuálně zobrazené obrazovce. Kdo jsem já abych dobrý nápad ignoroval. Tuhle myšlenku jsem trochu rozvedl a udělal to jako volitelné nastavení v settings.

Představte si to tak, že nahrajete fotku terče a lokálně běžící offline AI model rozpozná veškeré zásahy na terči. To je skvělé, ale pokud máte více skupin zásahů na jednom terči může to být nepraktické. Následovala myšlenka, že by tedy AI měla rozpoznávat zásahy jen v aktuálně zobrazené části obrázku, tedy když zazoomuju tak, že je vidět jen část terče s konkrétní skupinou zásahů a spustím AI detekci, tak AI detekce rozpozná jen tyto konkrétní zásahy. Vzhledem ke složitosti implementace to ve skutečnosti funguje tak, že AI stále rozpoznává zásahy na celém terči, ale kód pak “vytvoří” dočasné body zásahu pouze u zásahů, které jsou v aktivním výřezu. Po vytvoření dočasných bodů zásahu je potřeba je ještě vybrat Magickou hůlkou a tady vznikl problém. Po dokončení AI detekce se nastavoval stav "is magic wand active = true". Ve finále došlo k tomu, že pokud jste přidali další terč, "Magic wand" zůstal ve stavu “true” a proto nešlo přidat referenční body.

Když jsem na to po několika dnech konečně přišel, opravdu se mi ulevilo, už jsem se pomalu psychicky chystal na rollback z Githubu :smiley:

Abych si spravil chuť, trochu jsem vypimpoval obrazovku pro detailní zobrazení seance a konkrétně graf. Nyní jde graf rozkliknout na fullscreen. Poté se automaticky přepne na širokoúhlé zobrazení, podporuje gesta jako Zoom (přiblížení) a Pan (posun), a také scrubbing (tažení prstem po ose X grafu).

Trochu jsem se pověnoval i “designu” aplikace, uvědomuji si, že to je moje slabá stránka, ale vytvořil jsem nějakou novou ikonu která se bude objevovat na ploše telefonu. Bojoval s native splash screenem, který neustále nesmyslně tuto ikonu zobrazoval i při načítání obrazovky. Nakonec jsem zjistil, že pokud nemá žádný obrázek co tam zobrazit, tak zobrazuje ikonu. Překecal jsem ho nakonec pomocí “Jako obrázek pro úvodní obrazovku použij, prosím, systémovou barvu 'průhledná”, ale byl to boj…

A tak vznikla 1.8.0 která je aktuálně ve schvalovacím procesu od Google.

Aplikaci Shooting companion najdete zde - https://play.google.com/store/apps/details?id=cz.aleskozubik.shootingcompanion&hl=cs

Screen_Recording_20250623_123009-ezgif.com-video-to-gif-converter

3 Líbí se

Vývojářský deníček #2 – Plynulejší a chytřejší workflow – „Quality of Life“ vylepšení

Ahoj, v posledním updatu jsem se zaměřil na „Quality of Life“ vylepšení a drobnosti, které odstraňují otravné momenty a zrychlují práci s aplikací.

Řada nápadů přišla od konkrétních uživatelů a já za ně moc děkuji a chtěl bych vás v tom podpořit. Pokud máte jakýkoliv nápad na zlepšení, něco vám nevyhovuje, neváhejte mi napsat klidně sem, do zpráv, nebo na Canny, kde sbíráme feedback.

Generální oprava Kouzelné hůlky – Kouzelná hůlka, která poslouchá (a uklízí po sobě).

Hůlka trpěla nevhodným chováním, po automatické detekci zásahů někdy docházelo k situaci, že se nepřepla do aktivního stavu a bylo nutné ji aktivovat ručně. To bylo způsobeno tím, že při výběru kód kontroloval, zda má uživatel prémiové funkce aktivní, a pokud to kód nestihl dostatečně rychle ověřit, přidání výběrem gestem selhalo. Informaci o prémiovém stavu nyní předáváme rovnou z předchozí obrazovky, takže obrazovka analýzy terče (Target Analysis screen) tuto informaci má, dokáže s ní pracovat a podle toho se kouzelná hůlka vždy správně aktivuje po dokončení AI detekce a není nutné ji zapínat ručně.

S tím souvisí další drobné, ale domnívám se, že důležité vylepšení. Pokud uživatel přidal všechny zásahy, které označila AI výběrem kouzelnou hůlkou do skupiny, a už nebylo co vybírat, musel ještě kouzelnou hůlku vypnout ručně, aby opět mohl zadat POA atd. Nyní je při přidávání bodů kouzelnou hůlkou do skupiny nastavena kontrola, že pokud jsou všechny body již přidány a není co dále přidávat, tak se kouzelná hůlka deaktivuje a opět je k dispozici tlačítko pro rozpoznávání AI, třeba pro další skupinu zásahů nebo zadání POA a uložení terče. Opět odpadá klikání.

Konec prázdným stavům: Vylepšení správy skupin – Už nikdy nezůstanete viset

Pokud jste smazali poslední skupinu zásahů, aplikace se dostala do stavu, kdy nebyla aktivní žádná skupina zásahů a nešlo s aplikací vlastně pracovat. Uživatel musel ručně přidat novou, první skupinu zásahů a poté již vše fungovalo zase správně. Předpokládalo to ale uživatelskou znalost nebo dostatek trpělivosti na bádání, proč to vlastně nefunguje. Nasadil jsem jednoduchou, ale účinnou změnu. Pokud nyní smažete poslední skupinu, aplikace vám automaticky vytvoří novou, prázdnou „Skupinu 1“. Aplikace vás nenechá ve slepé uličce. Můžete bez přerušení pokračovat v práci, ať už mažete nebo přidáváte skupiny.

Praktická drobnost: Snadnější přístup k zálohám – Vaše data, vaše kontrola

Do této verze fungovalo zálohování souborů přes klasické „sdílení“. V podstatě se v aplikaci stáhne kompletní databáze, k tomu se do balíku přidají obrázky terčů a to vše se zabalí do balíčku ZIP a připraví k odeslání, sdílení atp. Problém je v tom, že pokud aplikace obsahuje pár obrázků terčů, tento vygenerovaný balík ZIP měl takovou velikost, že nešel poslat mailem ani jinak sdílet. Nyní to funguje tak, že aplikace vygeneruje balík ZIP a uživatel pak dostane možnost si zálohu uložit na jím zvolené místo v úložišti telefonu, odkud ji lze stáhnout přes PC atd.

Věřím, že i tyto drobné změny mohou mít velký dopad na pocit z používání aplikace, a těší mě, že řada nápadů přišla od vás, uživatelů, kteří již aplikaci testujete v reálném nasazení. Moc si vašich poznatků vážím. Tyto informace jsou pro mě naprosto zásadní.

Budu velmi rád, když mi budete i nadále posílat jakýkoliv nápad nebo hlásit chyby atd.

Zmíněné změny najdete v 1.8.2, která je právě ve schvalování a brzy by se měla nabídnout jako aktualizace.

Keep your powder dry and your scope zeroed!

Podařilo se mi navázat přímou Bluetooth komunikaci s jedním z nejpoužívanějších a nejpřesnějších chronografů na trhu. :shushing_face:

Vývojářský deníček #3 - Inference, kvantizace modelů a hovězí BLE

Ke stažení na Google play zde

Screen_Recording_20250630_091007-ezgif.com-optimize

V posledních dnech jsem se zaměřil převážně na optimalizace AI rozpoznávání zásahů a povedlo se mi dokončit upgrade který zrychluje automatické rozpoznání zásahů o 41%. Pokud AI rozpoznávání používáte (což doporučuju, ohromně to zpříjemňuje práci a zásahy jsou označené konzistentně) tak byste si po aktualizování aplikace měli všimnout citelného zrychlení. Nakonec se jako nejjednodušší cesta ukázalo stáhnout čas pro dekodování obrázku.

Srovnání výkonu AI detekce

Původní časy

Komponenta Čas (ms)
Načítání modelu 22
Dekódování obrázku 1,598
Zpracování obrázku 85
Příprava tensoru 150
AI inference 1,451
Zpracování výsledků 1
Celkový čas 3,312

Současné časy

Komponenta Čas (ms)
Načítání modelu 8
Dekódování obrázku 192
Finální zpracování 253
Příprava tensoru 140
AI inference 1,362
Zpracování výsledků 5
Celkový čas 1,968

Celkový čas inference se zkrátil z 3,312ms na 1,968ms, což představuje zrychlení o 41%.

Kvantizace AI modelu

Pokoušel jsem se také o další zrychlení pomocí kvantizace modelu z float32 na Float16, ale tady jsem si bohužel dost vymlátil zuby a nepodařilo se mi dosáhnout rozumné úspěšnosti rozeznání zásahů. Int8 model dopadl bohužel stejně. Vzhledem k náročnosti a přínosu ve stovkách milisekund to aktuálně dávám taky k ledu..

Reverse engineering Garmin protokolu BLE aneb jak jsem si vybil zuby podruhé

Moje myšlenka byla poměrně jednoduchá. Radar od Garminu přeci komunikuje s mobilní aplikací přes Bluetooth, proč bych tuto komunikaci nezkusil napodobit ve své aplikaci? Co jsem tím chtěl dosáhnout? Chtěl jsem aby se aplikace uměla připojit k radaru stejně jako to dělá nativní aplikace a třeba si rovnou stáhnout uložená naměřená data.

Povedlo se mi dokončit autentizaci, Garmin si s mou aplikací povídá, prošli jsme až k příkazu, který vypisuje obsah filesystemu ale tady jsem narazil. Reverzní engineering je vlastně cely jen hádání a zkoušení, bez dokumentace, bez nápovědy, bez ničeho. Když už jsme se dostali k příkazu pro vypsání uložených seancí, tak jsem si nebyl jistý, jestli ten příkaz v zařízení vůbec existuje a tak jsem se to pokusil ověřil způsobem, kdy zařízení pošlu prokazatelně neexistující příkaz, který jsem si random vymyslel (BEEF_REQUEST) a potvrdilo se, že zařízení skutečně odpovídá jinak než na (DOWNLOAD_REQUEST). To je prokazatelný důkaz, že (DOWNLOAD_REQUEST) v zařízení existuje, jen se mi ještě nepovedlo správně navázat komunikaci a postoupit dále. Tuto možnost jsem nakonec také dal k ledu kvůli časové náročnosti a rozhodl jsem se pro jiný přístup.

Změna importu dat z chronografů do aplikace

Aktuálně to tedy funguje tak, že si v mobilní aplikaci ShotView můžete vygeneroval xlsx soubor, kde můžou být klidně všechny naměřené seance nahromadě. Ten nahrajete do Shooting Companiona, ten to rozparsuje a podle času kdy byl uložen terč a kdy byla naměřená seance radarem přednabídne z hromady dat z xlsx tu správnou seanci. Samozřejmě jsou možné ruční korekce a toto je jen doporučení, ale aspoň trochu “inteligentní” jsem to chtěl udělat a neodpustil jsem si to.

Veškeré tohle hraní bylo bohužel poměrně časově náročné, takže víc novinek v projektu nemám a a zřejmě se teď budu zase chvíli věnovat překladům.

Pokud byste měli nějaký poznatek, nápad na vylepšení, chtěli nahlásit bug, tak můžete klasicky na Canny nebo zde.

Screen_Recording_20250630_090326-ezgif.com-optimize

Vývojářský deníček #4 - iOS

Na Androidu už je Shooting Companion nějakou dobu doma, zbývalo ale dostat se na iOS. K tomu mi ale chyběl hardware – bez něj totiž bohužel build na jablečnou platformu nejde.
Když se mi vrátily peníze z reklamace jedné pušky, rozhodl jsem se je zainvestovat do MacBooku a zaplacení vývojářských poplatků. Radši bych si asi koupil novou flintu… ale bez téhle investice by se Companion na iOS nikdy nedostal. Nakonec – železo jako železo i když pušku bych asi radši. Co se dá dělat…

Ještě první večer se mi podařilo vytvořit funkční build a Companion se poprvé rozběhl na jablečné platformě. Následovala hromada ladění a bolehlavů.
Když aplikace běžela jen na telefonu přes kabel z počítače, všechno fungovalo. Jakmile jsem ale build nahrál do TestFlightu, optimalizační procesy v Xcode ho oholily o „zbytečné“ reference a přestalo fungovat automatické rozpoznávání zásahů.
I tohle se nakonec podařilo vyřešit – a tak vyšla první verze v TestFlightu (47).

Co je nového v 1.8.3 (48)

Aplikaci teď na iOS testují desítky lidí a na základě první zpětné vazby jsem začal ladit a upravovat:


Změny na domovské obrazovce

Zrušený AppBar a přesun tlačítka pro nastavení do pravého horního rohu.
→ Mělo by to ušetřit místo a snížit nutnost scrollování.

Pohodlnější zadávání vzdáleností

Změna textového vstupu pro vzdálenost střelby a referenční vzdálenost:
Po kliknutí se automaticky označí celý text a je připravený k přepsání,
Aktivuje se pokročilejší klávesnice s potvrzovacím tlačítkem.

ScreenRecording_07-04-202511-42-12_1-ezgif.com-video-to-gif-converter

Radarová data – nová logika

Data z radaru se nově přiřazují ke konkrétnímu terči, ne ke střelivu.
Dříve se chrono session ukládala k náboji – teď může být propojena s konkrétním terčem.
U náboje se stále zobrazuje průměrná hodnota, ale počítaná z terčů, které s daným nábojem souvisí a mají přiřazená radarová data.
Na obrazovce náboje se dá zobrazit, z jakých hodnot se průměr počítá.

(Na screenshotech jsou ilustrační data: chrono session z .44 Magnum přiřazená k .308 Win)



To je prozatím vše z update 48 – díky všem testerům za zpětnou vazbu.
Pokud jste v iOS betě a chcete přidat postřeh, můžete buď do Canny, nebo přes e-mail.

Do tohohdle testu se mi popravdě moc nechtělo. Naprosto jsem si uvědomoval, že se ukáže, jak jsou pevné základy projektu a jestli vše sedí jak má.

Plán byl jednoduchý, na telefonu s Androidem provést anotaci několika terčů.


Následně udělat přes volbu v menu backup dat a zálohu odeslat na Dropbox.
(Mimochodem, zálohy jsou nově možné i v tzv. sezonách. Předpokládám, že data aplikace mohou nabýt větších rozměrů s větším množstvím fotek. Proto jde v menu nově zvolit “Export po sezonách”). V podstatě jde o export po jednotlivých rocích.

Zálohovací algoritmus si osahá záznamy v aplikaci a nabídne časové rozpětí dle uložených dat. Pak se zvolí rok a při zálohování jsou zálohovány jen data za toto časové období. Můžu si tedy tak vybrat pohodlně třeba jen terče za rok 2025

Smysl testu spočíval v tom, že zálohu dat vytvořenou na jednom zařízení obnovím na úplně jiném zařízení. A tak jsem provedl import zálohy na iPhone 16e

Výsledek mne velmi potěšil. Anotace jsou na svých místech stejně jako body zásahů a další aktivně vykreslované prvky. Companion anotace natvrdo vypaluje do obrázkových dat terčů až při anotaci. Díky tomu jsou i uložené terče editovatelné, lze tak i u uloženého terče libovolně měnit zobrazení, ovlivnit které prvky se vykreslí.


Když už jsem v tom byl, vyzkoušel jsem i nativní build pro macOS a obnovil androidi data i tady, je vidět že označení zásahů atd sedí.

Proč je tohle tak zásadní? Pokud například dojde k výměně zařízení na kterém uživatel Shooting Companiona používá, nemusí se tak bát, že by byla data dříve pořízená na novém telefonu nečitelná.

Do budoucna si ještě pohrávám s myšlenkou, že bych proces exportu zálohy doplnil o QR kód a nějakou formu přenosu do druhého zařízení airdropem nebo podobným řešením. Uvidím kam se to vyvine a jestli bude mít smysl tomu věnovat čas.