#include "ui/apps/travel/settings/settings_handler.h" #include "cJSON.h" #include "esp_log.h" static const char* TAG = "TravelSettings"; namespace travel { SettingHandler::SettingHandler(std::unique_ptr storage) : routes_() , polling_interval_sec_(DEFAULT_POLLING_INTERVAL) , storage_(std::move(storage)) { } esp_err_t SettingHandler::init(const EventGroupHandle_t& system_event_group) { storage_->init(system_event_group); return ESP_OK; } void SettingHandler::load_settings() { // Load polling interval std::string poll_str = storage_->get(NVS_KEY_POLLING); if (!poll_str.empty()) { polling_interval_sec_ = std::stoul(poll_str); if (polling_interval_sec_ < MIN_POLLING_INTERVAL || polling_interval_sec_ > MAX_POLLING_INTERVAL) { polling_interval_sec_ = DEFAULT_POLLING_INTERVAL; } } // Load routes - clear existing settings as per new format routes_.clear(); std::string routes_json = storage_->get(NVS_KEY_ROUTES); if (!routes_json.empty()) { routes_from_json(routes_json); } ESP_LOGI(TAG, "Loaded %d routes, polling interval: %d seconds", static_cast(routes_.size()), static_cast(polling_interval_sec_)); } void SettingHandler::save_settings() { // Save polling interval storage_->put(NVS_KEY_POLLING, std::to_string(polling_interval_sec_)); // Save routes std::string routes_json = routes_to_json(); storage_->put(NVS_KEY_ROUTES, routes_json); ESP_LOGI(TAG, "Saved %d routes, polling interval: %d seconds", static_cast(routes_.size()), static_cast(polling_interval_sec_)); } void SettingHandler::add_route(const RoutePair& route) { if (routes_.size() >= MAX_ROUTES) { ESP_LOGW(TAG, "Maximum number of routes reached (%d)", static_cast(MAX_ROUTES)); return; } // Check for duplicates for (const auto& existing : routes_) { if (existing == route) { ESP_LOGW(TAG, "Route already exists"); return; } } routes_.push_back(route); ESP_LOGI(TAG, "Added route: %s -> %s", route.station_name.c_str(), route.direction_name.c_str()); } void SettingHandler::remove_route(size_t index) { if (index < routes_.size()) { ESP_LOGI(TAG, "Removing route at index %d", static_cast(index)); routes_.erase(routes_.begin() + index); } } void SettingHandler::clear_routes() { routes_.clear(); ESP_LOGI(TAG, "Cleared all routes"); } void SettingHandler::set_polling_interval(uint32_t seconds) { if (seconds < MIN_POLLING_INTERVAL) { seconds = MIN_POLLING_INTERVAL; } else if (seconds > MAX_POLLING_INTERVAL) { seconds = MAX_POLLING_INTERVAL; } polling_interval_sec_ = seconds; ESP_LOGI(TAG, "Set polling interval to %d seconds", static_cast(seconds)); } std::string SettingHandler::routes_to_json() const { cJSON* root = cJSON_CreateArray(); for (const auto& route : routes_) { cJSON* route_obj = cJSON_CreateObject(); cJSON_AddStringToObject(route_obj, "line_code", route.line_code.c_str()); cJSON_AddStringToObject(route_obj, "line_name", route.line_name.c_str()); cJSON_AddStringToObject(route_obj, "line_color", route.line_color.c_str()); cJSON_AddStringToObject(route_obj, "station_code", route.station_code.c_str()); cJSON_AddStringToObject(route_obj, "station_name", route.station_name.c_str()); cJSON_AddStringToObject(route_obj, "direction", route.direction.c_str()); cJSON_AddStringToObject(route_obj, "direction_name", route.direction_name.c_str()); cJSON_AddItemToArray(root, route_obj); } char* json_str = cJSON_PrintUnformatted(root); std::string result(json_str ? json_str : "[]"); if (json_str) { free(json_str); } cJSON_Delete(root); return result; } void SettingHandler::routes_from_json(const std::string& json) { routes_.clear(); cJSON* root = cJSON_Parse(json.c_str()); if (!root || !cJSON_IsArray(root)) { ESP_LOGE(TAG, "Failed to parse routes JSON"); if (root) { cJSON_Delete(root); } return; } int array_size = cJSON_GetArraySize(root); for (int i = 0; i < array_size && i < static_cast(MAX_ROUTES); i++) { cJSON* route_obj = cJSON_GetArrayItem(root, i); if (!route_obj || !cJSON_IsObject(route_obj)) { continue; } RoutePair route; cJSON* item; item = cJSON_GetObjectItem(route_obj, "line_code"); if (item && cJSON_IsString(item)) route.line_code = item->valuestring; item = cJSON_GetObjectItem(route_obj, "line_name"); if (item && cJSON_IsString(item)) route.line_name = item->valuestring; item = cJSON_GetObjectItem(route_obj, "line_color"); if (item && cJSON_IsString(item)) route.line_color = item->valuestring; item = cJSON_GetObjectItem(route_obj, "station_code"); if (item && cJSON_IsString(item)) route.station_code = item->valuestring; item = cJSON_GetObjectItem(route_obj, "station_name"); if (item && cJSON_IsString(item)) route.station_name = item->valuestring; item = cJSON_GetObjectItem(route_obj, "direction"); if (item && cJSON_IsString(item)) route.direction = item->valuestring; item = cJSON_GetObjectItem(route_obj, "direction_name"); if (item && cJSON_IsString(item)) route.direction_name = item->valuestring; if (!route.line_code.empty() && !route.station_code.empty() && !route.direction.empty()) { routes_.push_back(route); } } cJSON_Delete(root); ESP_LOGI(TAG, "Loaded %d routes from JSON", static_cast(routes_.size())); } } // namespace travel