Nimbin[12]?Embedded / esp_garden / commits / b0cebc2

esp_garden git · master

Distributed ESP sensor and actuator system (garden)

esp32 esp-idf iot sensors c++ sql · first commit 2025-10-15 · last commit 2026-01-20 (8 months ago) · synced 3 days ago · upstream: git.ide3.de/hsnr/mic/esp_garden

C++ 70.7% Markdown 18% C 10.7%
git clone https://git.christianimmanuel.de/embedded/esp_garden.gitwget https://git.christianimmanuel.de/embedded/esp_garden/archive/esp_garden.tar.gz

Update syncTime and receive config

Chris esp · 2025-11-02 07:16 · b0cebc2cf38b692c761b7d321389f8da42fc9ffb

 post_server/main/WiFiManager.cpp | 171 ++++++++++++++++++++++++++++++++++++++-
 post_server/main/WiFiManager.h   |  11 ++-
 post_server/main/main.cpp        |  11 ++-
 3 files changed, 187 insertions(+), 6 deletions(-)

diff --git a/post_server/main/WiFiManager.cpp b/post_server/main/WiFiManager.cpp
index 0c20769..0aead7e 100644
--- a/post_server/main/WiFiManager.cpp
+++ b/post_server/main/WiFiManager.cpp
@@ -7,7 +7,9 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cinttypes>
+#include <ctime>
 
+#include "esp_sntp.h"
 #include "esp_log.h"
 #include "esp_wifi.h"
 #include "esp_http_client.h"
@@ -43,19 +45,57 @@ esp_err_t WiFi_connect() {
   return ESP_OK;
 }
 
-esp_err_t WiFi_disconnect(void) {
+esp_err_t WiFi_disconnect() {
     esp_err_t err = esp_wifi_disconnect();
     ESP_ERROR_CHECK(esp_wifi_stop());
     ESP_ERROR_CHECK(esp_wifi_deinit());
     return err;
 }
 
+void WIFI_SyncTime() {
+    static const char *TAG = "WIFI_SyncTime";
+    ESP_LOGI(TAG, "Syncing time...");
+
+    // Configure SNTP
+    sntp_setoperatingmode(SNTP_OPMODE_POLL);
+    sntp_setservername(0, NTP_SERVER);
+    sntp_init();
+
+    // Wait until time is set (or timeout)
+    const int64_t min_valid_time = 1600000000;
+    const int max_wait_ms = 10000;
+    const int interval_ms = 500;
+    int waited_ms = 0;
+    time_t now = 0;
+
+    while (waited_ms < max_wait_ms) {
+        time(&now);
+        if (now > min_valid_time) break;
+        vTaskDelay(pdMS_TO_TICKS(interval_ms));
+        waited_ms += interval_ms;
+    }
 
+    if (now < min_valid_time) {
+        ESP_LOGW(TAG, "NTP sync failed (no valid time within %d ms)", max_wait_ms);
+    } else {
+        // Set timezone
+        setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
+        tzset();
+        char buf[64];
+        struct tm timeinfo;
+        localtime_r(&now, &timeinfo);
+        strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &timeinfo);
+        ESP_LOGI(TAG, "Time synced: %s", buf);
+    }
+
+    // Should i stop it?
+}
 
 
 
 /////////////////////////////////////////////////
 /////////////////////////////////////////////////
+/// Post data to server
 
 static std::string http_response;
 
@@ -131,7 +171,7 @@ void post_ToServer( const char* path, char* json, size_t len) {
         ESP_LOGE(TAG, "esp_http_client_perform failed: %d", err);
     }
 
-    // cleanup client (this will not free http_response)
+    // cleanup client
     esp_err_t cleanup_err = esp_http_client_cleanup(client);
     if (cleanup_err != ESP_OK) {
         ESP_LOGW(TAG, "esp_http_client_cleanup returned %d", cleanup_err);
@@ -277,3 +317,130 @@ void WiFi_PostDataToServer(size_t buffer_len, SensorEntry_s buffer[BUFFER_SIZE])
     free(json);
 }
 
+
+
+
+
+
+//////////////////////////////////////
+/// Config stuff
+
+static int findKey(const std::string &src, const char *key) {
+    std::string pattern = std::string("\"") + key + "\":";
+    auto pos = src.find(pattern);
+    return (pos == std::string::npos) ? -1 : (int)pos + pattern.size();
+}
+
+
+bool WIFI_GetSensorConfigServer(const char* sensor_name, SensorConfigServer_s &cfg) {
+    static const char *TAG = "WIFI_GetSensorConfigServer";
+
+    // construct URL
+    char name_enc[64];
+    snprintf(name_enc, sizeof(name_enc), "%s", sensor_name);
+    char url[256];
+    snprintf(url, sizeof(url), "https://%s:%d/get_sensor_config.php?name=%s", server_host, server_port, name_enc);
+
+    ESP_LOGI(TAG, "Requesting config for sensor: %s", sensor_name);
+    http_response.clear();
+
+    // configure HTTP client
+    esp_http_client_config_t config = {
+        .url = url,
+        .event_handler = http_event_handler,
+    };
+
+    esp_http_client_handle_t client = esp_http_client_init(&config);
+    if (!client) {
+        ESP_LOGE(TAG, "esp_http_client_init failed");
+        return false;
+    }
+
+    esp_http_client_set_method(client, HTTP_METHOD_GET);
+    esp_http_client_set_header(client, "X-API-Token", api_token);
+
+    esp_err_t err = esp_http_client_perform(client);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "HTTP GET failed: %s", esp_err_to_name(err));
+        esp_http_client_cleanup(client);
+        return false;
+    }
+
+    int status = esp_http_client_get_status_code(client);
+    esp_http_client_cleanup(client);
+
+    if (status != 200) {
+        ESP_LOGW(TAG, "Server returned HTTP %d", status);
+        return false;
+    }
+
+    ESP_LOGI(TAG, "Received %zu bytes", http_response.size());
+    ESP_LOGD(TAG, "Body: %s", http_response.c_str());
+
+    // Parse json response
+    const std::string &body = http_response;
+    memset(&cfg, 0, sizeof(cfg));
+
+    auto extractInt = [&](const char *key) -> int {
+        int pos = findKey(body, key);
+        if (pos < 0) return 0;
+        return std::atoi(body.c_str() + pos);
+    };
+
+    auto extractBool = [&](const char *key) -> bool {
+        int pos = findKey(body, key);
+        if (pos < 0) return false;
+        const char *p = body.c_str() + pos;
+        return (strncmp(p, "true", 4) == 0 || *p == '1');
+    };
+
+    auto extractString = [&](const char *key, char *out, size_t out_size) {
+        std::string pattern = std::string("\"") + key + "\":\"";
+        auto start = body.find(pattern);
+        if (start == std::string::npos) { out[0] = '\0'; return; }
+        start += pattern.size();
+        auto end = body.find('"', start);
+        if (end == std::string::npos) { out[0] = '\0'; return; }
+        size_t len = end - start;
+        if (len >= out_size) len = out_size - 1;
+        memcpy(out, body.c_str() + start, len);
+        out[len] = '\0';
+    };
+
+    cfg.success  = extractBool("success");
+    extractString("sensor_name", cfg.sensor_name, sizeof(cfg.sensor_name));
+    cfg.pin      = extractInt("pin");
+    cfg.use_time = extractBool("use_time");
+    cfg.delay_ms = extractInt("delay_ms");
+    cfg.min_moisture = extractInt("min_moisture");
+    cfg.is_active    = extractBool("is_active");
+    extractString("notification_name", cfg.notification_name, sizeof(cfg.notification_name));
+    cfg.pumping_delay_sec = extractInt("pumping_delay_sec");
+    cfg.pumping_duration  = extractInt("pumping_duration");
+
+    // Parse times array
+    cfg.time_count = 0;
+    size_t arr_start = body.find("\"times\":[");
+    if (arr_start != std::string::npos) {
+        arr_start += 9;
+        size_t arr_end = body.find(']', arr_start);
+        if (arr_end != std::string::npos) {
+            std::string arr = body.substr(arr_start, arr_end - arr_start);
+            size_t pos = 0;
+            while (cfg.time_count < 8 && pos < arr.size()) {
+                size_t comma = arr.find(',', pos);
+                std::string token = arr.substr(pos, (comma == std::string::npos ? arr.size() : comma) - pos);
+                pos = (comma == std::string::npos) ? arr.size() : comma + 1;
+                int val = std::atoi(token.c_str());
+                if (val > 0) cfg.times[cfg.time_count++] = (uint16_t)val;
+            }
+        }
+    }
+
+    ESP_LOGI(TAG, "Parsed config: success=%d pin=%d min=%d delay=%d use_time=%d time_count=%u",
+             cfg.success, cfg.pin, cfg.min_moisture, cfg.delay_ms, cfg.use_time, cfg.time_count);
+    ESP_LOGI(TAG, "sensor_name='%s' notification='%s' pumping_delay_sec=%d pumping_duration=%d",
+             cfg.sensor_name, cfg.notification_name, cfg.pumping_delay_sec, cfg.pumping_duration);
+
+    return cfg.success;
+}
diff --git a/post_server/main/WiFiManager.h b/post_server/main/WiFiManager.h
index 140f98d..48e2518 100644
--- a/post_server/main/WiFiManager.h
+++ b/post_server/main/WiFiManager.h
@@ -1,5 +1,5 @@
-// tutorial.h
-#pragma once
+#ifndef WIFIMANAGER_H
+#define WIFIMANAGER_H
 
 #include "globals.h"
 
@@ -14,7 +14,12 @@
 #include "freertos/FreeRTOS.h"
 
 esp_err_t WiFi_connect();
-esp_err_t WiFi_disconnect(void);
+esp_err_t WiFi_disconnect();
 
+void WIFI_SyncTime();
 void WiFi_PostDataToServer(size_t buffer_len, SensorEntry_s buffer[BUFFER_SIZE]);
 
+bool WIFI_GetSensorConfigServer(const char* sensor_name, SensorConfigServer_s &cfg);
+
+
+#endif
diff --git a/post_server/main/main.cpp b/post_server/main/main.cpp
index cde3010..a17c410 100644
--- a/post_server/main/main.cpp
+++ b/post_server/main/main.cpp
@@ -24,7 +24,11 @@ extern "C" void app_main() {
 
             vTaskDelay(10000 / portTICK_PERIOD_MS);
 
+            // we should do that more than once!
+            WIFI_SyncTime();
 
+            SensorConfigServer_s cfg;
+            WIFI_GetSensorConfigServer("moisture_1", cfg);
             strcpy(g_buffer[0].table, "moisture_1");
             strcpy(g_buffer[0].value, "123");
             g_buffer[0].time = 0;
@@ -37,10 +41,15 @@ extern "C" void app_main() {
 
             while (true) {
                 WiFi_PostDataToServer(g_buffer_count, g_buffer);
-                vTaskDelay(pdMS_TO_TICKS(5000));
+                // Check stack size 
+                UBaseType_t free_stack = uxTaskGetStackHighWaterMark(NULL);
+                ESP_LOGI("wifi_task", "Stack remaining: %u bytes", (unsigned)free_stack);
 
+                vTaskDelay(pdMS_TO_TICKS(5000));
             }
             vTaskDelay(10000 / portTICK_PERIOD_MS);
+
+            WiFi_disconnect();
     }, "wifi_task", 8192, NULL, 1, NULL);
 
 }