esp_garden git · master
Distributed ESP sensor and actuator system (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.gzCleanup
client_pump/client_pump.ino | 192 +++-------------------------------------- client_sensor/ClientSensor.cpp | 46 ++++++---- client_sensor/ClientSensor.h | 9 +- 3 files changed, 42 insertions(+), 205 deletions(-) diff --git a/client_pump/client_pump.ino b/client_pump/client_pump.ino index c175419..2b8f923 100644 --- a/client_pump/client_pump.ino +++ b/client_pump/client_pump.ino @@ -1,209 +1,36 @@ -#include "globals.h" -#include "secrets.h" - -#include <Arduino.h> -#include <WiFi.h> -#include <esp_wifi.h> -#include <esp_now.h> -#include <esp_sleep.h> -#include <sys/time.h> - +#include "ClientPump.h" #include "esp_system.h" extern "C" esp_err_t esp_base_mac_addr_set(const uint8_t mac[6]); -long long next_message_unix = 0; -bool go_to_sleep = false; -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; -}; +long long next_message_unix = 0; +bool received_starting_message = false; -#define PUMP_COUNT 2 PumpConfig_s pump_configs[PUMP_COUNT] = { {"pump_1", 0, 0, 0, 0, INACTIVE}, {"pump_2", 0, 0, 0, 0, INACTIVE}, }; -// ---------------------------------------------------------------------------- -// 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; // seconds since epoch - tv.tv_usec = 0; // microseconds - - settimeofday(&tv, nullptr); // set system time -} - -// ---------------------------------------------------------------------------- -// 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; - - 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; - - 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); - - set_LocalTime(unix_now); - - if (pump_configs[i].pumping_duration > 0) { - pump_configs[i].pumping_status = START; - } else { - go_to_sleep = true; - } - break; - } - } else { - DBG_PRINTLN("Failed to parse message"); - } - } -} - - -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) { - go_to_sleep = false; - - 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"); - 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; - - DBG_PRINTF("Sleeping for %u ms (setup margin: %u ms)\n", - sleep_time_ms, prep_time_ms); - DBG_PRINTF("######################\n\n"); - - esp_sleep_enable_timer_wakeup((uint64_t)sleep_time_ms * 1000ULL); - esp_deep_sleep_start(); -} - - void start_Pump(PumpConfig_s& pump_data) { + DBG_PRINTF("Starting Pump %s\n", pump_data.pump_name); pump_data.pumping_started_at_unix = get_CurrentUnix(); pump_data.pumping_status = RUNNING; - DBG_PRINTF("Starting Pump %s\n", pump_data.pump_name); // whatever we have to do to make the pump running } void stop_Pump(PumpConfig_s& pump_data) { - pump_data.pumping_status = INACTIVE; DBG_PRINTF("Stopped Pump %s\n", pump_data.pump_name); + pump_data.pumping_status = INACTIVE; // whatever we have to do to stop the pump } void setup() { uint32_t setup_start = millis(); - go_to_sleep = false; DBG_BEGIN(); @@ -213,6 +40,9 @@ void setup() { init_WiFi(); init_EspNow(); + next_message_unix = 0; + received_starting_message = false; + g_setup_duration = millis() - setup_start; DBG_PRINTF("Setup duration: %u ms\n", g_setup_duration); } @@ -225,20 +55,22 @@ void loop() { if (START == cfg.pumping_status) { - start_Pump(cfg); pumping = true; + received_starting_message = false; + start_Pump(cfg); } else if (RUNNING == cfg.pumping_status) { long long stop_time = cfg.pumping_started_at_unix + cfg.pumping_duration; long long now = get_CurrentUnix(); + // maybe we should add a safety here so we dont pump longer than n seconds,... if (stop_time <= now) stop_Pump(cfg); else pumping = true; } } - if (go_to_sleep && !pumping) + if (!pumping && next_message_unix != 0 && !received_starting_message) sleep_UntilNextSend(next_message_unix); } diff --git a/client_sensor/ClientSensor.cpp b/client_sensor/ClientSensor.cpp index eb8fd6c..4d4993d 100644 --- a/client_sensor/ClientSensor.cpp +++ b/client_sensor/ClientSensor.cpp @@ -1,6 +1,12 @@ #include "ClientSensor.h" #include "secrets.h" +#include <WiFi.h> +#include <esp_wifi.h> +#include <esp_now.h> +#include <esp_sleep.h> +#include <sys/time.h> + volatile bool rtc_synced_with_server = false; volatile bool response_received = false; volatile bool send_process_complete = false; @@ -135,7 +141,7 @@ void on_DataSent(const wifi_tx_info_t* info, esp_now_send_status_t status) { } if (status == ESP_NOW_SEND_SUCCESS) - DBG_PRINTLN(" queued successfully (waiting for Response)"); + DBG_PRINTLN(" queued successfully"); else DBG_PRINTLN(" failed to queue!"); } @@ -420,13 +426,15 @@ int64_t get_NextSensorReadFor(const char* sensor_name) { return -1; } -int64_t get_NextSensorReadsUnixTime() { +int64_t get_NextSensorReadsUnixTime(const uint8_t* mac) { int64_t unix_now = get_CurrentUnix(); int64_t unix_next = INT64_MAX; for (size_t i = 0; i < SENSOR_CONFIG_COUNT; i++) { SensorConfig_s &p = sensor_configs[i]; if (!p.is_active) continue; + if (mac != nullptr && memcmp(mac, p.pump_mac, 6) != 0) continue; + int64_t next_time = get_NextSensorReadFor(p.sensor_name); @@ -692,28 +700,30 @@ void get_AllSensorConfigs() { // ---------------------------------------------------------------------------- -void send_DataToPeer(size_t config_id, uint32_t value) { - char message[64]; - - +void send_DataToPumpAndServer(size_t config_id, uint32_t value, bool shall_pump) { SensorConfig_s& p = sensor_configs[config_id]; + DBG_PRINTF("send_DataToPumpAndServer: %s\n", p.sensor_name); - DBG_PRINTF("send_DataToPeer: %s\n", p.sensor_name); + int pumping_duration = shall_pump ? p.pumping_duration : 0; - snprintf(message, sizeof(message), "%s:%u:%lld", p.sensor_name, value, p.last_sensor_read); + char message[64]; - DBG_PRINT("Sending to peer: "); - printMac(p.pump_mac); - send_response_process_complete = false; - if (!send_AndWaitResponse(p.pump_mac, message)) { - DBG_PRINTLN("Delivery failed or peer offline!"); - send_response_process_complete = true; - } + DBG_PRINT("Sending to Pump: "); printMac(p.pump_mac); + snprintf(message, sizeof(message), "p:%lld:%s:%d:%d:%lld", + get_CurrentUnix(), + p.notification_name, + p.pumping_delay_sec, + pumping_duration, + get_NextSensorReadsUnixTime(p.pump_mac)); - while (!send_response_process_complete) delay(100); + if (!send_Message(p.pump_mac, message)) + DBG_PRINTLN("Delivery failed or peer offline!"); - DBG_PRINT("Sending to peer: "); - printMac(PEER_SERVER); + DBG_PRINT("Sending to Server: "); printMac(PEER_SERVER); + snprintf(message, sizeof(message), "%s:%u:%lld", + p.sensor_name, + value, + p.last_sensor_read); send_response_process_complete = false; if (!send_AndWaitResponse(PEER_SERVER, message)) { DBG_PRINTLN("Failed to get response from server!"); diff --git a/client_sensor/ClientSensor.h b/client_sensor/ClientSensor.h index a874281..0161912 100644 --- a/client_sensor/ClientSensor.h +++ b/client_sensor/ClientSensor.h @@ -4,11 +4,6 @@ #include "globals.h" #include <Arduino.h> -#include <WiFi.h> -#include <esp_wifi.h> -#include <esp_now.h> -#include <esp_sleep.h> -#include <sys/time.h> @@ -51,7 +46,7 @@ void setup_Timezone(); // Deep sleep scheduler // ---------------------------------------------------------------------------- int64_t get_NextSensorReadFor(const char* sensor_name); -int64_t get_NextSensorReadsUnixTime(); +int64_t get_NextSensorReadsUnixTime(const uint8_t* mac = nullptr); void sleep_UntilNextSend(int64_t next_read); // ---------------------------------------------------------------------------- @@ -66,7 +61,7 @@ void process_PendingSensorConfigs(); // ---------------------------------------------------------------------------- bool is_TimeToReadSensor(size_t config_id); -void send_DataToPeer(size_t config_id, uint32_t value); +void send_DataToPumpAndServer(size_t config_id, uint32_t value, bool shall_pump); void send_NextSensorReadToPeer(const uint8_t* mac, int64_t unix_time);