Nimbin[12]?Embedded / esp_garden / commits / 4e29e1e

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

init

Christian Immanuel · 2025-10-26 18:57 · 4e29e1e0c1b6ed9175c177974ad276e19e9b02d1

 client_pump/ClientPump.cpp | 168 +++++++++++++++++++++++++++++++++++++++++++++
 client_pump/ClientPump.h   |  61 ++++++++++++++++
 client_pump/globals.cpp    |   1 +
 client_pump/globals.h      |   1 +
 4 files changed, 231 insertions(+)

diff --git a/client_pump/ClientPump.cpp b/client_pump/ClientPump.cpp
new file mode 100644
index 0000000..81307f9
--- /dev/null
+++ b/client_pump/ClientPump.cpp
@@ -0,0 +1,168 @@
+#include "ClientPump.h"
+
+#include <WiFi.h>
+#include <esp_wifi.h>
+#include <esp_now.h>
+#include <esp_sleep.h>
+#include <sys/time.h>
+
+
+
+// ----------------------------------------------------------------------------
+// Time handling
+// ----------------------------------------------------------------------------
+
+int64_t get_CurrentUnix() {
+    return (int64_t)time(nullptr);
+}
+
+void setup_Timezone() {
+    setenv("TZ", "CET-1CEST,M3.5.0,M10.5.0/3", 1);
+    tzset();
+}
+
+void set_LocalTime(long long unix_now) {
+    struct timeval tv;
+    tv.tv_sec  = unix_now;
+    tv.tv_usec = 0;
+
+    settimeofday(&tv, nullptr);
+}
+
+// ----------------------------------------------------------------------------
+// WiFi handling
+// ----------------------------------------------------------------------------
+int32_t get_WiFiChannel() {
+    DBG_PRINTLN(ssid);
+    int32_t n = WiFi.scanNetworks();
+    if (n <= 0) return 0;
+    for (uint8_t i = 0; i < n; i++) {
+        if (!strcmp(ssid, WiFi.SSID(i).c_str())) return WiFi.channel(i);
+    }
+    return 0;
+}
+
+void init_WiFi() {
+    WiFi.mode(WIFI_MODE_STA);
+    int32_t channel = get_WiFiChannel();
+    if (channel > 0) {
+        esp_wifi_set_promiscuous(true);
+        esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
+        esp_wifi_set_promiscuous(false);
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+// ESP-NOW handling
+// ----------------------------------------------------------------------------
+
+void on_DataRecv(const esp_now_recv_info *info, const uint8_t *data, int len) {
+    if (!info || !data || len <= 0) return;
+    if (memcmp(info->src_addr, PEER_SENSOR, 6) != 0) return;
+
+    received_starting_message = true;
+
+    PumpConfig_s pump_config;
+    char msg[64];
+    long long unix_now = 0;
+    memcpy(msg, data, len);
+    msg[len] = '\0';
+
+    DBG_PRINTF("Received from server: %s\n", msg);
+
+    if (strncmp(msg, "p:", 2) == 0) {
+
+        int n = sscanf(msg, "p:%lld:%31[^:]:%d:%d:%lld",
+                &unix_now,
+                pump_config.pump_name,
+                &pump_config.pumping_delay_sec,
+                &pump_config.pumping_duration,
+                &pump_config.next_message_unix);
+
+        if (n == 5) {
+            for (size_t i = 0; i < PUMP_COUNT; i++) {
+                if (strcmp(pump_configs[i].pump_name, pump_config.pump_name) != 0)
+                    continue;
+
+                // make sure we keep old data before memcpy
+                pump_config.pumping_started_at_unix = pump_configs[i].pumping_started_at_unix;
+                pump_config.pumping_status = pump_configs[i].pumping_status;
+
+                
+                memcpy(&pump_configs[i], &pump_config, sizeof(PumpConfig_s));
+                next_message_unix = pump_config.next_message_unix;
+
+                DBG_PRINTF("unix_now: %lld\n", unix_now);
+                DBG_PRINTF("pump_name: %s\n", pump_configs[i].pump_name);
+                DBG_PRINTF("pumping_delay_sec: %d\n", pump_configs[i].pumping_delay_sec);
+                DBG_PRINTF("pumping_duration:  %d\n", pump_configs[i].pumping_duration);
+                DBG_PRINTF("next_message_unix: %lld\n", pump_configs[i].next_message_unix);
+
+                if (pump_configs[i].pumping_duration > 0)
+                    pump_configs[i].pumping_status = START;
+                else
+                    received_starting_message = false;
+
+                set_LocalTime(unix_now);
+                return;
+            }
+        } else {
+            DBG_PRINTLN("Failed to parse message");
+        }
+    }
+    received_starting_message = false;
+}
+
+
+void init_EspNow() {
+    if (esp_now_init() != ESP_OK) {
+        DBG_PRINTLN("ESP NOW init failed");
+        while (true);
+    }
+    esp_now_register_recv_cb(on_DataRecv);
+}
+
+
+// ----------------------------------------------------------------------------
+// Deep sleep scheduler
+// ----------------------------------------------------------------------------
+
+void sleep_UntilNextSend(int64_t next_read) {
+
+    DBG_PRINTF("Next read: %lld\n", next_read);
+
+    int64_t now_sec = get_CurrentUnix();
+
+    int64_t delta_sec = next_read - now_sec;
+    if (delta_sec <= 0) delta_sec = 0;
+
+    uint32_t min_delay_ms = delta_sec > UINT32_MAX / 1000
+                          ? UINT32_MAX
+                          : (uint32_t)(delta_sec * 1000);
+
+
+    // Prevent sleeping if next send is within g_min_sleep_time
+    if (min_delay_ms < g_min_sleep_time) {
+        DBG_PRINTF("Delaying for %u ms (no deep sleep)\n", min_delay_ms);
+        DBG_PRINTF("######################\n\n");
+        if (!received_starting_message)
+            delay(min_delay_ms);
+        return;
+    }
+
+    uint32_t prep_time_ms = g_setup_duration + g_wakeup_earlier_pump;
+    uint32_t sleep_time_ms = (min_delay_ms > prep_time_ms)
+                           ? (min_delay_ms - prep_time_ms)
+                           : 0;
+
+
+    esp_sleep_enable_timer_wakeup((uint64_t)sleep_time_ms * 1000ULL);
+    if (!received_starting_message) {
+        DBG_PRINTF("Sleeping for %u ms (setup margin: %u ms)\n",
+                   sleep_time_ms, prep_time_ms);
+        DBG_PRINTF("######################\n\n");
+        esp_deep_sleep_start();
+    }
+}
+
diff --git a/client_pump/ClientPump.h b/client_pump/ClientPump.h
new file mode 100644
index 0000000..4482929
--- /dev/null
+++ b/client_pump/ClientPump.h
@@ -0,0 +1,61 @@
+#ifndef CLIENTPUMP_H
+#define CLIENTPUMP_H
+
+
+#include "globals.h"
+#include "secrets.h"
+
+#include <Arduino.h>
+
+
+extern long long next_message_unix;
+extern bool received_starting_message;
+
+enum PumpSatatus_e {
+    INACTIVE,
+    START,
+    RUNNING,
+    FINISHED
+};
+
+struct PumpConfig_s {
+    char pump_name[32];
+    int pumping_delay_sec;
+    int pumping_duration;
+    long long next_message_unix;
+    long long pumping_started_at_unix;
+    PumpSatatus_e pumping_status;
+};
+
+#define PUMP_COUNT 2
+extern PumpConfig_s pump_configs[PUMP_COUNT];
+
+// ----------------------------------------------------------------------------
+// Time handling
+// ----------------------------------------------------------------------------
+
+int64_t get_CurrentUnix();
+void    setup_Timezone();
+
+// ----------------------------------------------------------------------------
+// WiFi handling
+// ----------------------------------------------------------------------------
+
+void init_WiFi();
+
+
+// ----------------------------------------------------------------------------
+// ESP-NOW handling
+// ----------------------------------------------------------------------------
+
+void init_EspNow();
+
+
+// ----------------------------------------------------------------------------
+// Deep sleep scheduler
+// ----------------------------------------------------------------------------
+
+void sleep_UntilNextSend(int64_t next_read);
+
+
+#endif
diff --git a/client_pump/globals.cpp b/client_pump/globals.cpp
new file mode 120000
index 0000000..3fef46a
--- /dev/null
+++ b/client_pump/globals.cpp
@@ -0,0 +1 @@
+../globals.cpp
\ No newline at end of file
diff --git a/client_pump/globals.h b/client_pump/globals.h
new file mode 120000
index 0000000..caa372d
--- /dev/null
+++ b/client_pump/globals.h
@@ -0,0 +1 @@
+../globals.h
\ No newline at end of file