#include "settings.hpp" #include #include #include #include Settings::Settings() { setDefaults(); } Settings::~Settings() { // Cleanup if needed } void Settings::setDefaults() { strcpy(data_.sync_server_url, "https://ssvc.ldev/api/"); strcpy(data_.device_api_key, "c62a6b5c-914e-49d4-9871-1896a627e0df"); strcpy(data_.sync_server_url, DEFAULT_SYNC_SERVER_URL); strcpy(data_.device_api_key, DEFAULT_DEVICE_API_KEY); data_.sync_interval_seconds = DEFAULT_SYNC_INTERVAL; data_.auto_sync = DEFAULT_AUTO_SYNC; data_.wifi_mode = DEFAULT_WIFI_MODE; strcpy(data_.station_ssid, DEFAULT_STATION_SSID); strcpy(data_.station_password, DEFAULT_STATION_PASSWORD); strcpy(data_.ap_ssid, DEFAULT_AP_SSID); strcpy(data_.ap_password, DEFAULT_AP_PASSWORD); data_.ap_channel = DEFAULT_AP_CHANNEL; data_.enable_fallback_ap = DEFAULT_ENABLE_FALLBACK_AP; data_.log_level = DEFAULT_LOG_LEVEL; data_.updated_at = millis(); // Use current uptime as timestamp data_.version = DEFAULT_VERSION; } bool Settings::fileExists() { return LittleFS.exists(filename_); } bool Settings::load() { if (!fileExists()) { // File doesn't exist, use defaults setDefaults(); }else{ File file = LittleFS.open(filename_, "r"); if (!file) { LOG_ERROR("Failed to open settings file for reading"); setDefaults(); return false; } // Read file into buffer size_t fileSize = file.size(); uint8_t buffer[fileSize]; file.read(buffer, fileSize); file.close(); // Decode protobuf pb_istream_t stream = pb_istream_from_buffer(buffer, fileSize); bool status = pb_decode(&stream, settings_SettingsData_fields, &data_); if (!status) { LOG_ERROR("Failed to decode settings protobuf"); setDefaults(); return false; } } // callback if set runCallback(); return true; } bool Settings::save() { // Update timestamp and version data_.updated_at = millis(); data_.version++; // Encode to buffer first to get size size_t bufferSize = 0; pb_get_encoded_size(&bufferSize, settings_SettingsData_fields, &data_); uint8_t buffer[bufferSize]; pb_ostream_t stream = pb_ostream_from_buffer(buffer, bufferSize); bool status = pb_encode(&stream, settings_SettingsData_fields, &data_); if (!status) { LOG_ERROR("Failed to encode settings protobuf"); return false; } // Write to file File file = LittleFS.open(filename_, "w"); if (!file) { LOG_ERROR("Failed to open settings file for writing"); return false; } size_t bytesWritten = file.write(buffer, bufferSize); file.close(); if (bytesWritten != bufferSize) { LOG_ERROR("Failed to write complete settings file"); return false; } return true; } void Settings::setData(const settings_SettingsData& newData) { data_ = newData; data_.updated_at = millis(); data_.version++; // Notify callback if set runCallback(); } void Settings::resetToDefaults() { setDefaults(); } struct SettingsCallbackParams { settings_SettingsData data; std::function callback; }; static void settingsChangeTask(void* pvParameters) { SettingsCallbackParams* params = static_cast(pvParameters); if (params->callback) { vTaskDelay(100 / portTICK_PERIOD_MS); // Small delay to ensure system stability LOG_DEBUG("Settings (Task): Executing change callback..."); params->callback(params->data); LOG_DEBUG("Settings (Task): Callback finished."); } delete params; vTaskDelete(NULL); } void Settings::runCallback() { if (changeCallback_) { SettingsCallbackParams* params = new SettingsCallbackParams(); params->data = data_; // Create a safe copy for the task params->callback = changeCallback_; xTaskCreate( settingsChangeTask, "SettingsChangeTask", 4096, // Stack size params, 1, // Priority NULL ); } } void Settings::setChangeCallback(std::function callback) { changeCallback_ = callback; } Settings settings;