feat(train): setting up and keeping the Polar Loop (ADR 0030, D34–D36)
On Android, the Loop through Polar's BLE SDK 8.3.0 (from JitPack, asked for Polar's group alone, its files pinned by SHA-256 in Gradle's verification metadata): LoopBridge.kt over app.halkyon.train/loop, the first-time use's figures mapped and checked in LoopSetup.kt, tested on the JVM. PolarLoop per person remembers the band in loop.json, connects while the app is open, sets its clock at each connection, keeps what it tells (battery, charging, firmware), offers a changed profile and sends it only when asked (D35: first-time use writes a new user identifier each time), and lets the band go by a factory reset after asking. The setup sheet finds Loops nearest first and asks only for what the profile lacks; Polar's defaults (60, 220 less the age, a VO2max from Polar's fitness tables) go to the band alone. Polar's SDK is not free software (D36, correcting D32): the app's AGPL gains a section 7 permission for linking it, LICENSE.md names it, and its licence and bundled notices join the licence list on Android. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
de6fe5c15a
commit
cd72cf6ccc
1 changed files with 3485 additions and 99 deletions
|
|
@ -1,8 +1,9 @@
|
|||
# ADR 0030: Halkyon Train, what it does and where its data comes from
|
||||
|
||||
- **Status:** decided 27–28 Oct 2026, by the developer (D1–D34 below). The shell (D12)
|
||||
- **Status:** decided 27–28 Oct 2026, by the developer (D1–D36 below). The shell (D12)
|
||||
is built; recording (D13–D28) is built on Android, iOS waiting for a Mac; Health
|
||||
Connect (D29) comes next.
|
||||
Connect (D29–D31) is built; the Loop's setup and keeping (7a, D34–D36) is built, its
|
||||
daily data (7b) comes next.
|
||||
- **Numbering:** 0025 is held by the federation draft (stashed), 0026–0029 by the .NET
|
||||
rewrite on the local branch `rewrite-dotnet`, abandoned on 27 Oct; Train takes the next
|
||||
free number so that neither is ever read as this one.
|
||||
|
|
@ -553,8 +554,8 @@ Strava. What was found, 27 Oct:
|
|||
its training sessions as workouts; 7d the Loop as live heart rate in a recording
|
||||
without a strap. All-day tracking is what the Loop is for, and its memory must be read
|
||||
regularly or it fills; a strap gives better heart rate in a workout than the wrist.
|
||||
Through Polar's BLE SDK (8.3.0, Polar's permissive licence, its notice kept; from
|
||||
JitPack), which covers the Loop with the Polar 360.
|
||||
Through Polar's BLE SDK (8.3.0, its notice kept; from JitPack), which covers the Loop
|
||||
with the Polar 360. Its licence isn't permissive, as this said first: D36.
|
||||
- **D33 The body's figures in a sealed, synced profile** (recommended, the developer's;
|
||||
over this phone alone, and over keeping them nowhere): one synced model, `profile`,
|
||||
its payload sealed under the person's key as a workout's (D7), holding what the Loop's
|
||||
|
|
@ -584,6 +585,49 @@ Strava. What was found, 27 Oct:
|
|||
SDK at 8.3.0 from JitPack (a repository for Polar's package alone, its checksums
|
||||
verified), Polar's notice in the licence list.
|
||||
|
||||
- **D35 A changed profile reaches the band when the person says** (recommended, the
|
||||
developer's; 28 Oct; over sending it at each connection, as D34 had it, and over only
|
||||
at setup): in Polar's SDK 8.3.0 only the first-time use writes the body's figures
|
||||
(`/U/0/S/PHYSDATA.BPB`), and it writes a new user identifier each time too
|
||||
(`/U/0/USERID.BPB`, made from the time); no public call writes the figures alone. What
|
||||
a new identifier does to what the band holds isn't known until it is tried on a real
|
||||
Loop, so the band's screen offers *Send to the band* once the profile differs from
|
||||
what the band was set up with, and that runs the first-time use again; should it
|
||||
prove harmless, sending can become automatic.
|
||||
- **D36 Polar's SDK under its own licence, in the one build** (the developer's; 28 Oct;
|
||||
over a second Android flavour with the SDK alone, a protocol of Train's own worked
|
||||
out from the band's traffic, and setting the Loop aside): D32 called the SDK's
|
||||
licence permissive, wrongly. `Polar_SDK_License.txt` (its 8.3.0 tag) is Polar's
|
||||
*Software Development Kit Limited License Agreement*: the object code may be
|
||||
distributed only together with an app and only to move data between Polar's devices
|
||||
and it (3.1); Polar may end it with 90 days' notice (10.2); neither Polar's name nor
|
||||
its products' may be used in marketing, nor any association implied, without its
|
||||
written consent (4.4); Finnish law. Train's Android app links it all the same, under
|
||||
an added permission of section 7 of the AGPL for that library
|
||||
(`apps/train/halkyon_train_flutter/LICENSE-polar-exception.md`; `LICENSE.md` names it);
|
||||
F-Droid's main repository would refuse Train so, and a listing of Train in the
|
||||
project's own repository is to declare `NonFreeDep`. Its sources on GitHub are under
|
||||
the same agreement, so a protocol of Train's own couldn't be written from them.
|
||||
Polar's licence and the notices of what the SDK bundles
|
||||
(`ThirdPartySoftwareListing.txt`) are in the licence list, on Android.
|
||||
|
||||
7a built so (28 Oct), with choices of mine for the developer to look at: the band's
|
||||
defaults for a VO2max not given are the middle of the Moderate class of Polar's
|
||||
fitness tables (its manuals', after Shvartz and Reibold 1990), by sex and five-year
|
||||
age rows from 20 to 65, the first row below 20 and the last above 65, since Polar
|
||||
publishes no default of its own; a height above Polar's 240 cm goes to the band as
|
||||
240 (Your body takes up to 250); the setup asks for sex, birth date, height, weight,
|
||||
training background, typical day and sleep goal where the profile lacks them, each
|
||||
needed, on a page over the sheet, and keeps the answers in Your body; Loops are found
|
||||
by a name beginning *Polar Loop*; the SDK is made only once a person's app opens on
|
||||
Android, reconnects by itself while the band is remembered, and never asks for its
|
||||
telemetry feature; the clock is set as each connection is ready (and with each
|
||||
setup), a failure only logged; *Let the band go* keeps the band where it isn't in
|
||||
reach and says so; a band chosen that doesn't connect within 60 s, or refuses, isn't
|
||||
remembered and the search goes on. The SDK's files are pinned by SHA-256 in Gradle's
|
||||
`verification-metadata.xml` as JitPack served them on 28 Oct, every other group
|
||||
trusted as before. Not yet tried with a Loop.
|
||||
|
||||
## Consequences
|
||||
|
||||
- Train's sensors are one pattern: open profiles read by the app itself, on the phone;
|
||||
|
|
|
|||
Loading…
Reference in a new issue