VEU.WathBody/1-docs/4-modules/m13-fenix-data-field/readme.md

18 KiB
Raw Permalink Blame History

m13-fenix-data-field — план работ (d-dev)

Модуль: FenixDataField — поле данных Connect IQ (Monkey C) «Феникс» в штатном профиле «Силовая»: пульс + зона, метрики подхода (Lap→Lap — errata Ф-2.3, см. module_reqs.md разд. 1.1/5), автономный таймер отдыха с вибрацией. Мультитаргет: якорь fenix6x 280×280, добавление моделей — строкой таргета. Алгоритм: std1\_rules\d\d-dev.md (адаптация: домен/функции/БД → единицы Monkey C, гейты те же). Зависимости: m12 (DONE — канал телефона не затрагивается; errata Ф-2.4 об автономном таймере — исполнение здесь). Сервер/телефон — без изменений.

Шаг Что делаем Статус
0 Модульные документы: module_reqs.md / readme.md / SKILL.md ✅ 2026-10-19
1 Список единиц (манифест/ядро×3/экран/вибрации/настройки/тесты/доставка) ✅ 2026-10-19
1.3 Пользователь! утверждение списка (+ errata Ф-2.3, toolchain, настройки-на-устройстве, таргеты) ✅ 2026-10-19 (все 5 решений утверждены)
2 Спецификации: api_specs (манифест/таргеты, ядро×3, экран, настройки/вибрации) ✅ 2026-10-19 (01-проект/манифест/сборка, 02-ядро SetTracker/RestTimer/ZoneCalc, 03-экран, 04-настройки/вибрации)
2.4 Пользователь! утверждение спецификаций ✅ 2026-10-19 (утверждены 4 api_specs)
3 Реализация + тесты + сборка таргетов + симулятор ✅ 2026-10-19 (сборки 3 таргетов; тесты 54/54; смок-в-симуляторе ограничен средой — примечания 5–6)
3.4 Пользователь! утверждение реализации (закрытие модуля) ✅ 2026-10-19 («заккомить» — утверждение и команда коммита)
4 Завершение: план, примечания, волна errata НД ✅ 2026-10-19 (errata внесена после гейта 1.3 — примечание 2; план/примечания обновлены)

Статусы: ⬜ не начат · 🔄 в работе · ✅ готов.

Список единиц (шаг 1)

# Единица Что делает
1 Проект + манифест + таргеты 3-app\5-watch\FenixDataField: тип datafield, UUID «Феникс», minApiVersion ≤ 2.1.0; monkey.jungle — матрица таргетов (якорь fenix6x), новая модель — строка
2 SetTracker метрики подхода: время с границы (Lap), средний пульс интервала (сэмплы из compute), обнуление по onTimerLap; null-пульс пропускается
3 RestTimer автономный отдых: старт по Lap, длительность restSec (умолчание 120 = Rest.DefaultSec), обратный отсчёт, конец → однократная лёгкая вибрация; пауза активности останавливает
4 ZoneCalc зоны 50/70/85 % от maxBpm: hrMaxBpm или Танака 208−0,7×age; цвет MIP-палитры + текстовая подпись (те же названия, что на «Профиле» m10)
5 Экран поля параметрический макет семейства квадратных MIP (якоря, dc-размеры): пульс крупно (FONT_NUMBER_*), плашка зоны цветом + подпись, строка «ПОДХОД мм:сс · ср N» / «ОТДЫХ мм:сс», прочерк без пульса
6 Вибрации Attention.vibrate + VibeProfile: конец отдыха — однократная лёгкая; красная зона — двойная, гистерезис (повтор ≥ 60 с, сброс ниже жёлтой)
7 Настройки поля properties: restSec (30–600, умолчание 120), hrMaxBpm (0–250, 0 = формула), age (14–100, 45); подписи ru/en; умолчания работают без магазина
8 Тесты Toybox.Test ZoneCalc / RestTimer / SetTracker: asserts (компилируются out в release), прогон инструментарием SDK
9 Сборка и доставка monkeyc по всем таргетам; developer-ключ; инструкция sideload (developer mode + GCM) и приёмки на Fenix 6X — в этом readme

