From 8fd658071a788de988739fcd0c2905a25c3499cd Mon Sep 17 00:00:00 2001 From: Arthur Roberts Date: Mon, 6 Nov 2023 20:41:17 +0000 Subject: [PATCH] Added start of HTTP server (& data storage) --- components/http_server/CMakeLists.txt | 4 + components/http_server/Kconfig.projbuild | 14 ++++ components/http_server/http.c | 98 ++++++++++++++++++++++++ components/http_server/http.h | 10 +++ main/main.c | 71 +++++------------ 5 files changed, 144 insertions(+), 53 deletions(-) create mode 100644 components/http_server/CMakeLists.txt create mode 100644 components/http_server/Kconfig.projbuild create mode 100644 components/http_server/http.c create mode 100644 components/http_server/http.h diff --git a/components/http_server/CMakeLists.txt b/components/http_server/CMakeLists.txt new file mode 100644 index 0000000..5468b07 --- /dev/null +++ b/components/http_server/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "http.c" + INCLUDE_DIRS "." + PRIV_REQUIRES dht22 wifi esp_http_server +) diff --git a/components/http_server/Kconfig.projbuild b/components/http_server/Kconfig.projbuild new file mode 100644 index 0000000..775022b --- /dev/null +++ b/components/http_server/Kconfig.projbuild @@ -0,0 +1,14 @@ +menu "HTTP" +# config WIFI_SSID +# string "WiFi SSID" +# default "VM8094728" +# help +# SSID (network name) for the example to connect to. + +# config WIFI_PASSWORD +# string "WiFi Password" +# default "tx3YrxvzMrbr" +# help +# WiFi password (WPA or WPA2) for the example to use. + +endmenu diff --git a/components/http_server/http.c b/components/http_server/http.c new file mode 100644 index 0000000..6013a12 --- /dev/null +++ b/components/http_server/http.c @@ -0,0 +1,98 @@ +#include "http.h" +#include "esp_sntp.h" +#include "wifi.h" +#include +#include +#include "esp_log.h" +#include "esp_http_server.h" + +// 2 Days worth of samples +#define NUM_SAMPLES_TO_STORE (( 24 * 60 ) / 10 ) * 2 + +typedef struct { + uint8_t myt_sec; // 0 -> 61 + uint8_t myt_min; // 0 -> 59 + 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; + +typedef struct { + deci_percent rh; + deci_degrees_c temp; + my_time time; +} my_dht22_data; + + +// I know this is asking for a race condition... +static my_dht22_data *dht22_buffer = NULL; +static int dht22_num = 0; + +my_time get_time() { + time_t epoch; + time(&epoch); + struct tm *timeinfo = localtime(&epoch); + my_time my_current_time; + + // There must be a better way - I couldn't figure out how to do it + // nicely all at once + my_current_time.myt_sec = timeinfo->tm_sec; + // -5 to get the middle of the averaged window + my_current_time.myt_min = timeinfo->tm_min; + my_current_time.myt_hour = timeinfo->tm_hour; + my_current_time.myt_day = timeinfo->tm_mday; + my_current_time.myt_month = timeinfo->tm_mon; + my_current_time.myt_year = timeinfo->tm_year; + return my_current_time; +} + + +esp_err_t dht22_data_get_handler(httpd_req_t *req) { + char *resp; + + size_t size_of_csv_line = strlen("YYYY:MM:DD HH:MM:SS,XXXX,YYYY\n"); + + resp = calloc(dht22_num, size_of_csv_line + 1); + + for (int i = 0; i < dht22_num; i++) { + my_dht22_data d = dht22_buffer[i]; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation" + snprintf(resp + (i * size_of_csv_line), size_of_csv_line, + "%04d:%02d:%02d %02d:%02d:%02d\t%04d\t%04d\n", d.time.myt_year, + d.time.myt_month, d.time.myt_day, d.time.myt_hour, d.time.myt_min, + d.time.myt_sec, d.rh, d.temp); +#pragma GCC diagnostic pop + } + // shouldn't need to null terminate this becuase of calloc + + httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); + return ESP_OK; +} + +/* URI handler structure for GET /uri */ +httpd_uri_t dht22_data_get = { + .uri = "/dht22.csv", + .method = HTTP_GET, + .handler = dht22_data_get_handler, + .user_ctx = NULL +}; + +void init_dht22_data() { + dht22_buffer = malloc(NUM_SAMPLES_TO_STORE * sizeof(my_dht22_data)); + // register an http endpoint thingy probably? +} + +void add_dht22_data(float rh, float temp) { + if (dht22_buffer == NULL) { + return; + } + my_dht22_data dht22_data; + dht22_data.time = get_time(); + dht22_data.time.myt_min -= 5; + dht22_data.temp = round(temp); + dht22_data.rh = round(rh); + dht22_buffer[dht22_num] = dht22_data; + dht22_num++; +} diff --git a/components/http_server/http.h b/components/http_server/http.h new file mode 100644 index 0000000..f56c924 --- /dev/null +++ b/components/http_server/http.h @@ -0,0 +1,10 @@ +#pragma once + +#include "dht22.h" + +void init_dht22_data(); + +// This function presumes we've got a 10 minute average here +// - could think about abstracting the average out into this +// function maybe. Something for the future! +void add_dht22_data(float rh, float temp); diff --git a/main/main.c b/main/main.c index 50c846c..ed471dc 100644 --- a/main/main.c +++ b/main/main.c @@ -6,14 +6,15 @@ #include "dht22.h" #include "esp_log.h" -#include "esp_sntp.h" #include "freertos/FreeRTOS.h" #include "freertos/projdefs.h" #include "freertos/task.h" +#include "http.h" #include "nvs_flash.h" #include "portmacro.h" #include "sdkconfig.h" #include "wifi.h" +#include "http.h" #include #include #include @@ -29,15 +30,6 @@ static TaskHandle_t dht22_handle = NULL; static TaskHandle_t pms5003_handle = NULL; static TaskHandle_t ds18b20_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_DS18B20_ENABLED #include "ds18b20.h" @@ -65,13 +57,8 @@ void read_from_pms5003() { #ifdef CONFIG_DHT22_ENABLED #include "dht22.h" -typedef struct { - deci_percent rh; - deci_degrees_c temp; - my_time time; -} my_dht22_data; - -my_dht22_data latest_datapoint; +deci_percent dht22_rh; +deci_degrees_c dht22_temp; void read_from_dht22() { // From datasheet: @@ -81,33 +68,32 @@ void read_from_dht22() { uint32_t num_samples_last_ten_mins = 0; float relative_humidity_tmp; float temperature_tmp; - my_dht22_data ten_minute_average; while (run_dht) { int ret = dht22_read(); if (ret != DHT22_OK) { dht22_handle_error(ret); } else { - latest_datapoint.temp = dht22_temperature(); - latest_datapoint.rh = dht22_relative_humidity(); + dht22_temp = dht22_temperature(); + dht22_rh = dht22_relative_humidity(); ESP_LOGI(TAG, - "Sucesfully obtained DHT22 data (temp: %"PRIi16" rh: %"PRIu16")", - latest_datapoint.temp, latest_datapoint.rh); + "Sucesfully obtained DHT22 data (temp: %" PRIi16 " rh: %" PRIu16 + ")", + dht22_temp, dht22_rh); // No point collecting rolling average if we don't know what the time is if (has_ntp_time_obtained_once()) { if (num_samples_last_ten_mins == 0) { - relative_humidity_tmp = latest_datapoint.rh; - temperature_tmp = latest_datapoint.temp; + relative_humidity_tmp = dht22_rh; + temperature_tmp = dht22_temp; } else { - relative_humidity_tmp += - ((float)latest_datapoint.rh - relative_humidity_tmp) / - ((float)num_samples_last_ten_mins + 1.0); - temperature_tmp += ((float)latest_datapoint.temp - temperature_tmp) / + relative_humidity_tmp += ((float)dht22_rh - relative_humidity_tmp) / + ((float)num_samples_last_ten_mins + 1.0); + temperature_tmp += ((float)dht22_temp - temperature_tmp) / ((float)num_samples_last_ten_mins + 1.0); } num_samples_last_ten_mins += 1; - ESP_LOGI(TAG, "latest_datapoint.temp: %" PRIi16, latest_datapoint.temp); + ESP_LOGI(TAG, "latest_datapoint.temp: %" PRIi16, dht22_temp); ESP_LOGI(TAG, "ten_minute_average.temp: %f, num_samples: %" PRIu32, temperature_tmp, num_samples_last_ten_mins); @@ -119,30 +105,8 @@ void read_from_dht22() { temperature_tmp); num_samples_last_ten_mins = 0; - time_t epoch; - time(&epoch); - struct tm *timeinfo = localtime(&epoch); + add_dht22_data(relative_humidity_tmp, temperature_tmp); - // There must be a better way - I couldn't figure out how to do it - // nicely all at once - ten_minute_average.time.myt_sec = timeinfo->tm_sec; - // -5 to get the middle of the averaged window - ten_minute_average.time.myt_min = timeinfo->tm_min - 5; - ten_minute_average.time.myt_hour = timeinfo->tm_hour; - ten_minute_average.time.myt_day = timeinfo->tm_mday; - ten_minute_average.time.myt_month = timeinfo->tm_mon; - ten_minute_average.time.myt_year = timeinfo->tm_year; - - // TODO: Consider rounding this number - although, .1 of a degree C... - // no one is going to miss that. Probably the calculation require to - // do the rounding would affect the temperature that much anyways - // haha - ten_minute_average.temp = temperature_tmp; - ten_minute_average.rh = relative_humidity_tmp; - ESP_LOGW(TAG, "ten_min_avg.temp %" PRIi16 ", .rh %" PRIu16, - ten_minute_average.temp, ten_minute_average.rh); - - // TODO: Write the data out somewhere - into RAM maybe // TODO: maybe push the data somewhere - or put a flag up that data // can be pushed // ^ could do a cute Semaphore thingy here - I don't think I've @@ -165,6 +129,7 @@ void app_main(void) { ESP_ERROR_CHECK(ret); #ifdef CONFIG_DHT22_ENABLED + init_dht22_data(); xTaskCreate(read_from_dht22, "DHT22", 4 * 1024, // honestly I have _no_ idea NULL, @@ -190,5 +155,5 @@ void app_main(void) { 5, // no idea either &ds18b20_handle); #endif /* CONFIG DS18B20_ENABLED */ - // start_wifi(); + start_wifi(); }