diff --git a/components/wifi/CMakeLists.txt b/components/wifi/CMakeLists.txt index 03dbf77..9f92fa8 100644 --- a/components/wifi/CMakeLists.txt +++ b/components/wifi/CMakeLists.txt @@ -1,4 +1,4 @@ idf_component_register(SRCS "wifi.c" INCLUDE_DIRS "." - REQUIRES driver esp_wifi + REQUIRES driver esp_wifi lwip ) diff --git a/components/wifi/wifi.c b/components/wifi/wifi.c index f113a5e..354f069 100644 --- a/components/wifi/wifi.c +++ b/components/wifi/wifi.c @@ -1,17 +1,28 @@ +#include "wifi.h" #include - -#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "esp_sntp.h" #include "esp_wifi.h" #include "esp_event.h" #include "esp_log.h" -static const char* TAG = "WIFI"; +static const char *TAG = "WIFI"; + +static EventGroupHandle_t s_wifi_event_group; +static bool ntp_time_obtained = false; + +#define WIFI_CONNECTED_BIT (1 << 0) + +bool has_ntp_time_obtained_once() { + return ntp_time_obtained; +} static void 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(); + esp_wifi_connect(); + ESP_LOGI(TAG, "connecting..."); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { esp_wifi_connect(); @@ -20,11 +31,11 @@ static void event_handler(void* arg, esp_event_base_t event_base, 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); } } void start_wifi() { - ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); @@ -33,6 +44,8 @@ void start_wifi() { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + s_wifi_event_group = xEventGroupCreate(); + esp_event_handler_instance_t instance_any_id; esp_event_handler_instance_t instance_got_ip; ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, @@ -58,4 +71,30 @@ void start_wifi() { ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) ); ESP_ERROR_CHECK(esp_wifi_start() ); ESP_LOGI(TAG, "wifi_init_sta finished."); + + // Wait for WiFi to connect + xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdFALSE, portMAX_DELAY); + esp_sntp_setservername(0, "pool.ntp.org"); + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); + sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); + esp_sntp_init(); + + setenv("TZ", "GMT0BST,M3.5.0/1,M10.5.0", 1); + tzset(); + + + for (uint32_t i = 0; i < 20; ++i) { + if (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED) { + ESP_LOGI(TAG, "... waiting for time update"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + } + + time_t epoch; + time(&epoch); + struct tm *timeinfo = localtime(&epoch); + + ESP_LOGI(TAG, "Current time: %i:%i", timeinfo->tm_hour, timeinfo->tm_min); + ntp_time_obtained = true; } diff --git a/components/wifi/wifi.h b/components/wifi/wifi.h index d4aab6b..4560ab1 100644 --- a/components/wifi/wifi.h +++ b/components/wifi/wifi.h @@ -1,3 +1,12 @@ #pragma once +#include +// The idea with this function is to check if NTP time has been obtained +// at least once - and therefore time is at least vaguely accurate +// I want to call this when saving data to know whether the time is valid/trusted +// at all +bool has_ntp_time_obtained_once(); + +// Probably should rename this to "start networking" or something because +// it also does NTP stuff, and maybe even establish the HTTP Server stuff? void start_wifi(); diff --git a/main/main.c b/main/main.c index a4c6fc9..fd9ed60 100644 --- a/main/main.c +++ b/main/main.c @@ -7,13 +7,14 @@ #include "dht22.h" #include "wifi.h" #include "esp_log.h" -#include "esp_wifi.h" +#include "esp_sntp.h" #include "freertos/FreeRTOS.h" #include "freertos/projdefs.h" #include "freertos/task.h" #include "nvs_flash.h" #include "portmacro.h" #include +#include #include static const char* TAG = "YASPAM"; @@ -24,6 +25,15 @@ static volatile bool run_pms5003 = true; static TaskHandle_t dht22_handle = NULL; static TaskHandle_t pms5003_handle = NULL; +typedef struct { + uint8_t myt_sec; // 0 -> 61 + uint8_t myt_min; // 0 -> 69 + uint8_t myt_hour; // 0 -> 23 + uint8_t myt_day; // 1 -> 31 + uint8_t myt_month; // 0 -> 11 !! + uint8_t myt_year; // years since 1900 +} my_time; + #ifdef CONFIG_PMS5003_ENABLED #include "pms5003.h" @@ -42,19 +52,48 @@ read_from_pms5003() #ifdef CONFIG_DHT22_ENABLED #include "dht22.h" -void -read_from_dht22() -{ +typedef struct { + deci_percent rh; + deci_degrees_c temp; + my_time time; +} my_dht22_data; + +my_dht22_data latest_datapoint; + +my_dht22_data ten_minute_rolling_average; +uint16_t num_samples_last_ten_mins = 0; + +void read_from_dht22() { while (run_dht) { // Data reading is based on time, so need to block interrups etc + // I _think_ these are freeRTOS task interrupts - I wonder if + // I need to also block ESP interrupts? Should I even do that? portDISABLE_INTERRUPTS(); int ret = dht22_read(); portENABLE_INTERRUPTS(); if (ret != DHT22_OK) { dht22_handle_error(ret); } else { - ESP_LOGI(TAG, "Got DHT22 data!"); - // TODO: Write the data out somewhere - into RAM maybe? + latest_datapoint.temp = dht22_temperature(); + latest_datapoint.rh = dht22_relative_humidity(); + + if (has_ntp_time_obtained_once()) { + time_t epoch; + time(&epoch); + struct tm *timeinfo = localtime(&epoch); + + // There must be a better way - I couldn't figure out how to do it nicely all at once + latest_datapoint.time.myt_sec = timeinfo->tm_sec; + latest_datapoint.time.myt_min = timeinfo->tm_min; + latest_datapoint.time.myt_hour = timeinfo->tm_hour; + latest_datapoint.time.myt_day = timeinfo->tm_mday; + latest_datapoint.time.myt_month = timeinfo->tm_mon; + latest_datapoint.time.myt_year = timeinfo->tm_year; + // TODO: update ten minute rolling average + // + // TODO: Write the data out somewhere - into RAM maybe - I think only every 10 minutes + // though + } } vTaskDelay(pdMS_TO_TICKS(CONFIG_DHT22_PERIOD_POLL)); }