18 KiB
18 KiB
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 (для владельца)
- Errata Ф-2.3 / Ф-2.1 — границы подхода. «Штатного события
Strength Set» в Connect IQ API нет (проверено по актуальному API:
классов повторений не существует ни в одной версии платформы —
родная детекция повторений «Силовой» стороннему коду недоступна).
Рекомендация: границы подхода = между нажатиями Lap (штатная
семантика «Силовой»: Lap — конец подхода, метки в
.fitсохраняются, КУ-2 жив). «Время подхода» — интервал с последнего Lap (включает предшествующий отдых; точно «под нагрузкой» не измерить), «средний пульс подхода» — среднее за интервал. Отвергнутая альтернатива: эвристика «начало подхода = рост пульса» — ненадёжна (зал, интервалы отдыха разные). Пакет errata НД — module_reqs разд. 5, вносится после «утверждаю». - Toolchain. Агент устанавливает Connect IQ SDK для Windows
(актуальная 9.2; SDK Manager — zip с developer.garmin.com) в
C:\toolsпо прецеденту m09 (JDK 21 уже стоит). Сборка — CLImonkeyc; смок — симулятор SDK; приёмка — реальный Fenix 6X (ui-ux: симулятор только для разработки). - Настройки поля на устройстве. Стандартные properties поля
(
restSec,hrMaxBpm,age) на реальном устройстве редактируются только через Garmin Connect Mobile/Express для приложений из магазина Connect IQ; sideload-дев-сборка живёт на зашитых умолчаниях (120 с и т.д.). Смена поведения в v1 = пересборка агентом. Опция владельца: публикация поля приватной бетой в магазине (бесплатный Garmin-аккаунт разработчика) — даёт правку настроек в GCM; в границы v1 не входит. - Таргетная матрица v1. Собираем только
fenix6x(якорь владельца); макет параметрический на семейство квадратных MIP — fenix 6 (260×260) / 6S (240×240) добавляются строкой таргета без правок кода (tech-req ОВ-7 «по фактическому парку», указание 2026-10-19 о лёгкой сборке под другие часы). - Красная зона на часах — процентная (Ф-2.2: > 85 % от
maxBpmполя), а не абсолютныйSafety.HrStrengthMax= 120 телефона: часам абсолютный порог неизвестен (передать нельзя — канал односторонний), по НД у часов процентная норма. Зоны настраиваются вручную в поле (hrMaxBpm/age), синхронизация с профилем телефона — открытый вопрос 3 (v2).
Примечания по ходу работ
- Исследование 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 Managerdeveloper.garmin.com/downloads/connect-iq/sdk-manager/connectiq-sdk-manager-windows.zip. - Расположение проекта —
3-app\5-watch\FenixDataField(продолжение нумерации 1-lib/2-cli/3-web/4-phone); «5-watch» — место будущих полей/приложений под другие часы (мультичасовая инфраструктура). - Волна 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. - Тулчейн фактически (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). - 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— подписи им больше не собираются. - Тесты: собственный раннер вместо
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, на результаты не влияет. - Смок поля в симуляторе — ограничение среды. Симулятор 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 без правок кода.
- Мультитаргет-инвариант подтверждён: fenix6 (260×260) и fenix6s
(240×240) — release и тестовые prg собираются только заменой
<iq:product>в манифесте (правки кода — нулевые; проверочные манифесты во временной папке, в репо не попадают). Симулятор 9.2 в контуре не используется (отвергает подписи нашего пака); если понадобится — отдельное исследование (sdk-settings.json симулятора). - Monkey C-ловушки, пойманные тестами:
==для строк — по ссылке (литерал ≠ собранная строка; сверятьLang.String.equals);число + строкане склеивается — конкатенация только со строки ("" + x + …); дефолтная джунгла компилирует.\**.mcрекурсивно — джунглы проекта обязаны задаватьbase.sourcePathявно (иначе test-source попадает в release). - Сборка/прогон (команды). Сборка:
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 (приёмка владельца)
- На часах включить режим разработчика: Settings → System → Developer Mode → On (перезагрузка по запросу).
- Подключить часы по USB (режим MTP), открыть диск GARMIN.
- Скопировать
FenixDataField.prgвGARMIN\APPS\DataField\(если папки нет — создать; вариант совместимости —GARMIN\APPS\WatchApp\). - Отсоединить USB. Профиль Strength (Силовая) → настройки тренировки → Data Screens → страница → Data Field 1 → Феникс (Phoenix).
- Проверки: пульс крупно + плашка зоны с подписью; Lap (кнопка
BACK/LAP на 6X) — строка «ОТДЫХ 2:00» тикает вниз, по нулю —
короткая вибрация; пульс > 85 % maxBpm (умолчание Танака 45 лет =
176) — двойная вибрация не чаще раза в минуту; пауза активности —
отсчёты стоят; без нагрудного датчика/оптического пульса — «—»,
поле не падает. Настройки
restSec/hrMaxBpm/ageв dev-сборке — зашитые умолчания (решение 3 гейта 1.3). - Удаление: часы → Settings → System → Storage → Connect IQ /
GARMIN\APPS\DataField\FenixDataField.prgвручную.