179 lines
14 KiB
Markdown
179 lines
14 KiB
Markdown
# Требования к модулю: m13-fenix-data-field
|
||
|
||
> Модуль — **FenixDataField** (архитектура разд. 1.1): поле данных
|
||
> Connect IQ (Monkey C) «Феникс» в штатном профиле «Силовая»: текущий
|
||
> пульс + зона цветом, метрики подхода (время, средний пульс),
|
||
> автономный таймер отдыха с вибрацией. Самодостаточная копия
|
||
> требований (d-dev-6). Источники: Ф-2.1–Ф-2.8 (requirements), errata
|
||
> Ф-2.4 (m12, автономный таймер), ОВ-7 (tech-req 1, таргеты),
|
||
> tech-req 6 п. 1 (UI/UX часов), 7 п. 1 (закрытие части «таймер»
|
||
> прототипа канала), ui-ux-recommendations разд. 2.
|
||
|
||
## 1. Назначение и границы
|
||
|
||
Поле данных на часах во время силовой активности: отображает пульс,
|
||
зону и метрики подхода, вибрирует в конце отдыха и при выходе пульса
|
||
в красную зону. Только отображение и вибрации — запись `.fit` ведёт
|
||
платформа Garmin (Ф-2.7); часы полностью автономны (Ф-2.4: не
|
||
зависимость — никаких требований к телефону).
|
||
|
||
### 1.1. Границы подхода (исследование API, 2026-10-19)
|
||
|
||
Ф-2.3 предполагала границами подхода «штатное событие нового подхода
|
||
(Strength Set) → событие Lap». Проверка по актуальной документации
|
||
Connect IQ API (вплоть до текущей версии платформы):
|
||
|
||
1. **События/данных повторений в Connect IQ API нет** — ни в
|
||
`Toybox.Activity` (6 классов: Info, ProfileInfo, SplitInfo,
|
||
WorkoutStep…; у `Activity.Info` нет полей сетов/повторов), ни
|
||
отдельным модулем; классов повторений нет в общем списке классов.
|
||
Это не ограничение fenix 6X — API не существует ни в одной версии
|
||
платформы: штатная детекция повторений «Силовой» сторонним кодом
|
||
недоступна.
|
||
2. **Доступно полю данных:** `compute(info as Activity.Info)` — раз
|
||
в секунду (`currentHeartRate` — Number|Null, API 1.0.0);
|
||
`onTimerLap()` — нажатие кнопки Lap (API 1.3.0); таймерные
|
||
колбэки `onTimerStart/Stop/Pause/Resume/Reset` (API 1.3.0);
|
||
`Attention.vibrate([VibeProfile(duty, мс)])` — до 8 профилей
|
||
подряд, поля данных поддержаны (API 1.0.0); собственная разметка
|
||
экрана (`onLayout` + отрисовка `dc`, параметрическая по
|
||
`dc.getWidth/getHeight`).
|
||
3. **Решение v1 (errata Ф-2.3, разд. 5):** границы подхода = между
|
||
нажатиями Lap — штатная семантика «Силовой» (Lap жмётся в конце
|
||
подхода, метки попадают в `.fit`, КУ-2 сохраняется). «Время
|
||
подхода» = интервал с последнего Lap (включает предшествующий
|
||
отдых — точное время «под нагрузкой» без детекции повторений
|
||
не измеряется); «средний пульс подхода» = среднее
|
||
`currentHeartRate` за тот же интервал. Lap обнуляет метрики и
|
||
стартует таймер отдыха.
|
||
|
||
**В границах модуля:**
|
||
|
||
- **проект Monkey C** `3-app\5-watch\FenixDataField`: манифест (тип
|
||
datafield, UUID, `minApiVersion` — не выше 2.1.0, чтобы поле
|
||
ставилось и на старые CIQ-устройства), таргетная матрица
|
||
`monkey.jungle` — якорь `fenix6x` (280×280); добавление модели —
|
||
строка таргета, код и макет не меняются (мультитаргет-инфраструктура,
|
||
указание владельца 2026-10-19);
|
||
- **ядро (чистые классы Monkey C, без UI):**
|
||
- `SetTracker` — метрики подхода: время с границы (Lap), средний
|
||
пульс интервала (накопление сэмплов из `compute`), обнуление по
|
||
`onTimerLap`; null-пульс пропускается;
|
||
- `RestTimer` — автономный таймер отдыха: старт по Lap,
|
||
длительность из настройки `restSec` (умолчание 120 =
|
||
`Rest.DefaultSec` телефона), обратный отсчёт, конец → вибрация;
|
||
пауза активности (`onTimerPause/Resume`) останавливает/ведёт
|
||
дальше;
|
||
- `ZoneCalc` — зоны от `maxBpm`: < 50 % синяя (recovery), 50–70 %
|
||
зелёная, 70–85 % жёлтая, > 85 % красная; `maxBpm` из настройки
|
||
`hrMaxBpm`, не задана (0) — формула Танаки
|
||
`208 − 0,7 × возраст` (настройка `age`); возвращает цвет
|
||
(MIP-палитра) и текстовую подпись зоны;
|
||
- **экран поля** — параметрическая разметка семейства квадратных
|
||
MIP-экранов (якоря + размеры от `dc`, без фиксированных
|
||
координат под конкретную модель): текущий пульс — крупнейшее
|
||
число (`FONT_NUMBER_*`), плашка/ободок зоны цветом + подпись зоны
|
||
текстом (цвет — не единственный носитель), строка состояния
|
||
«ПОДХОД мм:сс · ср N» / «ОТДЫХ мм:сс» (обратный отсчёт), прочерк
|
||
при отсутствии пульса;
|
||
- **вибрации:** конец отдыха — однократная лёгкая; красная зона —
|
||
двойная с гистерезисом (повторная не раньше 60 с, сброс при
|
||
возврате в жёлтую зону);
|
||
- **настройки поля** (стандартные properties, settings.xml):
|
||
`restSec` (30–600, умолчание 120), `hrMaxBpm` (0–250, умолчание
|
||
0 = расчёт по формуле), `age` (14–100, умолчание 45), подписи
|
||
ru/en; умолчания зашиты в сборку — работают без магазина;
|
||
- **тесты Toybox.Test** (модуль есть с API 2.1.0; asserts
|
||
компилируются out в release): зоны, таймер отдыха, трекер
|
||
подхода; прогон инструментарием SDK;
|
||
- **сборка и доставка:** `monkeyc` по всем таргетам без ошибок,
|
||
подпись developer-ключом, инструкция sideload на Fenix 6X
|
||
(developer mode + Garmin Connect Mobile) — в readme модуля.
|
||
|
||
**Вне границ модуля:** запись `.fit` (платформа Garmin), сетевой
|
||
обмен из поля (`Communications` на fenix 6X недоступен полям данных —
|
||
errata ОВ-3 m12; канал живого пульса — m12, BLE-трансляция),
|
||
редактирование настроек на часах (поля данных не имеют собственных
|
||
экранов настроек), публикация в магазине Connect IQ (опция владельца
|
||
— см. решение 3 гейта 1.3), добавление таргетов fenix6/6S (по
|
||
фактическому парку — строка конфигурации), пульс-оповещения
|
||
Safety.HrStrengthMax (абсолютный порог 120 — телефон, Ф-3/Ф-13;
|
||
часы красят по процентам Ф-2.2).
|
||
|
||
## 2. Решения интерфейса (ui-ux разд. 2, tech-req 6 п. 1)
|
||
|
||
- Один экран-поле, читается за 1–2 с (glanceable): пульс — главное
|
||
число; всё остальное — строкой состояния мельче.
|
||
- Семантика кнопок не меняется: Lap — конец подхода (штатно),
|
||
Start/Stop — пауза/стоп активности; поле не требует ни одного
|
||
нажатия и не перехватывает кнопки (Ф-2.5, Ф-2.6).
|
||
- Цвет зоны дублируется подписью (recovery/лёгкая/средняя/высокая —
|
||
те же названия, что на «Профиле» телефона m10).
|
||
- MIP-экран: тёмный фон, высокий контраст, крупные шрифты
|
||
(`FONT_NUMBER_*` для пульса), 64-цветная палитра; читаемость на
|
||
солнце не требует подсветки.
|
||
- Нет пульса (датчик не готов / null) — прочерк «—», остальное
|
||
живое; поле не падает (Ф-2.8).
|
||
|
||
## 3. Инварианты (🛡 — нарушать запрещено)
|
||
|
||
1. **Поле не пишет в сеть и не хранит историю** (Ф-2.7): только
|
||
отображение и вибрации; запись активности ведёт платформа Garmin.
|
||
2. **Кнопки не перехватываются** (Ф-2.5, Ф-2.6): Lap/Start/Stop —
|
||
штатная обработка; поле не блокирует паузу, остановку и
|
||
сохранение активности.
|
||
3. **Часы автономны** (Ф-2.4): поле не требует телефона и никак его
|
||
не вызывает; работа поля не зависит от наличия связи с чем бы то
|
||
ни было.
|
||
4. **Отсутствующая функция молча пропускается** (Ф-2.8): нет
|
||
пульса — прочерк; вибрация недоступна на модели — просто не
|
||
вызывается; поле не падает.
|
||
5. **Один исходный код** (Ф-2.8, указание владельца 2026-10-19):
|
||
функциональное поведение одинаково на всех таргетах; разметка —
|
||
параметрический макет семейства экранов; добавление модели часов
|
||
— конфигурация сборки без правок кода.
|
||
6. **Секретов нет:** поле ничего не передаёт — ключей, паролей и
|
||
персональных данных в коде/настройках нет (настройки — возраст,
|
||
макс. ЧСС, отдых).
|
||
|
||
## 4. Критерии приёмки модуля
|
||
|
||
1. `monkeyc` собирает все таргеты матрицы без ошибок и предупреждений
|
||
(кроме подавленных обоснованно); тесты `Toybox.Test` зелёные
|
||
(зоны, таймер отдыха, метрики подхода).
|
||
2. Симулятор Connect IQ: поле добавляется в профиль Strength;
|
||
пульс/зона/строка подхода отображаются и обновляются раз в
|
||
секунду; Lap обнуляет метрики и запускает отдых; вибрации
|
||
вызываются (видно в логе симулятора).
|
||
3. Приёмка на устройстве владельца (Fenix 6X, якорь): sideload
|
||
dev-сборки; «Силовая» с полем «Феникс»: пульс и зона на экране,
|
||
Lap — граница подхода, вибрация конца отдыха, двойная вибрация
|
||
в красной зоне; метки Lap присутствуют в `.fit` выгрузки Garmin
|
||
Connect (проверяется импортом m06/консолью m08).
|
||
4. Деградация: без пульс-данных — прочерк, поле живое; пауза
|
||
активности — таймер стоит; модель без вибрации — остальное
|
||
работает (Ф-2.8, смок владельца на имеющемся парке).
|
||
|
||
## 5. Errata НД (по утверждении гейта 1.3; ВНЕСЕНА 2026-10-19)
|
||
|
||
- requirements **Ф-2.1**: «время текущего подхода (под нагрузкой)» →
|
||
«время с последнего Lap (границы подхода — Ф-2.3; включает
|
||
предшествующий отдых — точное время „под нагрузкой“ не измеряется:
|
||
детекция повторений недоступна Connect IQ API, errata 2026-10-19)»;
|
||
- requirements **Ф-2.3**: «от штатного события нового подхода
|
||
(Strength Set) до события Lap» → «между нажатиями кнопки Lap
|
||
(штатная семантика „Силовой“: Lap — конец подхода, метки Lap
|
||
попадают в .fit, КУ-2): событие Strength Set в Connect IQ API
|
||
отсутствует (errata 2026-10-19 — класса повторений нет ни в одной
|
||
версии платформы, проверено по актуальному API); метрики подхода
|
||
считаются за интервал Lap→Lap и обнуляются на Lap»;
|
||
- requirements **Ф-2.2** — правка не потребовалась: норма уже
|
||
содержит «границы — из настроек поля данных (Connect IQ settings;
|
||
автоматическая передача с телефона — открытый вопрос 3)»;
|
||
- tech-requirements **7 п. 1**: дополнено «вибрация конца отдыха и
|
||
метрики подхода Lap→Lap — приёмка m13».
|
||
|
||
Волна внесена одним пакетом после «утверждаю» гейта 1.3 (без подъёма
|
||
версий документов — errata в телах разделов, версии поднимутся на
|
||
ближайшем ревью; прецедент — волна m12).
|