34constexpr const char*
TAG =
"SysBackup";
37constexpr int kSchemaVer = 1;
40void addStr(cJSON* obj,
const char* key,
const char* value) {
41 if (value && value[0] !=
'\0') {
42 cJSON_AddStringToObject(obj, key, value);
47const char* getStr(
const cJSON* obj,
const char* key) {
48 const cJSON* item = cJSON_GetObjectItemCaseSensitive(obj, key);
49 if (cJSON_IsString(item) && item->valuestring && item->valuestring[0] !=
'\0') {
50 return item->valuestring;
56bool getNum(
const cJSON* obj,
const char* key,
double* out) {
57 const cJSON* item = cJSON_GetObjectItemCaseSensitive(obj, key);
58 if (cJSON_IsNumber(item)) {
59 *out = item->valuedouble;
66bool getBool(
const cJSON* obj,
const char* key,
bool* out) {
67 const cJSON* item = cJSON_GetObjectItemCaseSensitive(obj, key);
68 if (cJSON_IsBool(item)) {
69 *out = cJSON_IsTrue(item);
78 if (!out)
return false;
80 cJSON_AddNumberToObject(out,
"schema_ver", kSchemaVer);
87 cJSON_AddNumberToObject(out,
"backlight", display->getBacklight());
92 cJSON_AddNumberToObject(out,
"sleep_interval", sleep->getLightSleepInterval());
97 cJSON_AddNumberToObject(out,
"tz_offset", rtc->getTimezoneOffset());
111 cJSON* w = cJSON_AddObjectToObject(out,
"wifi");
113 addStr(w,
"ssid", cfg.
ssid);
115 cJSON_AddNumberToObject(w,
"sec", cfg.
security);
116 cJSON_AddBoolToObject(w,
"dhcp", cfg.
useDhcp);
118 cJSON_AddNumberToObject(w,
"ip", cfg.
staticIp);
119 cJSON_AddNumberToObject(w,
"gw", cfg.
gateway);
120 cJSON_AddNumberToObject(w,
"nm", cfg.
netmask);
124 cJSON_AddNumberToObject(out,
"wifi_timeout", wifi.getConnectTimeoutMs());
125 cJSON_AddBoolToObject(out,
"wifi_enabled", wifi.isUserEnabled());
128 cJSON* mods = cJSON_AddObjectToObject(out,
"modules_enabled");
131 uint8_t count = reg.getModuleCount();
132 for (uint8_t i = 0; i < count; i++) {
135 cJSON_AddBoolToObject(mods, m->
getName(), reg.isModuleEnabled(i));
148 if (getNum(in,
"schema_ver", &sv) &&
static_cast<int>(sv) != kSchemaVer) {
149 LOG_W(
TAG,
"system schema_ver %d != expected %d, skipping section",
150 static_cast<int>(sv), kSchemaVer);
155 if (
const char* lang = getStr(in,
"language")) {
161 if (getNum(in,
"backlight", &num)) {
163 display->setBacklight(
static_cast<uint16_t
>(num));
164 display->saveBacklight();
172 if (getNum(in,
"sleep_interval", &num)) {
174 sleep->setLightSleepInterval(
static_cast<uint32_t
>(num));
182 if (getNum(in,
"tz_offset", &num)) {
184 rtc->setTimezoneOffset(
static_cast<int8_t
>(num));
200 const cJSON* w = cJSON_GetObjectItemCaseSensitive(in,
"wifi");
201 if (cJSON_IsObject(w)) {
202 const char* ssid = getStr(w,
"ssid");
206 std::strncpy(wz.
ssid, ssid,
sizeof(wz.
ssid) - 1);
207 if (
const char* pass = getStr(w,
"pass")) {
211 getNum(w,
"sec", &secNum);
215 getBool(w,
"dhcp", &dhcp);
220 auto packToStr = [](
const cJSON* obj,
const char* key,
char* dst,
size_t dstSize) {
222 getNum(obj, key, &v);
223 uint32_t ip =
static_cast<uint32_t
>(v);
224 std::snprintf(dst, dstSize,
"%u.%u.%u.%u",
225 static_cast<unsigned>((ip >> 24) & 0xFF),
226 static_cast<unsigned>((ip >> 16) & 0xFF),
227 static_cast<unsigned>((ip >> 8) & 0xFF),
228 static_cast<unsigned>(ip & 0xFF));
241 if (getNum(in,
"wifi_timeout", &num)) {
242 if (wifi.setConnectTimeoutMs(
static_cast<uint32_t
>(num))) r.
imported++;
else r.
failed++;
245 bool wifiEnabled =
false;
246 if (getBool(in,
"wifi_enabled", &wifiEnabled)) {
247 wifi.persistUserIntent(wifiEnabled);
252 const cJSON* mods = cJSON_GetObjectItemCaseSensitive(in,
"modules_enabled");
253 if (cJSON_IsObject(mods)) {
255 uint8_t count = reg.getModuleCount();
256 for (
const cJSON* item = mods->child; item; item = item->next) {
257 if (!item->string || !cJSON_IsBool(item)) {
262 for (uint8_t i = 0; i < count; i++) {
264 if (m && m->
getName() && std::strcmp(m->
getName(), item->string) == 0) {
265 reg.setModuleEnabled(i, cJSON_IsTrue(item));
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_I(tag, fmt,...)
Module interface that extends IService with module-specific features.
virtual const char * getName() const =0
static ModuleRegistry & instance()
Returns the singleton module registry instance.
static bool exportSystemSettings(cJSON *out)
Writes the user-configurable NVS settings into out.
static cdc::core::IModule::BackupResult importSystemSettings(const cJSON *in)
Restores the system settings from in best-effort.
static I18n & instance()
Singleton accessor.
static constexpr uint8_t MAX_TEXT_LEN
static WifiHandlers & instance()
Returns singleton Wi-Fi handlers instance.
IDisplay * getDisplayInstance()
Returns lazily created singleton display instance.
IRtc * getRtcInstance()
Returns the singleton RTC service instance.
ISleepController * getSleepControllerInstance()
Returns the singleton sleep controller service instance.
bool loadDisplayField(const char *key, char *out, size_t outSize)
Reads one display text field from NVS into the caller buffer.
void saveDisplayField(const char *key, const char *value)
Saves one display text field to NVS.
Per-module restore outcome reported by importBackup().
uint16_t failed
Records skipped due to errors.
uint16_t imported
Records restored successfully.
hal::WifiSecurity security
void reset()
Resets Wi-Fi wizard state to defaults.