Решения на гейт 1.3 (для владельца)

  1. Errata Ф-2.3 / Ф-2.1 — границы подхода. «Штатного события Strength Set» в Connect IQ API нет (проверено по актуальному API: классов повторений не существует ни в одной версии платформы — родная детекция повторений «Силовой» стороннему коду недоступна). Рекомендация: границы подхода = между нажатиями Lap (штатная семантика «Силовой»: Lap — конец подхода, метки в .fit сохраняются, КУ-2 жив). «Время подхода» — интервал с последнего Lap (включает предшествующий отдых; точно «под нагрузкой» не измерить), «средний пульс подхода» — среднее за интервал. Отвергнутая альтернатива: эвристика «начало подхода = рост пульса» — ненадёжна (зал, интервалы отдыха разные). Пакет errata НД — module_reqs разд. 5, вносится после «утверждаю».
  2. Toolchain. Агент устанавливает Connect IQ SDK для Windows (актуальная 9.2; SDK Manager — zip с developer.garmin.com) в C:\tools по прецеденту m09 (JDK 21 уже стоит). Сборка — CLI monkeyc; смок — симулятор SDK; приёмка — реальный Fenix 6X (ui-ux: симулятор только для разработки).
  3. Настройки поля на устройстве. Стандартные properties поля (restSec, hrMaxBpm, age) на реальном устройстве редактируются только через Garmin Connect Mobile/Express для приложений из магазина Connect IQ; sideload-дев-сборка живёт на зашитых умолчаниях (120 с и т.д.). Смена поведения в v1 = пересборка агентом. Опция владельца: публикация поля приватной бетой в магазине (бесплатный Garmin-аккаунт разработчика) — даёт правку настроек в GCM; в границы v1 не входит.
  4. Таргетная матрица v1. Собираем только fenix6x (якорь владельца); макет параметрический на семейство квадратных MIP — fenix 6 (260×260) / 6S (240×240) добавляются строкой таргета без правок кода (tech-req ОВ-7 «по фактическому парку», указание 2026-10-19 о лёгкой сборке под другие часы).
  5. Красная зона на часах — процентная (Ф-2.2: > 85 % от maxBpm поля), а не абсолютный Safety.HrStrengthMax = 120 телефона: часам абсолютный порог неизвестен (передать нельзя — канал односторонний), по НД у часов процентная норма. Зоны настраиваются вручную в поле (hrMaxBpm/age), синхронизация с профилем телефона — открытый вопрос 3 (v2).

