Nimbin[12]?Embedded / esp_garden / client_sensor/main/main.cpp

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
client_sensor/main/main.cpp 4 KB · 120 lines raw
#include "ClientSensor.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_timer.h"
#include <sys/time.h>


extern "C" esp_err_t esp_base_mac_addr_set(const uint8_t mac[6]);



// this is going to be a sensor read value!
// RTC_DATA_ATTR is not required than!
RTC_DATA_ATTR uint32_t fake_value_to_send = 0;


// ----------------------------------------------------------------------------
// Fix time after power loss and no server connection
// ----------------------------------------------------------------------------
void restore_TimeBackup() {
    int64_t stored_epoch_ref = 0;
    int64_t stored_uptime_ref = 0;
    // load persisted values from NVS
    load_time_reference(&stored_epoch_ref, &stored_uptime_ref);
    struct timeval tv;
    gettimeofday(&tv, NULL);
    int64_t now_unix = tv.tv_sec;
    int64_t now_uptime = esp_timer_get_time() / 1000000LL;
    if (now_unix < stored_epoch_ref && stored_epoch_ref > 100000 && stored_uptime_ref > 0) {
        int64_t reconstructed = stored_epoch_ref + (now_uptime - stored_uptime_ref);
        struct timeval new_tv = { .tv_sec = reconstructed, .tv_usec = 0 };
        settimeofday(&new_tv, NULL);
        ESP_LOGW("restore_TimeBackup", "System time restored from reference: %lld", get_CurrentUnix());
        ESP_LOGW("restore_TimeBackup", "Resetting next sensor reads!");
        set_AllNextSensorReads();
    }
}

// ----------------------------------------------------------------------------
// Sensor task loop
// ----------------------------------------------------------------------------
void sensor_loop(void*) {
    static const char *TAG = "sensor_loop";

    while (true) {
        ESP_LOGI(TAG, "## Unix time: %lld", get_CurrentUnix());
        for (size_t config_id = 0; config_id < SENSOR_CONFIG_COUNT; config_id++) {
            SensorConfig_s& cfg = sensor_configs[config_id];
            ESP_LOGI(TAG, "LOOP checking config: %s", cfg.sensor_name);
            print_SensorConfig(cfg);

            if (is_TimeToReadSensor(cfg)) {
                ESP_LOGI(TAG, "ITS TIME FOR THIS SENSOR!");
                uint32_t value_to_send = fake_value_to_send;

                // set last and next read times
                cfg.last_sensor_read = get_CurrentUnix();
                cfg.next_sensor_read = get_NextSensorReadFor(cfg.sensor_name);

                // decide if pump should run
                bool shall_pump = fake_value_to_send % 2;
                send_DataToPumpAndServer(config_id, value_to_send, shall_pump);
                fake_value_to_send++;
            }
        }

        if (g_pending_sensor_configs_count > 0)
            process_PendingSensorConfigs();

        // tell server when next read will happen
        int64_t next_read = get_NextSensorReadsUnixTime();
        send_NextSensorReadToPeer(PEER_SERVER, next_read - (g_setup_duration + g_wakeup_earlier_sensor)/1000);

        sleep_UntilNextSend(next_read);

        // allow other tasks to run
        vTaskDelay(pdMS_TO_TICKS(100));

        ESP_LOGI(TAG, "\n\n");
    }
}

// ----------------------------------------------------------------------------
// ESP-IDF entry point
// ----------------------------------------------------------------------------
extern "C" void app_main(void) {
    static const char *TAG = "app_main";
    uint32_t setup_start = esp_timer_get_time() / 1000ULL;

    esp_base_mac_addr_set(PEER_SENSOR);

    setup_Timezone();
    init_WiFi();
    init_EspNow();

    restore_SensorConfigs();

    restore_TimeBackup();

    ESP_LOGI(TAG, "Requesting time sync...");
    if (request_TimeSync()) ESP_LOGI(TAG, "done");
    else ESP_LOGE(TAG, "failed (timeout)");

    ESP_LOGI(TAG, "----------------------");

    if (!all_init_configs_received)
        get_AllSensorConfigs();

    ESP_LOGI(TAG, "----------------------");

    ensure_Peers();

    g_setup_duration = (esp_timer_get_time() / 1000ULL) - setup_start;
    ESP_LOGI(TAG, "Setup duration: %u ms", g_setup_duration);

    // start sensor loop task
    xTaskCreate(sensor_loop, "sensor_loop", 8192, nullptr, 5, nullptr);
}