126 lines
4.9 KiB
C
126 lines
4.9 KiB
C
#ifndef SETTINGS_BACKUP_H
|
||
#define SETTINGS_BACKUP_H
|
||
|
||
/* Переносимое ядро резервирования не включает HAL, FatFs, AppStorage и Modbus. */
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
|
||
#define SETTINGS_BACKUP_SCHEMA_VERSION 1U
|
||
#define SETTINGS_BACKUP_MAX_ROOMS 32U
|
||
#define SETTINGS_BACKUP_MAX_SENSORS 32U
|
||
#define SETTINGS_BACKUP_MAX_PATH 160U
|
||
|
||
/* Календарь передаётся приложением вместе с признаком доверия к RTC. */
|
||
typedef struct {
|
||
uint16_t year;
|
||
uint8_t month;
|
||
uint8_t date;
|
||
uint8_t hours;
|
||
uint8_t minutes;
|
||
uint8_t seconds;
|
||
uint8_t valid;
|
||
} SettingsBackupDateTime;
|
||
|
||
/* Одна комната содержит только документированные инженерные параметры. */
|
||
typedef struct {
|
||
uint16_t setpoint_x10;
|
||
uint8_t hysteresis_x10;
|
||
uint8_t calibration_start_pct;
|
||
uint16_t full_open_time_100ms;
|
||
uint8_t target_position_pct;
|
||
uint8_t confirmed_position_pct;
|
||
} SettingsBackupRoom;
|
||
|
||
/* В JSON всегда попадает полный ROM, включая family и Dallas CRC. */
|
||
typedef struct {
|
||
uint8_t rom[8];
|
||
uint8_t room;
|
||
} SettingsBackupSensor;
|
||
|
||
/* Снимок создаётся адаптером только из committed-записи AppStorage. */
|
||
typedef struct {
|
||
uint32_t revision;
|
||
uint32_t content_crc32;
|
||
uint8_t requested_backend;
|
||
uint8_t active_backend;
|
||
uint8_t room_count;
|
||
uint8_t sensor_count;
|
||
SettingsBackupDateTime rtc;
|
||
SettingsBackupRoom rooms[SETTINGS_BACKUP_MAX_ROOMS];
|
||
SettingsBackupSensor sensors[SETTINGS_BACKUP_MAX_SENSORS];
|
||
} SettingsBackupSnapshot;
|
||
|
||
/* Короткий набор результатов позволяет порту отобразить SD absent/full/I/O. */
|
||
typedef enum {
|
||
SETTINGS_BACKUP_PORT_OK = 0,
|
||
SETTINGS_BACKUP_PORT_NOT_READY,
|
||
SETTINGS_BACKUP_PORT_NO_SPACE,
|
||
SETTINGS_BACKUP_PORT_IO_ERROR
|
||
} SettingsBackupPortResult;
|
||
|
||
/* Наблюдаемое состояние не скрывает retry и отказ носителя от Modbus/GUI. */
|
||
typedef enum {
|
||
SETTINGS_BACKUP_IDLE = 0,
|
||
SETTINGS_BACKUP_PENDING,
|
||
SETTINGS_BACKUP_LAST_OK,
|
||
SETTINGS_BACKUP_LAST_NOT_READY,
|
||
SETTINGS_BACKUP_LAST_NO_SPACE,
|
||
SETTINGS_BACKUP_LAST_IO_ERROR,
|
||
SETTINGS_BACKUP_LAST_INVALID_SNAPSHOT
|
||
} SettingsBackupStatus;
|
||
|
||
/* Все операции платформы ограничены одной файловой транзакцией за вызов. */
|
||
typedef struct {
|
||
uint32_t (*tick_ms)(void *context);
|
||
SettingsBackupPortResult (*mount)(void *context);
|
||
void (*unmount)(void *context);
|
||
SettingsBackupPortResult (*find_identical)(void *context,
|
||
uint32_t revision, uint32_t crc32, uint8_t *found);
|
||
SettingsBackupPortResult (*resolve_paths)(void *context,
|
||
const SettingsBackupSnapshot *snapshot, char *final_path,
|
||
uint32_t final_capacity, char *temporary_path,
|
||
uint32_t temporary_capacity);
|
||
SettingsBackupPortResult (*atomic_write)(void *context,
|
||
const char *temporary_path, const char *final_path,
|
||
const char *utf8_json, uint32_t length);
|
||
SettingsBackupPortResult (*apply_retention)(void *context,
|
||
uint16_t maximum_copies);
|
||
} SettingsBackupPort;
|
||
|
||
/* Контекст хранит pending-снимок: вызывающий может освобождать свой буфер. */
|
||
typedef struct {
|
||
SettingsBackupPort port;
|
||
void *port_context;
|
||
SettingsBackupSnapshot pending_snapshot;
|
||
char *json_buffer;
|
||
uint32_t json_capacity;
|
||
char final_path[SETTINGS_BACKUP_MAX_PATH];
|
||
char temporary_path[SETTINGS_BACKUP_MAX_PATH];
|
||
uint32_t next_retry_ms;
|
||
uint16_t maximum_copies;
|
||
uint8_t phase;
|
||
uint8_t retry_count;
|
||
uint8_t pending;
|
||
SettingsBackupStatus status;
|
||
} SettingsBackup;
|
||
|
||
/* Инициализация не обращается к SD и потому безопасна во время старта МК. */
|
||
uint8_t SettingsBackup_Init(SettingsBackup *instance,
|
||
const SettingsBackupPort *port, void *port_context,
|
||
char *json_buffer, uint32_t json_capacity, uint16_t maximum_copies);
|
||
|
||
/* Новая committed-ревизия заменяет только ещё не записанный pending-снимок. */
|
||
uint8_t SettingsBackup_Notify(SettingsBackup *instance,
|
||
const SettingsBackupSnapshot *snapshot);
|
||
|
||
/* Service делает не более одного mount/scan/write/retention шага за проход. */
|
||
void SettingsBackup_Service(SettingsBackup *instance);
|
||
|
||
/* Форматирование и CRC открыты для host-тестов без файловой системы. */
|
||
uint32_t SettingsBackup_CalculateContentCrc(const SettingsBackupSnapshot *snapshot);
|
||
int SettingsBackup_FormatJson(const SettingsBackupSnapshot *snapshot,
|
||
char *output, uint32_t capacity);
|
||
SettingsBackupStatus SettingsBackup_GetStatus(const SettingsBackup *instance);
|
||
|
||
#endif /* SETTINGS_BACKUP_H */
|