Примечания по ходу работ

  1. Исследование API (2026-10-19, веб) — обоснование errata Ф-2.3, см. module_reqs разд. 1.1: Toybox.Activity — 6 классов, повторений нет нигде (вплоть до актуального API платформы); у DataField есть onTimerLap() (API 1.3.0), compute() раз/с (currentHeartRate с 1.0.0), Attention.vibrate (1.0.0); Toybox.Test — с API 2.1.0, asserts компилируются out в release. SDK: актуальная 9.2, Windows SDK Manager developer.garmin.com/downloads/connect-iq/sdk-manager/connectiq-sdk-manager-windows.zip.
  2. Расположение проекта — 3-app\5-watch\FenixDataField (продолжение нумерации 1-lib/2-cli/3-web/4-phone); «5-watch» — место будущих полей/приложений под другие часы (мультичасовая инфраструктура).
  3. Волна errata НД внесена (2026-10-19, после «утверждаю» гейта 1.3): requirements Ф-2.1 («время с последнего Lap — точное „под нагрузкой“ не измеряется») и Ф-2.3 (границы подхода = Lap→Lap, события Strength Set в CIQ API нет); Ф-2.2 — правка не потребовалась (норма уже содержит «настройки поля», открытый вопрос 3); tech-req 7 п. 1 — дополнено «вибрация конца отдыха и метрики Lap→Lap — приёмка m13». Версии документов не поднимались (ближайшее ревью). UUID поля зафиксирован в спеке 01: 34f470ff-b5d1-4141-ad06-c483fa79a1f8.
  4. Тулчейн фактически (2026-10-19). Рабочая связка: SDK 4.2.2 (Wayback-архив zip; актуальная 9.2 скачана, но её симулятор отвергает dev-подписи нашего пака — примечание 7) + JDK 21 + девайс-паки fenix6xpro/fenix6/fenix6s из docker-образа piccobit/docker-connectiq:4.1.7 → %APPDATA%\Garmin\ConnectIQ\Devices (путь виндового стора найден декомпиляцией Monkeybrains). Идентификатор таргета — fenix6xpro (6X существует только в Pro-линии). Ключ разработчика: RSA 4096, PKCS#8 DER (C:\Users\virus-home\.watchbody\ciq\developer_key.der; PEM и 2048-битные отвергаются — см. примечание 4).
  5. Developer-ключ обязан быть RSA 4096. Симуляционная прошивка отвергала 2048-битную подпись «Signature check failed» (проверено на штатном сэмпле Garmin — падает одинаково; JDK ни при чём: сборка под Java 11 в docker даёт то же). В DeveloperSignature (monkeybrains.jar) модуль = 512 байт = 4096 бит. Ключ перегенерирован 2026-10-19; старый 2048 сохранён как developer_key2048.obsolete.der — подписи им больше не собираются.
  6. Тесты: собственный раннер вместо monkeydo /t. Штатный (:test)-harness Toybox.Test не стартует в связке «симулятор 4.2.2 + девайс-пак docker»: ЛЮБОЙ тестовый prg (включая минимальный проект из 15 строк) падает на старте «Unexpected Type Error: Failed to start CIQ Application»; поле данных, к тому же, нельзя запускать как приложение. Решение: test-source/ — watch-app-вход TestEntry (test-manifest.xml, тип watch-app) + CoreChecks (счётчик/печать) + те же 13 тестовых функций из спеки 02; тестовая сборка monkey-test.jungle (без --unit-test), прогон — monkeydo без /t, вывод println → консоль. Итог: 54/54 проверок (зоны 12, метрики подхода 6, отдых 10, вибрации 7, формат 10, клампы 9 — состав уточнён против спеки 02 числом проверок, случаи те же). Раннер отработал как положено: нашёл 3 реальных бага ядра (шкала порогов ZoneCalc ×10, лишнее слагаемое в округлении avgBpm, сборка строки mmss не со строки) — исправлены, повторный прогон зелёный. Поле данных (release, monkey.jungle) в тестовые сборки не входит. Хвостовой «app crash» после RESULT — штатный выход watch-app без view, на результаты не влияет.
  7. Смок поля в симуляторе — ограничение среды. Симулятор 4.2.2 не хостит поля данных в симулируемой активности (поле нельзя «открыть» как приложение), поэтому интерактивные проверки спеки 03 §5 (проводка пульса по зонам, Lap, пауза, вибрации глазами) — приёмка владельца на реальном Fenix 6X (прецедент m12: «на устройстве — приёмка владельца»). Поведенческое ядро этих проверок закрыто юнит-тестами: пороги всех 4 зон (границы 89/90, 125/126, 152/153 при max 180), прочерк без пульса (ZONE_NONE), обнуление по Lap + отсчёт отдыха + однократность сигнала, гистерезис красной 60 с, целочисленный mmss. Отрисовка — параметрическая, собирается под 280×280/260×260/240×240 без правок кода.
  8. Мультитаргет-инвариант подтверждён: fenix6 (260×260) и fenix6s (240×240) — release и тестовые prg собираются только заменой <iq:product> в манифесте (правки кода — нулевые; проверочные манифесты во временной папке, в репо не попадают). Симулятор 9.2 в контуре не используется (отвергает подписи нашего пака); если понадобится — отдельное исследование (sdk-settings.json симулятора).
  9. Monkey C-ловушки, пойманные тестами: == для строк — по ссылке (литерал ≠ собранная строка; сверять Lang.String.equals); число + строка не склеивается — конкатенация только со строки ("" + x + …); дефолтная джунгла компилирует .\**.mc рекурсивно — джунглы проекта обязаны задавать base.sourcePath явно (иначе test-source попадает в release).
  10. Сборка/прогон (команды). Сборка: monkeyc.bat -d fenix6xpro -w -f monkey.jungle -y <ключ> -o bin\FenixDataField.prg (тест — -f monkey-test.jungle … FenixDataField-test.prg; JAVA_HOME = JDK 21). Симулятор: bin\connectiq.bat (запуск вне песочницы), затем monkeydo.bat <prg> fenix6xpro (без /t) — юнит-вывод в консоль; лог прошивки — %TEMP%\com.garmin.connectiq\GARMIN\APPS\LOGS\CIQ_LOG.YML.

Sideload на Fenix 6X (приёмка владельца)

  1. На часах включить режим разработчика: Settings → System → Developer Mode → On (перезагрузка по запросу).
  2. Подключить часы по USB (режим MTP), открыть диск GARMIN.
  3. Скопировать FenixDataField.prg в GARMIN\APPS\DataField\ (если папки нет — создать; вариант совместимости — GARMIN\APPS\WatchApp\).
  4. Отсоединить USB. Профиль Strength (Силовая) → настройки тренировки → Data Screens → страница → Data Field 1 → Феникс (Phoenix).
  5. Проверки: пульс крупно + плашка зоны с подписью; Lap (кнопка BACK/LAP на 6X) — строка «ОТДЫХ 2:00» тикает вниз, по нулю — короткая вибрация; пульс > 85 % maxBpm (умолчание Танака 45 лет = 176) — двойная вибрация не чаще раза в минуту; пауза активности — отсчёты стоят; без нагрудного датчика/оптического пульса — «—», поле не падает. Настройки restSec/hrMaxBpm/age в dev-сборке — зашитые умолчания (решение 3 гейта 1.3).
  6. Удаление: часы → Settings → System → Storage → Connect IQ / GARMIN\APPS\DataField\FenixDataField.prg вручную.