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.gzUpdate working with esp-idf now,- jeii
client_sensor/main/ClientSensor.cpp | 2 +- post_server/main/WiFiManager.cpp | 22 +- post_server/main/main.cpp | 4 - server/main/CMakeLists.txt | 4 +- server/main/Server.cpp | 326 ++++++++++++------------ server/main/Server.h | 2 - server/main/WiFiManager.cpp | 491 +----------------------------------- server/main/WiFiManager.h | 18 +- server/main/main.cpp | 36 ++- server/sdkconfig | 3 +- 10 files changed, 208 insertions(+), 700 deletions(-) diff --git a/client_sensor/main/ClientSensor.cpp b/client_sensor/main/ClientSensor.cpp index bc0ab96..0d05b72 100644 --- a/client_sensor/main/ClientSensor.cpp +++ b/client_sensor/main/ClientSensor.cpp @@ -211,7 +211,7 @@ void on_DataRecv(const esp_now_recv_info *info, const uint8_t *data, int len) { const uint8_t *src = info->src_addr; if (memcmp(src, PEER_SERVER, 6) == 0) { - ESP_LOGI("Ignoring message: unknown sender"); + ESP_LOGI(TAG, "Ignoring message: unknown sender"); return; } diff --git a/post_server/main/WiFiManager.cpp b/post_server/main/WiFiManager.cpp index f77f0fd..c60ab4b 100644 --- a/post_server/main/WiFiManager.cpp +++ b/post_server/main/WiFiManager.cpp @@ -15,13 +15,26 @@ #include "esp_http_client.h" #include "freertos/event_groups.h" -static const char *TAG = "WiFiManager.cpp"; - esp_err_t WiFi_connect() { static const char *TAG = "WiFi_connect"; + + // Initialize NVS + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + + // Initialize TCP/IP stack and default event loop + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + // Initialize Wi-Fi driver wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); cfg.nvs_enable = 0; - esp_wifi_init(&cfg); + + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_WIFI_STA(); @@ -30,7 +43,8 @@ esp_err_t WiFi_connect() { esp_wifi_set_storage(WIFI_STORAGE_RAM); esp_wifi_set_mode(WIFI_MODE_STA); - esp_wifi_start(); + ESP_ERROR_CHECK(esp_wifi_start()); + wifi_config_t wifi_config = { .sta = diff --git a/post_server/main/main.cpp b/post_server/main/main.cpp index e105f6c..9d7ff04 100644 --- a/post_server/main/main.cpp +++ b/post_server/main/main.cpp @@ -16,10 +16,6 @@ extern "C" void app_main() { static const char *TAG = "app_main"; xTaskCreate([](void*) { - esp_netif_init(); - nvs_flash_init(); - esp_event_loop_create_default(); - WiFi_connect(); vTaskDelay(10000 / portTICK_PERIOD_MS); diff --git a/server/main/CMakeLists.txt b/server/main/CMakeLists.txt index 61e175f..bf21135 100644 --- a/server/main/CMakeLists.txt +++ b/server/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register( - SRCS "main.cpp" "Server.cpp" "globals.cpp" + SRCS "main.cpp" "Server.cpp" "WiFiManager.cpp" "globals.cpp" INCLUDE_DIRS "." - REQUIRES esp_timer freertos esp_system esp_wifi esp_event nvs_flash + REQUIRES esp_timer freertos esp_system esp_wifi esp_event nvs_flash esp_http_client ) diff --git a/server/main/Server.cpp b/server/main/Server.cpp index 554436f..7c7ca83 100644 --- a/server/main/Server.cpp +++ b/server/main/Server.cpp @@ -2,7 +2,15 @@ #include "secrets.h" #include "WiFiManager.h" -#include <esp_now.h> +#include <esp_sleep.h> +#include "esp_wifi_types.h" +#include "esp_now.h" +#include "esp_log.h" +#include <sys/time.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> uint8_t received_from_mac_addr[6]; @@ -12,272 +20,258 @@ uint8_t received_from_mac_addr[6]; // Helper // ---------------------------------------------------------------------------- +int64_t get_CurrentUnix() { + return (int64_t)time(nullptr); +} + +void printMac(const uint8_t* mac) { + if (!mac) return; + ESP_LOGI("APP", "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); +} + void print_SensorConfigServer(const SensorConfigServer_s& cfg) { - DBG_PRINTLN("----------------------------"); - DBG_PRINTF("Got cfg for moisture_1:\n"); - DBG_PRINTF("Pin: %d\n", cfg.pin); - DBG_PRINTF("Use Time: %d\n", cfg.use_time); - DBG_PRINTF("Delay: %d\n", cfg.delay_ms); - DBG_PRINTF("Notification Name: %s\n", cfg.notification_name); - DBG_PRINTF("Min Moisture: %d\n", cfg.min_moisture); - DBG_PRINTF("Active: %d\n", cfg.is_active); - DBG_PRINTF("Pumping Delay: %d\n", cfg.pumping_delay_sec); - DBG_PRINTF("Pumping Duration: %d\n", cfg.pumping_duration); + static const char *TAG = "print_SensorConfig"; + ESP_LOGI(TAG, "----------------------------"); + ESP_LOGI(TAG, "Got cfg for moisture_1:"); + ESP_LOGI(TAG, "Pin: %d", cfg.pin); + ESP_LOGI(TAG, "Use Time: %d", cfg.use_time); + ESP_LOGI(TAG, "Delay: %d", cfg.delay_ms); + ESP_LOGI(TAG, "Notification Name: %s", cfg.notification_name); + ESP_LOGI(TAG, "Min Moisture: %d", cfg.min_moisture); + ESP_LOGI(TAG, "Active: %d", cfg.is_active); + ESP_LOGI(TAG, "Pumping Delay: %d", cfg.pumping_delay_sec); + ESP_LOGI(TAG, "Pumping Duration: %d", cfg.pumping_duration); for (uint8_t i = 0; i < cfg.time_count; i++) { uint16_t minutes = cfg.times[i]; uint8_t hh = minutes / 60; uint8_t mm = minutes % 60; - DBG_PRINTF("Time[%d]: %02u:%02u (%u min)\n", i, hh, mm, minutes); + ESP_LOGI(TAG, "Time[%d]: %02u:%02u (%u min)", i, hh, mm, minutes); } - DBG_PRINTLN("----------------------------"); + ESP_LOGI(TAG, "----------------------------"); } -// ---------------------------------------------------------------------------- -// Server handling (g_buffer) - // ---------------------------------------------------------------------------- - -void add_ReadingCallback(const char* table, const char* value, const int64_t time, const bool pump_reached) { - if (g_buffer_count >= BUFFER_SIZE) { - for (int i = 1; i < g_buffer_count; i++) g_buffer[i-1] = g_buffer[i]; - g_buffer_count--; - } - strncpy(g_buffer[g_buffer_count].table, table, TABLE_SIZE-1); - g_buffer[g_buffer_count].table[TABLE_SIZE-1] = '\0'; - strncpy(g_buffer[g_buffer_count].value, value, VALUE_SIZE-1); - g_buffer[g_buffer_count].time = time; - g_buffer[g_buffer_count].pump_reached = pump_reached; - g_buffer_count++; -} - -void init_Server() { - WIFI_OnAddReading = add_ReadingCallback; -} // ---------------------------------------------------------------------------- -// WiFi handling +// ESP-NOW helpers // ---------------------------------------------------------------------------- -#include "esp_wifi.h" - -void init_WiFi() { - WiFi.mode(WIFI_MODE_APSTA); - - WiFi.begin(ssid, password); +void on_DataSent(const wifi_tx_info_t *info, esp_now_send_status_t status) { + static const char *TAG = "on_DataSent"; - DBG_PRINTF("Connecting to %s .", ssid); - while (WiFi.status() != WL_CONNECTED) { DBG_PRINT("."); delay(200); } - DBG_PRINTLN(" ok"); + if (!info) return; - IPAddress ip = WiFi.localIP(); + const uint8_t *mac_addr = info->des_addr; // destination MAC - DBG_PRINTF("SSID: %s\n", ssid); - DBG_PRINTF("Channel: %u\n", WiFi.channel()); - DBG_PRINTF("IP: %u.%u.%u.%u\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, ip >> 24); + ESP_LOGI(TAG, "Delivery to %02X:%02X:%02X:%02X:%02X:%02X %s", + mac_addr[0], mac_addr[1], mac_addr[2], + mac_addr[3], mac_addr[4], mac_addr[5], + status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAIL"); } -// ---------------------------------------------------------------------------- -// ESP-NOW helpers (add peer + send callback) -// ---------------------------------------------------------------------------- +void add_Peer(const uint8_t *addr) +{ + if (!addr) return; -void on_DataSent(const wifi_tx_info_t *info, esp_now_send_status_t status) { - if (!info) return; - - DBG_PRINT("Delivery to "); - for (int i = 0; i < 6; i++) { - DBG_PRINTF("%02X", info->des_addr[i]); - if (i < 5) DBG_PRINT(":"); - } - DBG_PRINT(" -> "); - DBG_PRINTLN(status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAIL"); -} - -void add_Peer(const uint8_t* addr) { if (esp_now_is_peer_exist(addr)) return; - esp_now_peer_info_t peer{}; + esp_now_peer_info_t peer = {0}; memcpy(peer.peer_addr, addr, 6); - peer.ifidx = WIFI_IF_STA; // server is in APSTA mode but acts as STA on same SSID - peer.channel = (uint8_t)WiFi.channel(); // ensure same channel + peer.ifidx = WIFI_IF_STA; + peer.channel = 0; // auto-select current Wi-Fi channel peer.encrypt = false; - esp_err_t res = esp_now_add_peer(&peer); - if (res != ESP_OK) { - DBG_PRINT("Failed to add peer: "); - for (int i=0; i<6; i++) { - DBG_PRINTF("%02X", addr[i]); - if (i<5) DBG_PRINT(":"); - } - DBG_PRINTF(" -> error code %d\n", res); - } else { - DBG_PRINT("Added peer: "); - for (int i=0; i<6; i++) { - DBG_PRINTF("%02X", addr[i]); - if (i<5) DBG_PRINT(":"); - } - DBG_PRINTLN(""); - } + esp_now_add_peer(&peer); } + // ---------------------------------------------------------------------------- // ESP-NOW receive callback // ---------------------------------------------------------------------------- -void on_DataRecv(const esp_now_recv_info *info, const uint8_t *data, int len) { +void add_Reading(const char* table, const char* value, const int64_t time, const bool pump_reached) { + if (g_buffer_count >= BUFFER_SIZE) { + for (int i = 1; i < g_buffer_count; i++) g_buffer[i-1] = g_buffer[i]; + g_buffer_count--; + } + strncpy(g_buffer[g_buffer_count].table, table, TABLE_SIZE-1); + g_buffer[g_buffer_count].table[TABLE_SIZE-1] = '\0'; + strncpy(g_buffer[g_buffer_count].value, value, VALUE_SIZE-1); + g_buffer[g_buffer_count].time = time; + g_buffer[g_buffer_count].pump_reached = pump_reached; + g_buffer_count++; +} + +void on_DataRecv(const esp_now_recv_info_t *info, const uint8_t *data, int len) { + static const char *TAG = "on_DataRecv"; + if (!info || !data || len <= 0) return; + memcpy(received_from_mac_addr, info->src_addr, 6); add_Peer(received_from_mac_addr); char msg[128]; - int copylen = len < (int)sizeof(msg)-1 ? len : (int)sizeof(msg)-1; + int copylen = len < (int)sizeof(msg) - 1 ? len : (int)sizeof(msg) - 1; memcpy(msg, data, copylen); msg[copylen] = '\0'; - DBG_PRINTF("Received from %02X:%02X:%02X:%02X:%02X:%02X: %s\n", - received_from_mac_addr[0], received_from_mac_addr[1], received_from_mac_addr[2], - received_from_mac_addr[3], received_from_mac_addr[4], received_from_mac_addr[5], msg); + ESP_LOGI(TAG, "Received from %02X:%02X:%02X:%02X:%02X:%02X: %s", + received_from_mac_addr[0], received_from_mac_addr[1], received_from_mac_addr[2], + received_from_mac_addr[3], received_from_mac_addr[4], received_from_mac_addr[5], + msg); if (strcmp(msg, "time?") == 0) { char time_msg[32]; - snprintf(time_msg, sizeof(time_msg), "time:%lld", now()); - esp_now_send(received_from_mac_addr, (uint8_t*)time_msg, strlen(time_msg)); + snprintf(time_msg, sizeof(time_msg), "time:%lld", get_CurrentUnix()); + esp_now_send(received_from_mac_addr, (uint8_t *)time_msg, strlen(time_msg)); return; } - // Queue config request instead of calling HTTP directly if (strncmp(msg, "next_read:", 10) == 0) { - - const char* value_str = msg + 10; + const char *value_str = msg + 10; next_connection_unix = atoll(value_str); go_to_sleep = true; - DBG_PRINTF("Received next_read: %lld\n", next_connection_unix); + ESP_LOGI(TAG, "Received next_read: %lld", next_connection_unix); return; + } - } else if (strncmp(msg, "get_config:", 11) == 0 && !pending_config.active) { - + if (strncmp(msg, "get_config:", 11) == 0 && !pending_config.active) { pending_config.active = true; memcpy(pending_config.mac, received_from_mac_addr, 6); strncpy(pending_config.sensor_name, msg + 11, sizeof(pending_config.sensor_name) - 1); pending_config.sensor_name[sizeof(pending_config.sensor_name) - 1] = '\0'; - DBG_PRINTF("Queued config request for %s\n", pending_config.sensor_name); + ESP_LOGI(TAG, "Queued config request for %s", pending_config.sensor_name); return; } - // --- Normal table:value:time:pump_reached handling --- - DBG_PRINTLN("Message:"); - DBG_PRINTF(" %s\n", msg); + ESP_LOGI(TAG, "Message: %s", msg); g_received_ok_from_server = false; - char *first = strchr(msg, ':'); - char *second = first ? strchr(first + 1, ':') : NULL; - char *third = second ? strchr(second + 1, ':') : NULL; + char *first = strchr(msg, ':'); + char *second = first ? strchr(first + 1, ':') : NULL; + char *third = second ? strchr(second + 1, ':') : NULL; if (first && second && third) { *first = '\0'; *second = '\0'; *third = '\0'; - const char *sensor_name = msg; - const char *value_str = first + 1; - const int64_t time = atoll(second + 1); - const bool pump_reached = (*(third + 1) == '1'); + const char *sensor_name = msg; + const char *value_str = first + 1; + int64_t time = atoll(second + 1); + bool pump_reached = (*(third + 1) == '1'); - add_ReadingCallback(sensor_name, value_str, time, pump_reached); + add_Reading(sensor_name, value_str, time, pump_reached); } else { - DBG_PRINTLN("Invalid message format (expected <name>:<value>:<time>:<reached_pump>)"); + ESP_LOGW(TAG, "Invalid message format (expected <name>:<value>:<time>:<reached_pump>)"); } - /* - * Replying to Sensor happens in main loop - */ + // Response deferred to main loop } - // ---------------------------------------------------------------------------- // Init ESP-NOW // ---------------------------------------------------------------------------- void init_EspNow() { + static const char *TAG = "init_EspNow"; + if (esp_now_init() != ESP_OK) { - DBG_PRINTLN("ESP-NOW failed to initialize"); + ESP_LOGI(TAG, "ESP NOW init failed"); while (true); } - - esp_now_register_recv_cb(on_DataRecv); esp_now_register_send_cb(on_DataSent); + esp_now_register_recv_cb(on_DataRecv); } + // ---------------------------------------------------------------------------- // Config handling // ---------------------------------------------------------------------------- -void get_PendingConfigFromServer() { +void get_PendingConfigFromServer(void) { + static const char *TAG = "get_PendingConfigFromServer"; + pending_config.active = false; - SensorConfigServer_s cfg_response; + SensorConfigServer_s cfg_response = {0}; if (WIFI_GetSensorConfigServer(pending_config.sensor_name, cfg_response)) { + char response[250]; int len_out = snprintf(response, sizeof(response), - "cfg:%s,%d,%d,%d,%s,%d,%d,%d,%d", - cfg_response.sensor_name, - cfg_response.is_active, - cfg_response.pin, - cfg_response.min_moisture, - cfg_response.notification_name, - cfg_response.pumping_delay_sec, - cfg_response.pumping_duration, - cfg_response.delay_ms, - cfg_response.use_time); + "cfg:%s,%d,%d,%d,%s,%d,%d,%d,%d", + cfg_response.sensor_name, + cfg_response.is_active, + cfg_response.pin, + cfg_response.min_moisture, + cfg_response.notification_name, + cfg_response.pumping_delay_sec, + cfg_response.pumping_duration, + cfg_response.delay_ms, + cfg_response.use_time); if (cfg_response.time_count > 0) { - strncat(response, ",times=", sizeof(response)-strlen(response)-1); + strncat(response, ",times=", sizeof(response) - strlen(response) - 1); for (uint8_t i = 0; i < cfg_response.time_count; i++) { char buf[8]; snprintf(buf, sizeof(buf), "%u", cfg_response.times[i]); - strncat(response, buf, sizeof(response)-strlen(response)-1); + strncat(response, buf, sizeof(response) - strlen(response) - 1); if (i < cfg_response.time_count - 1) - strncat(response, "|", sizeof(response)-strlen(response)-1); + strncat(response, "|", sizeof(response) - strlen(response) - 1); } } - esp_now_send(pending_config.mac, (uint8_t*)response, strlen(response)); - DBG_PRINTF("Sent config for %s\n", cfg_response.sensor_name); - DBG_PRINTF("Sending: %s\n", response); + esp_err_t res = esp_now_send(pending_config.mac, (uint8_t *)response, strlen(response)); + if (res == ESP_OK) + ESP_LOGI(TAG, "Sent config for %s: %s", cfg_response.sensor_name, response); + else + ESP_LOGW(TAG, "Failed to send config for %s (err=%d)", cfg_response.sensor_name, res); + } else { - const char* err = "cfg_error:fetch_failed"; - esp_now_send(pending_config.mac, (uint8_t*)err, strlen(err)); - DBG_PRINTLN("Config fetch failed"); + const char *err = "cfg_error:fetch_failed"; + esp_err_t res = esp_now_send(pending_config.mac, (uint8_t *)err, strlen(err)); + ESP_LOGW(TAG, "Config fetch failed (send result=%d)", res); } } -void send_ConfigToEsp() { - DBG_PRINTLN("Preparing time + configs message"); +void send_ConfigToEsp(void) { + static const char *TAG = "send_ConfigToEsp"; + + ESP_LOGI(TAG, "Preparing time + configs message"); + char msg[256]; size_t offset = 0; time_t now_t; time(&now_t); - offset += snprintf(msg + offset, sizeof(msg) - offset, "time:%lu", (unsigned long)now_t); + offset += snprintf(msg + offset, sizeof(msg) - offset, + "time:%lu", (unsigned long) now_t); - // add configs if available + // append configs if available if (g_pending_sensor_configs_count > 0) { - DBG_PRINTLN("Appending pending configs..."); + ESP_LOGI(TAG, "Appending pending configs..."); for (size_t i = 0; i < g_pending_sensor_configs_count; i++) { - DBG_PRINTF(" adding config: %s\n", g_pending_sensor_configs[i]); - offset += snprintf(msg + offset, sizeof(msg) - offset, ",cfg:%s", g_pending_sensor_configs[i]); - if (offset >= sizeof(msg)) break; + ESP_LOGI(TAG, " adding config: %s", g_pending_sensor_configs[i]); + offset += snprintf(msg + offset, + sizeof(msg) - offset, + ",cfg:%s", g_pending_sensor_configs[i]); + if (offset >= sizeof(msg)) + break; } g_pending_sensor_configs_count = 0; } - DBG_PRINTLN("Sending combined message:"); - DBG_PRINTLN(msg); + ESP_LOGI(TAG, "Sending combined message: %s", msg); + + esp_err_t res = esp_now_send(received_from_mac_addr, + (uint8_t *)msg, + strlen(msg)); - esp_err_t result = esp_now_send(received_from_mac_addr, (uint8_t*)msg, strlen(msg)); - if (result == ESP_OK) - DBG_PRINTLN("Send queued successfully."); + if (res == ESP_OK) + ESP_LOGI(TAG, "Send queued successfully"); else - DBG_PRINTF("Send failed: %d\n", result); + ESP_LOGW(TAG, "Send failed, err=%d", res); g_received_ok_from_server = false; } @@ -288,40 +282,40 @@ void send_ConfigToEsp() { // ---------------------------------------------------------------------------- void sleep_UntilNextReceive() { + static const char *TAG = "sleep_UntilNextSend"; + go_to_sleep = false; - uint32_t min_delay_ms = (next_connection_unix - now())*1000; - /////////////////////////// - int64_t unix_now = now(); + int64_t now_sec = get_CurrentUnix(); - int64_t delta_sec = next_connection_unix - unix_now; + int64_t delta_sec = next_connection_unix - 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); - if (next_connection_unix < unix_now) return; + if (next_connection_unix < now_sec) return; - DBG_PRINTF("Nex: %lld\nNow: %lld\n", next_connection_unix, unix_now); + ESP_LOGI(TAG, "Nex: %lld\nNow: %lld", next_connection_unix, now_sec); next_connection_unix = 0; // 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); + ESP_LOGI(TAG, "Delaying for %u ms (no deep sleep)", min_delay_ms); + ESP_LOGI(TAG, "######################"); vTaskDelay(pdMS_TO_TICKS(min_delay_ms)); return; } - uint32_t prep_time_ms = g_setup_duration + g_wakeup_earlier_server; - uint32_t sleep_time_ms = (min_delay_ms > prep_time_ms) - ? (min_delay_ms - prep_time_ms) - : 0; + uint32_t prep_time_ms = g_setup_duration + g_wakeup_earlier_sensor; + 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_LOGI(TAG, "Sleeping for %u ms (setup margin: %u ms)", + sleep_time_ms, prep_time_ms); + ESP_LOGI(TAG, "######################"); esp_sleep_enable_timer_wakeup((uint64_t)sleep_time_ms * 1000ULL); esp_deep_sleep_start(); diff --git a/server/main/Server.h b/server/main/Server.h index a17c1be..4d83ea4 100644 --- a/server/main/Server.h +++ b/server/main/Server.h @@ -3,8 +3,6 @@ #include "globals.h" -#include <Arduino.h> - extern int64_t next_connection_unix; extern bool go_to_sleep; diff --git a/server/main/WiFiManager.cpp b/server/main/WiFiManager.cpp deleted file mode 100644 index 3865eeb..0000000 --- a/server/main/WiFiManager.cpp +++ /dev/null @@ -1,490 +0,0 @@ -#include "WiFiManager.h" -#include "secrets.h" -#include "globals.h" - -#include "esp_wifi.h" -#include "esp_event.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp_err.h" -#include "nvs_flash.h" -#include "esp_netif.h" -#include "lwip/err.h" -#include "lwip/sys.h" -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "freertos/task.h" -#include "sdkconfig.h" -#include "lwip/apps/sntp.h" -#include <time.h> - -#include "esp_http_client.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_timer.h" -#include <string.h> -#include <stdlib.h> - -#include "esp_http_client.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "cJSON.h" -#include <string.h> - -static const char *TAG = "WIFI"; - -static EventGroupHandle_t s_wifi_event_group; -static const int WIFI_CONNECTED_BIT = BIT0; - -bool wifi_is_connected(void) -{ - wifi_ap_record_t ap; - return esp_wifi_sta_get_ap_info(&ap) == ESP_OK; -} - - - -// helper -static void encode_UrlToBuf(const char *in, char *out, size_t out_sz) { - const char *hex = "0123456789ABCDEF"; - size_t pos = 0; - while (*in && pos + 4 < out_sz) { - unsigned char c = (unsigned char)*in++; - if ( (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || - c == '-' || c == '_' || c == '.' || c == '~') { - out[pos++] = c; - } else { - out[pos++] = '%'; - out[pos++] = hex[(c >> 4) & 0xF]; - out[pos++] = hex[c & 0xF]; - } - } - out[pos] = '\0'; -} - -WIFI_ReadingCallback WIFI_OnAddReading = nullptr; - -bool WIFI_GetSensorConfigServer(const char *sensor_name, SensorConfigServer_s &cfg) -{ - if (!wifi_is_connected()) { - ESP_LOGW(TAG, "WiFi not connected"); - return false; - } - - char name_enc[32]; - encode_UrlToBuf(sensor_name, name_enc, sizeof(name_enc)); - - char url[256]; - snprintf(url, sizeof(url), - "https://%s/get_sensor_config.php?name=%s", - server_host, name_enc); - - esp_http_client_config_t config = { - .url = url, - .transport_type = HTTP_TRANSPORT_OVER_SSL, - .skip_cert_common_name_check = true, - .timeout_ms = 5000, - }; - - esp_http_client_handle_t client = esp_http_client_init(&config); - if (!client) 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 request failed: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); - return false; - } - - int status = esp_http_client_get_status_code(client); - if (status != 200) { - ESP_LOGW(TAG, "Server returned status %d", status); - esp_http_client_cleanup(client); - return false; - } - - int content_length = esp_http_client_get_content_length(client); - if (content_length <= 0 || content_length > 2048) { - ESP_LOGW(TAG, "Invalid response length: %d", content_length); - esp_http_client_cleanup(client); - return false; - } - - char *body = (char *)malloc(content_length + 1); - if (!body) { - esp_http_client_cleanup(client); - return false; - } - - int read_len = esp_http_client_read(client, body, content_length); - body[read_len > 0 ? read_len : 0] = '\0'; - esp_http_client_cleanup(client); - - ESP_LOGI(TAG, "Response: %s", body); - - memset(&cfg, 0, sizeof(cfg)); - - /* --- Parse JSON --- */ - cJSON *root = cJSON_Parse(body); - free(body); - if (!root) { - ESP_LOGW(TAG, "Failed to parse JSON"); - return false; - } - - cfg.success = cJSON_IsTrue(cJSON_GetObjectItem(root, "success")); - cfg.pin = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "pin")); - cfg.use_time = cJSON_IsTrue(cJSON_GetObjectItem(root, "use_time")); - cfg.delay_ms = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "delay_ms")); - cfg.min_moisture = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "min_moisture")); - cfg.is_active = cJSON_IsTrue(cJSON_GetObjectItem(root, "is_active")); - cfg.pumping_delay_sec= cJSON_GetNumberValue(cJSON_GetObjectItem(root, "pumping_delay_sec")); - cfg.pumping_duration = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "pumping_duration")); - - const char *sname = cJSON_GetStringValue(cJSON_GetObjectItem(root, "sensor_name")); - const char *nname = cJSON_GetStringValue(cJSON_GetObjectItem(root, "notification_name")); - if (sname) strncpy(cfg.sensor_name, sname, sizeof(cfg.sensor_name)-1); - if (nname) strncpy(cfg.notification_name, nname, sizeof(cfg.notification_name)-1); - - cfg.time_count = 0; - cJSON *times = cJSON_GetObjectItem(root, "times"); - if (cJSON_IsArray(times)) { - int count = cJSON_GetArraySize(times); - for (int i = 0; i < count && i < 8; i++) { - cJSON *t = cJSON_GetArrayItem(times, i); - if (cJSON_IsNumber(t)) { - cfg.times[cfg.time_count++] = (uint16_t)t->valueint; - } - } - } - - ESP_LOGI(TAG, - "Parsed: 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); - - cJSON_Delete(root); - return cfg.success; -} - -int64_t now() { - return (int64_t)time(nullptr); -} - -//// WIFI TRY START - -static void wifi_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) -{ - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { - esp_wifi_connect(); - } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - ESP_LOGI(TAG, "Disconnected - will try to reconnect"); - esp_wifi_connect(); - xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { - ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; - ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip)); - xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); - } -} - - -static esp_err_t wifi_init_sta(void) -{ - esp_err_t err; - - if (s_wifi_event_group == NULL) { - s_wifi_event_group = xEventGroupCreate(); - if (s_wifi_event_group == NULL) return ESP_ERR_NO_MEM; - } - - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, - ESP_EVENT_ANY_ID, - &wifi_event_handler, - NULL, - NULL)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &wifi_event_handler, - NULL, - NULL)); - - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_start()); - - return ESP_OK; -} - -void WIFI_Try(uint8_t max_attempts) -{ - // if already connected -> nothing to do - EventBits_t bits = xEventGroupGetBits(s_wifi_event_group ? s_wifi_event_group : NULL); - if (bits & WIFI_CONNECTED_BIT) return; - - // ensure WiFi stack and event handler are initialized once - if (wifi_init_sta() != ESP_OK) { - ESP_LOGE(TAG, "wifi_init_sta failed"); - return; - } - - // assume `ssid` and `password` are const char* (adapt if stored differently) - char ssid_buf[33] = {0}; - char password_buf[65] = {0}; - // Copy safely. If you used PROGMEM earlier, adapt to how secrets are stored. - strncpy(ssid_buf, ssid, sizeof(ssid_buf) - 1); - strncpy(password_buf, password, sizeof(password_buf) - 1); - - wifi_config_t wifi_config = {}; - strncpy((char*)wifi_config.sta.ssid, ssid_buf, sizeof(wifi_config.sta.ssid) - 1); - strncpy((char*)wifi_config.sta.password, password_buf, sizeof(wifi_config.sta.password) - 1); - wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; - wifi_config.sta.pmf_cfg.capable = true; - wifi_config.sta.pmf_cfg.required = false; - - ESP_LOGI(TAG, "Connecting to WiFi: %s", ssid_buf); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); - ESP_ERROR_CHECK(esp_wifi_connect()); - - // Wait for connection (poll event group's WIFI_CONNECTED_BIT). - // We mimic original behaviour: delay 250ms per attempt, up to max_attempts - uint8_t attempts = 0; - const TickType_t delay_ticks = pdMS_TO_TICKS(250); - while (!(xEventGroupGetBits(s_wifi_event_group) & WIFI_CONNECTED_BIT) && attempts++ < max_attempts) { - vTaskDelay(delay_ticks); - ESP_LOGI(TAG, "."); - } - - if (xEventGroupGetBits(s_wifi_event_group) & WIFI_CONNECTED_BIT) { - ESP_LOGI(TAG, "connected!"); - WIFI_SyncTime(); - } else { - ESP_LOGI(TAG, "failed!"); - } -} - - - - -/// WIFI TRY END - -void WIFI_SyncTime() -{ - ESP_LOGI(TAG, "Syncing time..."); - - // initialize SNTP - sntp_setoperatingmode(SNTP_OPMODE_POLL); - sntp_setservername(0, NTP_SERVER); // NTP_SERVER should be a const char* with hostname - sntp_init(); - - time_t t = time(nullptr); - uint8_t tries = 0; - while (t < 1600000000 && tries++ < 20) { - vTaskDelay(pdMS_TO_TICKS(500)); - t = time(nullptr); - } - - if (t < 1600000000) { - ESP_LOGW(TAG, "NTP sync failed!"); - } else { - ESP_LOGI(TAG, "Time synced: %lld", (long long)t); - } -} - -/* -bool WIFI_PostBuffer() { - DBG_PRINTLN("Posting g_buffer called!"); - if (g_buffer_count == 0 || WiFi.status() != WL_CONNECTED) return false; - char json[JSON_BUFFER_SIZE]; - int len = snprintf(json, sizeof(json), "["); - if (len < 0 || len >= (int)sizeof(json)) { - DBG_PRINTLN("JSON g_buffer overflow at start!"); - return false; - } - - for (uint8_t i = 0; i < g_buffer_count; i++) { - DBG_PRINTF("Positng creating g_buffer %d %s %s\n", i, g_buffer[i].table, g_buffer[i].value); - int n; - if (i) { - n = snprintf(json + len, sizeof(json) - len, ","); - if (n < 0 || n >= (int)(sizeof(json)-len)) return false; - len += n; - } - n = snprintf(json + len, sizeof(json) - len, - "{\"table\":\"%s\",\"value\":\"%s\",\"time\":%u}", - g_buffer[i].table, g_buffer[i].value, g_buffer[i].time); - if (n < 0 || n >= (int)(sizeof(json)-len)) return false; - len += n; - } - len += snprintf(json + len, sizeof(json) - len, "]"); - - DBG_PRINTLN("Posting copying stuff!"); - char host_buf[64], path_buf[64], token_buf[64]; - strcpy_P(host_buf, server_host); - strcpy_P(path_buf, server_path); - strcpy_P(token_buf, api_token); - - WiFiClientSecure client; - client.setInsecure(); - DBG_PRINTF("Connecting to %s:%d\n", host_buf, server_port); - if (!client.connect(host_buf, server_port)) return false; - - DBG_PRINTLN("Posting creating post stuff!"); - client.printf( - "POST %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Content-Type: application/json\r\n" - "X-API-Token: %s\r\n" - "Content-Length: %d\r\n" - "Connection: close\r\n\r\n", - path_buf, host_buf, token_buf, len - ); - client.write((const uint8_t*)json, len); - - DBG_PRINTLN("HTTP response:"); - bool success = false; - uint32_t t_start = millis(); - while (client.connected() && millis() - t_start < 3000) { - if (client.available()) { - char line[64]; - int n = client.readBytesUntil('\n', line, sizeof(line)-1); - line[n] = 0; - DBG_PRINTLN(line); - if (strstr(line, "200 OK")) success = true; - } - } - client.stop(); - - if (success) g_buffer_count = 0; - return success; -} -*/ - -bool WIFI_PostBufferSync(void) -{ - if (g_buffer_count == 0) return false; - - /* --- Build JSON payload --- */ - char json[JSON_BUFFER_SIZE]; - int len = snprintf(json, sizeof(json), "["); - if (len < 0 || len >= (int)sizeof(json)) return false; - - for (uint8_t i = 0; i < g_buffer_count; i++) { - if (i) - len += snprintf(json + len, sizeof(json) - len, ","); - len += snprintf(json + len, sizeof(json) - len, - "{\"table\":\"%s\",\"value\":\"%s\",\"time\":%lld,\"pump_reached\":%d}", - g_buffer[i].table, g_buffer[i].value, - (long long)g_buffer[i].time, g_buffer[i].pump_reached); - if (len >= (int)sizeof(json)) return false; - } - len += snprintf(json + len, sizeof(json) - len, "]"); - - /* --- Configure HTTPS client --- */ - char url[128]; - snprintf(url, sizeof(url), "https://%s%s", server_host, server_path); - - esp_http_client_config_t cfg = { - .url = url, - .transport_type = HTTP_TRANSPORT_OVER_SSL, - .skip_cert_common_name_check = true, // similar to setInsecure() - .timeout_ms = 5000, - }; - - esp_http_client_handle_t client = esp_http_client_init(&cfg); - if (!client) return false; - - esp_http_client_set_method(client, HTTP_METHOD_POST); - esp_http_client_set_header(client, "Content-Type", "application/json"); - esp_http_client_set_header(client, "X-API-Token", api_token); - esp_http_client_set_post_field(client, json, len); - - ESP_LOGI(TAG, "POST %s (len=%d)", url, len); - - esp_err_t err = esp_http_client_perform(client); - if (err != ESP_OK) { - ESP_LOGW(TAG, "HTTP request failed: %s", esp_err_to_name(err)); - esp_http_client_cleanup(client); - return false; - } - - int status = esp_http_client_get_status_code(client); - int content_length = esp_http_client_get_content_length(client); - ESP_LOGI(TAG, "HTTP status=%d, length=%d", status, content_length); - - bool success = (status == 200); - - /* --- Read response body (optional) --- */ - char *body = NULL; - if (content_length > 0 && content_length < 2048) { - body = (char*)malloc(content_length + 1); - if (body) { - int r = esp_http_client_read(client, body, content_length); - if (r > 0) body[r] = '\0'; - } - } - - esp_http_client_cleanup(client); - - g_buffer_count = 0; - g_pending_sensor_configs_count = 0; - - if (!success) { - g_received_ok_from_server = true; - free(body); - return false; - } - - /* --- Parse pending_sensors from body --- */ - if (body) { - const char *key = "\"pending_sensors\":["; - char *start = strstr(body, key); - if (start) { - start += strlen(key); - char *end = strchr(start, ']'); - if (end) { - *end = '\0'; - char *token = strtok(start, ","); - while (token && g_pending_sensor_configs_count < 4) { - while (*token == ' ' || *token == '"' || *token == '\'') - token++; - char *term = token + strlen(token) - 1; - while (term > token && (*term == '"' || *term == '\'' || *term == ' ')) - *term-- = '\0'; - - strncpy(g_pending_sensor_configs[g_pending_sensor_configs_count], - token, - sizeof(g_pending_sensor_configs[0]) - 1); - g_pending_sensor_configs_count++; - token = strtok(NULL, ","); - } - ESP_LOGI(TAG, "COUNTED: %d", g_pending_sensor_configs_count); - } - } - free(body); - } - - for (size_t i = 0; i < g_pending_sensor_configs_count; i++) - ESP_LOGI(TAG, "%s", g_pending_sensor_configs[i]); - - g_received_ok_from_server = true; - return true; -} diff --git a/server/main/WiFiManager.cpp b/server/main/WiFiManager.cpp new file mode 120000 index 0000000..ccf03b2 --- /dev/null +++ b/server/main/WiFiManager.cpp @@ -0,0 +1 @@ +../../post_server/main/WiFiManager.cpp \ No newline at end of file diff --git a/server/main/WiFiManager.h b/server/main/WiFiManager.h deleted file mode 100644 index f80a2f7..0000000 --- a/server/main/WiFiManager.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include <Arduino.h> -#include <WiFi.h> -#include <WiFiClientSecure.h> - -#include "globals.h" - -bool WIFI_GetSensorConfigServer(const char* sensor_name, SensorConfigServer_s &cfg); - -using WIFI_ReadingCallback = void(*)(const char* table, const char* value, const int64_t time, const bool pump_reached); -extern WIFI_ReadingCallback WIFI_OnAddReading; - -int64_t now(); -void WIFI_Try(uint8_t max_attempts = 20); -void WIFI_SyncTime(); -bool WIFI_PostBuffer(); -bool WIFI_PostBufferSync(); diff --git a/server/main/WiFiManager.h b/server/main/WiFiManager.h new file mode 120000 index 0000000..0150723 --- /dev/null +++ b/server/main/WiFiManager.h @@ -0,0 +1 @@ +../../post_server/main/WiFiManager.h \ No newline at end of file diff --git a/server/main/main.cpp b/server/main/main.cpp index bf81775..2968ad7 100644 --- a/server/main/main.cpp +++ b/server/main/main.cpp @@ -12,31 +12,41 @@ PendingConfigRequest_s pending_config; extern "C" void server_loop(void*) { - if (pending_config.active) - get_PendingConfigFromServer(); + while (true) { + if (pending_config.active) + get_PendingConfigFromServer(); - if (g_buffer_count > 0) - WIFI_PostBufferSync(); + if (g_buffer_count > 0) + WiFi_PostDataToServer(g_buffer_count, g_buffer); - if (g_received_ok_from_server) - send_ConfigToEsp(); + if (g_received_ok_from_server) + send_ConfigToEsp(); - if (go_to_sleep) - sleep_UntilNextReceive(); + if (go_to_sleep) + sleep_UntilNextReceive(); + + vTaskDelay(10 / portTICK_PERIOD_MS); + } } extern "C" void app_main(void) { + static const char *TAG = "app_main"; + uint32_t setup_start = millis(); - DBG_BEGIN(); + esp_base_mac_addr_set(PEER_SERVER); + + WiFi_connect(); + + vTaskDelay(10000 / portTICK_PERIOD_MS); esp_base_mac_addr_set(PEER_SERVER); - init_WiFi(); WIFI_SyncTime(); - init_Server(); + //init_Server(); + init_EspNow(); /* @@ -49,7 +59,7 @@ else DBG_PRINTLN("Failed to get cfg!"); go_to_sleep = false; next_connection_unix = 0; g_setup_duration = millis() - setup_start; - DBG_PRINTF("Setup duration: %u ms\n", g_setup_duration); + ESP_LOGI(TAG, "Setup duration: %u ms\n", g_setup_duration); - xTaskCreate(pump_loop, "serverloop", 4096, nullptr, 5, nullptr); + xTaskCreate(server_loop, "serverloop", 8192, nullptr, 5, nullptr); } diff --git a/server/sdkconfig b/server/sdkconfig index 11ff890..b671e8e 100644 --- a/server/sdkconfig +++ b/server/sdkconfig @@ -651,7 +651,8 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y # CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set -# CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_INSECURE=y +CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS