Första testets uteblivna sammansättning berodde på att kroppsdatan inte var ifylld — varningen var för diskret. Nu röd/tydlig med hänvisning till Profil → Kroppsdata. Doc-noten rättad så orsaken inte påstås vara ramtiming (merge-logiken finns kvar som robusthet). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C2GA94E1f3cmrvdQLQhYdg
7.3 KiB
openScale BT-vågar — integrationsplan
Bygga in openScale:s Bluetooth- drivrutiner i FitnessDroid så att vägningar (vikt + %muskler/fett/vatten) kan hämtas direkt från en BT-våg in i appens kroppsmätningar.
Beslut (2026-07-26)
- Licens: FitnessDroid relicensas till GPL-3.0. openScale är GPL-3.0; att bädda in deras kod kräver att hela appen blir GPL-3.0. LICENSE byts, och källfilerna som kommer från openScale behåller sina copyright-headers.
- Alla drivrutiner portas (hela
core/bluetooth-paketet, ~55 handlers + adaptrar), inte bara en modell.ScaleFactoryauto-detekterar vågen vid skanning precis som i openScale. - Attribution: en About-vy under Profil som anger att appen använder openScales drivrutiner, med länk till deras GitHub och GPL-3.0-licensen, plus en lista på öppen källkod som används (openScale, Blessed-Kotlin).
Teknik (bekräftat från repot)
- openScale använder Blessed-Kotlin (coroutine-BLE-wrapper) — läggs till som Gradle-beroende; vi portar drivrutinerna som ligger ovanpå, inte BLE-plumbingen.
ScaleDeviceHandler.supportFor(device)→DeviceSupport(displayName, linkMode, tuningProfile).ScaleFactoryreturnerar första matchande handler.- Tre kopplingslägen:
CONNECT_GATT,BROADCAST_ONLY,CLASSIC_SPPmed var sin adapter (Gatt/Broadcast/Spp). ScaleMeasurementbär weight, fat, water, muscle, visceralFat, bone, lbm, bmr, protein, impedance m.m. → vi mappar weight + muscle/fat/water till vårBodyMeasurement(resten kan tas in senare).- minSdk 31 matchar vår app (BLE-permissions
BLUETOOTH_SCAN/_CONNECT).
Fallgrop: impedansvågar behöver användarprofil
Vissa vågar skickar bara rå impedans; openScale räknar då själv ut fett/muskler/vatten med en formel som kräver längd, ålder, kön (ScaleUser). Vi måste därför:
- Lägga till längd/födelseår/kön i profilen (se API-ändring nedan).
- Porta openScales BIA-beräkning för de vågar som kräver den. Vågar som räknar ombord och skickar färdiga procent behöver inte detta.
API-ändring: spara användarens längd (+ ålder/kön)
Längden ska sparas på servern (gym-API:t) så att den är gemensam för app och webb, överlever ominstallation, och kan användas för mer korrekta beräkningar:
- BIA/kroppssammansättning: openScales formler för impedansvågar kräver längd (+ ålder + kön) för att ge korrekta %fett/muskler/vatten.
- Energiförbrukning: med längd (+ ålder + kön) kan kaloriberäkningen gå
från ren MET × vikt × tid till en BMR-baserad uppskattning
(Mifflin–St Jeor:
10·vikt + 6.25·längd − 5·ålder + könskonstant), vilket ger rimligare siffror per pass.
Backend (brasse-pc.eu-v2, gym-api):
- Utöka
UsermedHeightCm(double?), och för full BIA ävenBirthDate(ellerBirthYear) ochSex(enum/sträng). Nullable + bakåtkompatibla. - Migration (körs automatiskt vid uppstart, samma mönster som
BodyMeasurement). - Exponera i
myProfile-query och enupdateProfile-mutation (eller utökaupdateBodyWeight→updateProfilemed längd/ålder/kön). - Deploya om gym-api-prod + -test (serialiserat bygge, se pi5-ci-concurrency).
App: profil-fält för längd (och ålder/kön) som läser/skriver mot API:t; cachas lokalt (som kroppsvikten) för offline och för BIA-beräkningen.
Webb (brasse-pc.eu-v2): samma fält på profil-fliken via updateProfile.
Användarens våg (identifierad 2026-08-23)
Biltema 84-1002 "Bluetooth Analyser Scale", modell PT-727 (Ningbo Putian).
Annonserar som BLE-namnet "VScale" (verifierat med bluetoothctl på
brasse-linux01: Device C4:BE:84:79:D0:6C VScale) → openScales
ExingtechY1Handler matchar (exakt namnmatch vscale).
Protokoll (GATT): appen skriver [0x10, userId, kön, ålder, längd_cm] till
vågen; vågen räknar ut kroppssammansättningen ombord och notifierar en
20-bytes-ram (vikt, fett-%, vatten-%, muskel-%, benmassa kg, bukfettsindex).
Ingen BIA-formel behövs i appen — men längd/födelseår/kön måste finnas.
Lärdom från första testet (2026-08-23): utan ifylld kroppsdata (längd/födelseår/kön) skickar vågen bara vikt — sammansättningen uteblir tyst. Väg-skärmen varnar numera tydligt när kroppsdata saknas, och håller dessutom anslutningen öppen och mergar ramar (vågen kan skicka vikten först och sammansättningen i en senare ram; max 20 s väntan).
Hårdvarudetaljer från GATT-dump (openScales debug-läge): tillverkarsträng
"VTrump", modellnummer V300B1000001 — dvs. en VTrump-OEM. Notify-
tecknet 1a2ea400… ligger i service 78667579-7b48… (inte i f433bd80… som
klassiska Y1), och f433bd80… har ett extra notify-tecken 23b4fec0….
Fungerar ändå med ExingtechY1Handler — bra att veta vid framtida felsökning.
Milstolpar (byggbara steg)
- Grund + licens + About (klar 2026-08-23) — LICENSE → GPL-3.0;
blessed-kotlin3.0.12 via JitPack (krävde Kotlin 2.0.21→2.2.0, KSP2, Room 2.7.2); BLE-permissions (BLUETOOTH_SCANneverForLocation +BLUETOOTH_CONNECT); About-vy under Profil med GPL-attribution. - Porta bluetooth-paketet (grund) (klar 2026-08-23) — vendrat
com.health.openscale.core.bluetoothmed copyright-headers kvar: ScaleDeviceHandler, Gatt/Broadcast/Spp-adaptrar, ScaleFactory (utan Hilt), ScaleCommunicator, BleScanner, ConverterUtils, ScaleMeasurement/ScaleUser, samt ExingtechY1Handler. Shims i samma paketnamn för openScales interna beroenden (facades → DataStore, slimmade enums, LogManager → logcat), så fler drivrutiner kan portas nästan rakt av. Kvar: resterande ~59 handlers + libs/ portas allteftersom. - Skanna + koppla (klar 2026-08-23) — Inställningar → Bluetooth-våg: BLE-skanning, vågar med drivrutinsstöd överst (drivrutinsnamn visas), spara/ta bort vald våg. Runtime-permission-flöde.
- Väg dig-flöde (klar och verifierad mot Biltema-vågen 2026-08-23) — knapp i
profilen → väg-skärm med livestatus, resultat och spara via
addBodyMeasurement. Kroppsdata (längd/födelseår/kön) i profilen skickas till vågen. Vikt + muskel/fett/vatten-% bekräftade end-to-end. - API: längd (+ ålder/kön) — utöka gym-API:ts
UsermedHeightCm(+BirthDate/Sex), migration,myProfile+updateProfile, deploy. App + webb får profilfält; appens lokala kroppsdata börjar synka mot API:t. Se "API-ändring" ovan. - Fler drivrutiner + impedansvågar + bättre kalorier — porta resterande
handlers +
libs/(BIA-beräkningar för vågar som skickar rå impedans), och BMR-baserad energiförbrukning. - Polering + docs — felhantering, timeouts, ominställning av våg; uppdatera README/wiki + infra-Doc (GPL-relicens noterad).
Öppna frågor / risker
Vilken våg du har→ Biltema PT-727 = Exingtech Y1 ("VScale"), räknar ombord — milstolpe 6:s BIA behövs inte för den.Blessed-Kotlins koordinater→com.github.weliem:blessed-kotlin:3.0.12(JitPack). Byggd med Kotlin 2.2 → tvingade upp projektets Kotlin/KSP/Room.- APK växer (drivrutiner + BLE-lib) — troligen någon MB, oproblematiskt.
- GPL-relicens är permanent för koden; medvetet val.
Väg-flödet är obekräftat→ verifierat mot Biltema-vågen 2026-08-23 (vikt + sammansättning).