// firmware/src/config.cpp #include "config.h" #include static const char* NS = "doorcounter"; bool config_load(DeviceConfig& cfg) { Preferences prefs; prefs.begin(NS, true); // read-only cfg.device_id = prefs.getString("device_id", ""); cfg.location_id = prefs.getString("location_id", ""); cfg.hmac_secret = prefs.getString("hmac_secret", ""); cfg.wifi_ssid = prefs.getString("wifi_ssid", ""); cfg.wifi_pass = prefs.getString("wifi_pass", ""); cfg.line_offset = (uint8_t)prefs.getUInt("line_offset", 50); prefs.end(); return !cfg.device_id.isEmpty() && !cfg.location_id.isEmpty() && !cfg.hmac_secret.isEmpty(); } bool config_save_wifi(const String& ssid, const String& pass) { Preferences prefs; prefs.begin(NS, false); size_t r1 = prefs.putString("wifi_ssid", ssid); size_t r2 = prefs.putString("wifi_pass", pass); prefs.end(); return (r1 > 0) && (r2 > 0); } bool config_has_wifi() { Preferences prefs; prefs.begin(NS, true); String ssid = prefs.getString("wifi_ssid", ""); prefs.end(); return !ssid.isEmpty(); } void config_clear_wifi() { Preferences prefs; prefs.begin(NS, false); prefs.remove("wifi_ssid"); prefs.remove("wifi_pass"); prefs.end(); } bool config_load_tuning(CVTuning& tuning) { Preferences prefs; prefs.begin(NS, true); // read-only uint32_t ver = prefs.getUInt("cv_ver", UINT32_MAX); if (ver == UINT32_MAX) { prefs.end(); return false; } // All six keys must be present; use sentinels to detect missing. uint32_t diff = prefs.getUInt("cv_diff", UINT32_MAX); uint32_t blob = prefs.getUInt("cv_blob", UINT32_MAX); uint32_t miss = prefs.getUInt("cv_miss", UINT32_MAX); uint32_t line = prefs.getUInt("cv_line", UINT32_MAX); bool has_move = prefs.isKey("cv_move"); float move = prefs.getFloat("cv_move", 0.0f); prefs.end(); if (diff == UINT32_MAX || blob == UINT32_MAX || miss == UINT32_MAX || line == UINT32_MAX || !has_move) { return false; } tuning.diff_thresh = (uint8_t)diff; tuning.min_blob_px = (int)blob; tuning.max_move = move; tuning.max_missed = (int)miss; tuning.line_offset = (uint8_t)line; tuning.cfg_version = ver; return true; } bool config_save_tuning(const CVTuning& tuning) { Preferences prefs; prefs.begin(NS, false); size_t r1 = prefs.putUInt("cv_diff", (uint32_t)tuning.diff_thresh); size_t r2 = prefs.putUInt("cv_blob", (uint32_t)tuning.min_blob_px); size_t r3 = prefs.putFloat("cv_move", tuning.max_move); size_t r4 = prefs.putUInt("cv_miss", (uint32_t)tuning.max_missed); size_t r5 = prefs.putUInt("cv_line", (uint32_t)tuning.line_offset); if (!(r1 > 0 && r2 > 0 && r3 > 0 && r4 > 0 && r5 > 0)) { prefs.end(); return false; } // cv_ver is the atomic commit marker: only written after all tunables succeed. size_t r6 = prefs.putUInt("cv_ver", tuning.cfg_version); prefs.end(); return r6 > 0; }