SettingsBackup
SettingsBackup сохраняет только подтверждённые конфигурации в JSON на
SD-карту. Ядро Src/settings_backup.c не включает STM32 HAL, FatFs, Modbus,
RTC или AppStorage: календарь и нормализованный снимок передаёт приложение,
а файловые операции задаются callbacks структуры SettingsBackupPort.
Размещение
При достоверном RTC используется путь:
niceOne/settings/YYYY-MM_EnglishMonth/settings_YYYY-MM-DD_HH-MM-SS.json
Например:
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.
Модельные тесты запускаются так:
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.