# SettingsBackup `SettingsBackup` сохраняет только подтверждённые конфигурации в JSON на SD-карту. Ядро `Src/settings_backup.c` не включает STM32 HAL, FatFs, Modbus, RTC или `AppStorage`: календарь и нормализованный снимок передаёт приложение, а файловые операции задаются callbacks структуры `SettingsBackupPort`. ## Размещение При достоверном RTC используется путь: ```text niceOne/settings/YYYY-MM_EnglishMonth/settings_YYYY-MM-DD_HH-MM-SS.json ``` Например: ```text niceOne/settings/2026-07_July/settings_2026-07-17_14-30-05.json ``` Названия месяцев фиксированы на английском и состоят только из FAT-безопасных ASCII-символов. При недостоверном RTC файл помещается в `invalid_rtc` и получает имя `settings_invalid_rtc_rev_N.json`; это имя не выдаётся за календарную дату. Коллизии разрешаются суффиксами `_1`, `_2` и далее. Проверяются одновременно итоговое имя и `.tmp`, поэтому незавершённая транзакция после перезапуска не перезаписывается. ## Schema v1 Корневые поля: `schema`, `schema_version`, `snapshot_revision`, `snapshot_crc32`, `rtc`, `storage`, `units`, `rooms`, `sensors` и `restore_policy`. Все 32 комнаты содержат уставку и гистерезис в десятых долях градуса, старт калибровки и время полного открытия в 100 мс, целевое и подтверждённое положение в процентах. Датчик содержит полный 16-символьный HEX ROM: family, шесть serial-байтов и Dallas CRC, а также номер комнаты. В `RoomSettings` v1 во Flash фиксируется достигнутый безопасный checkpoint. Поэтому `target_position_pct` резервной копии равен `confirmed_position_pct`; ещё не подтверждённая цель Modbus/GUI принципиально не попадает в файл. ## Когда создаётся копия `settings_backup_app.c` сравнивает номер committed-записи. Только при его изменении он физически перечитывает 512 байт через `AppStorage_GetConfirmedSnapshot`, где кольцевой журнал повторно проверяет version, длину, commit marker и CRC. На старте та же ревизия ищется во всех месячных каталогах по content CRC; revision остаётся в файле для аудита, но повторный commit тех же настроек не создаёт дубль. Десятиминутный температурный журнал не является trigger backup. Запись атомарна: уникальный `.tmp` создаётся с `FA_CREATE_NEW`, полностью записывается, синхронизируется, закрывается и только затем переименовывается в `.json`. Старые JSON не удаляются при ошибке open/write/sync/close/rename. Ошибки absent/full/removal переводят автомат в диагностическое состояние и назначают ограниченный retry без задержек и busy wait в main loop. Retention задаётся `SETTINGS_BACKUP_MAXIMUM_COPIES` (по умолчанию 24). При превышении лимита сначала удаляется самый старый подтверждённый duplicate hash, затем самый старый уникальный файл; последняя корректная копия не удаляется. ## Восстановление Автоматического восстановления нет. Наличие JSON никогда не вызывает запись в `AppStorage`. Будущая отдельная команда должна прочитать выбранный файл только для проверки, подтвердить schema/version, UTF-8/JSON, диапазоны 32 комнат, полные ROM и Dallas CRC, content CRC, совместимость backend и получить явное подтверждение оператора. Лишь после этого отдельная реализация может собрать новый AppStorage image и выполнить обычный committed write с обратным чтением. ## Перенос на другую платформу Скопируйте `Inc`, `Src` и конфигурацию. Реализуйте callbacks mount, global dedupe scan, collision-safe path resolve, atomic write и retention. Каждая callback-функция должна иметь ограниченный timeout и не выполняться из ISR. FatFs-порт данного проекта находится в `Port/FatFs`; это единственный модуль библиотеки, который включает `ff.h` и использует общий том SD logger. Модельные тесты запускаются так: ```text python -m unittest discover -s Libraries/SettingsBackup/Tests -p "test_*.py" ``` ## Shared source Canonical source: `templates/c/settings-backup`. Used by `home/climate`; its old paths are compatibility includes. Board-specific ports remain in the application. Change this library, not the forwarding files.