diff --git a/CAR_GPS_TRACKER.ino b/CAR_GPS_TRACKER.ino index 5176fa2..b6edef9 100644 --- a/CAR_GPS_TRACKER.ino +++ b/CAR_GPS_TRACKER.ino @@ -43,6 +43,17 @@ void setup() { // GNSS power on (if applicable later) NetMgr::sendAT("AT+CGNSPWR=1", 2000); + +OTAMgr::setCurrentVersion(FW_VERSION); +String ver, url, sha; +if (OTAMgr::check(CFG.baseUrl, CFG.imei, ver, url, sha)) { + Serial.println("OTA available: " + ver + " -> " + url); + // Optionally apply now: + // OTAMgr::apply(url, sha); +} + + + } void loop() { diff --git a/src/core/CommandMgr.cpp b/src/core/CommandMgr.cpp index 991436a..b9e9d45 100644 --- a/src/core/CommandMgr.cpp +++ b/src/core/CommandMgr.cpp @@ -1,6 +1,7 @@ #include "CommandMgr.hpp" #include "HttpClient.hpp" #include "AppConfig.hpp" +#include "OTAMgr.hpp" extern AppConfig CFG; namespace @@ -13,6 +14,41 @@ namespace // Extract array of objects from a JSON string like: [{"id":..,"type":"..","payload":{...}}, ...] // We’ll do a naive split on "},{" for small payloads; replace with proper JSON parsing later. + static int pickInt(const String &j, const char *key) + { + String pat = String("\"") + key + "\":"; + int k = j.indexOf(pat); + if (k < 0) + return -1; + k += pat.length(); + while (k < (int)j.length() && (j[k] == ' ' || j[k] == ':')) + k++; + int i = k; + while (i < (int)j.length() && isDigit(j[i])) + i++; + if (i <= k) + return -1; + return j.substring(k, i).toInt(); + } + + static String pickStr(const String &j, const char *key) + { + String pat = String("\"") + key + "\":"; + int k = j.indexOf(pat); + if (k < 0) + return ""; + k += pat.length(); + while (k < (int)j.length() && (j[k] == ' ' || j[k] == '\"' || j[k] == ':')) + k++; + if (k > 0 && j[k - 1] == '\"') + { + int e = j.indexOf('\"', k); + if (e > k) + return j.substring(k, e); + } + return ""; + } + long extractId(const String &obj) { String pat = "\"id\":"; @@ -248,10 +284,67 @@ namespace CommandMgr } else if (c.type == "ota") { - String url = /* parse from payload */; - String sha = /* parse if provided */; - execOk = OTAMgr::apply(url, sha); - detail = execOk ? "ota applied" : "ota failed"; + + String url = pickStr(c.payload, "url"); + String sha = pickStr(c.payload, "sha256"); + if (!url.length()) + { + execOk = false; + detail = "missing url"; + } + else + { + execOk = OTAMgr::apply(url, sha); + detail = execOk ? "ota applied" : "ota failed"; + } + } + else if (c.type == "telemetry_sec") + { + int sec = pickInt(c.payload, "telemetry_sec"); + if (sec > 0) + { + CFG.telemetryPeriodSec = (uint32_t)sec; + Serial.printf("Telemetry sec set to %u\n", CFG.telemetryPeriodSec); + execOk = true; + detail = "telemetry updated"; + } + else + { + execOk = false; + detail = "bad telemetry_sec"; + } + } + else if (c.type == "poll_sec") + { + int sec = pickInt(c.payload, "poll_sec"); + if (sec > 0) + { + CFG.commandPollSec = (uint32_t)sec; + Serial.printf("Poll sec set to %u\n", CFG.commandPollSec); + execOk = true; + detail = "poll updated"; + } + else + { + execOk = false; + detail = "bad poll_sec"; + } + } + else if (c.type == "wifi") + { + String tgt = pickStr(c.payload, "target"); + if (tgt.equalsIgnoreCase("home")) + { + CFG.atHomeRequested = true; + Serial.println("WiFi home connect requested"); + execOk = true; + detail = "wifi home requested"; + } + else + { + execOk = false; + detail = "unknown wifi target"; + } } else { @@ -274,6 +367,15 @@ namespace CommandMgr bool handleSleep(const String &payload) { + + int sec = pickInt(payload, "interval_sec"); + if (sec > 0) + { + CFG.sleepSec = (uint32_t)sec; + Serial.printf("Sleep sec set to %u\n", CFG.sleepSec); + return true; + } + // TODO: parse {"interval_sec":120} Serial.println("handleSleep payload: " + payload); return true;