# 📐 Стандарт компонента firmware/Components


## Архитектура кода

- **Один класс-драйвер на компонент**: `include/<Name>.h` + `src/<Name>.cpp`. Без фасадов/обёрток из свободных функций поверх класса, аудитория школьники — упрощай публичный API самого класса (короткие геттеры, разумные значения по умолчанию), а не добавляй второй слой.
- **Dependency Injection** шины через конструктор с значением по умолчанию: `Driver(TwoWire &wire = Wire, ...)` / `Driver(HardwareSerial &serial = Serial2)`.
- **Структура `Data`** для возвращаемых значений, если полей больше 2-3; `getData()` возвращает `const Data&`.
- **Именованные константы**: адреса регистров, индексы полей, пороги — `constexpr`/`enum class` с комментарием об источнике числа (даташит, раздел/страница). Никаких magic numbers в теле методов.
- **Doxygen-комментарии** (`/** @brief ... @param ... @return ... */`) на каждый публичный метод.
- **Проверка кода возврата** каждой транзакции шины (`endTransmission()`, `requestFrom()` и т.п.) — не глотать ошибки молча.
- **Вотчдог связи**: `bool isAlive(unsigned long timeoutMs = ...) const`, обновляющий метку времени при каждом успешном обмене с датчиком и сравнивающий с `millis()`. Обязателен всегда — обрыв провода должен быть заметен, а не тихо зависать в устаревших данных.
- **Защита от вырожденных входных параметров** (0, отрицательные значения count/timeout и т.п.), если они могут дать деление на ноль или UB.
- **`src/main.cpp`** — тестовый стенд: единственный экземпляр драйвера, диагностика в человеко-читаемом формате, включая статус `isAlive()`.
- **FreeRTOS-задача** — только если реально нужна изоляция от Serial-задержек или частота опроса высокая (>~50 Гц). Приоритет — чуть выше `loop()` (priority 1), заметно ниже системных задач Wi-Fi/BT (обычно ~18-23), само число обосновано комментарием. Не задирать приоритет "с запасом" без измерений — это риск замять системные таски и словить сброс по watchdog.

## Документация — два допустимых формата

**A. «Триада + презентация»** — для полноценных компонентов с богатой теорией:
`README.md`, `THEORY.md` (физика/формулы), `WIRING.md` (подключение), `Lesson.md` (методический план урока (или уроков, если тема требует расширенного предоствления информации) для учителя).

Имена файлов — **строго** из этого списка (латиницей): `README.md`, `THEORY.md`,
`WIRING.md`, `GUIDE.md`, `Lesson.md`, `ROADMAP.md`, `PREZ.md`. Шорткод сайта
собирает вкладки по этим именам, читая каталог с диска: файл с другим именем
(или кириллицей в имени) просто не попадёт на сайт — молча, без ошибки сборки.
Порядок и подписи вкладок задаются одним списком в
`layouts/shortcodes/firmware-tabs.html`; отсутствующий файл не ломает сборку,
а лишь убирает свою вкладку. Подробности — в `ARCHITECTURE.md` в корне репозитория.

Общие требования к тексту документации, независимо от формата:
- Целевой уровень — школьник 14-17 лет: термин объясняется до первого использования, без непояснённого жаргона.
- Теория привязывается к реальным строчкам кода ЭТОГО компонента (файл:строка), а не к абстрактным примерам.
- Никакого раздутого маркетингового тона и притянутых "промышленных" аналогий не по теме — если пример не помогает понять код или физику, его не должно быть.
- Не дублируй контент между файлами — если факт уже объяснён в одном файле, в другом на него ссылаются, а не повторяют.
- используй самые передовые педагогические технологии преподавания и подачи материала. Делай материал живым, интересным и увлекательным

## Известные репозиторий-специфичные нюансы

- Окружение `esp32c6` может падать на конфликте макроса `Serial`/`USBSerial` в ядре Arduino (`#define Serial USBSerial` в `HardwareSerial.h`) — это баг фреймворка, не конкретного компонента. Если сборка `esp32c6` падает с этой ошибкой, подтверди через `git stash` + пересборку, что это не твоя регрессия, прежде чем чинить или списывать на неисправность своего кода.


## Процесс работы над новым компонентом

1. Изучи датащит/материалы, задай уточняющие вопросы по неоднозначным местам (диапазоны, единицы измерения, edge-cases) — не додумывай значения.
2. Реализуй драйвер + тестовый стенд по правилам архитектуры выше.
3. Собери одно окружения (`pio run -e esp32dev`), покажи результат.
4. Напиши документацию — файлами с именами из списка выше, в каталоге компонента.
5. Заведи страницу сайта `content/docs/<та же категория>/<тот же компонент>/_index.md`:
   фронтматтер, два-три абзаца описания и одна строка `{{< firmware-tabs >}}`.
   Путь повторять не нужно — шорткод берёт его из расположения страницы.
6. Проверь: `python3 scripts/check-docs-parity.py && hugo --minify && python3 scripts/check-build-output.py`.
7. Кратко резюмируй, что сделано и что осталось (например, физическое тестирование на реальном датчике, которое нельзя провести без железа).
