diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..0546715 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,27 @@ +{ + "configurations": [ + { + "name": "ESP-IDF", + "compilerPath": "${default}", + "compileCommands": "${workspaceFolder}/build/compile_commands.json", + "includePath": [ + "${config:idf.espIdfPath}/components/**", + "${config:idf.espIdfPathWin}/components/**", + "${config:idf.espAdfPath}/components/**", + "${config:idf.espAdfPathWin}/components/**", + "${workspaceFolder}/**" + ], + "browse": { + "path": [ + "${config:idf.espIdfPath}/components", + "${config:idf.espIdfPathWin}/components", + "${config:idf.espAdfPath}/components/**", + "${config:idf.espAdfPathWin}/components/**", + "${workspaceFolder}" + ], + "limitSymbolsToIncludedHeaders": false + } + } + ], + "version": 4 + } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 884c37d..b007ac5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,7 +17,13 @@ "type_traits": "c", "cmath": "c", "*.tcc": "c", - "*.inc": "c" + "*.inc": "c", + "safety.h": "c", + "event_groups.h": "c", + "string.h": "c", + "time.h": "c", + "timers.h": "c", + "nvs_flash.h": "c" }, "idf.openOcdConfigs": [ "board/esp32-wrover-kit-3.3v.cfg" diff --git a/README.md b/README.md index 9b900e1..bdafc6b 100644 --- a/README.md +++ b/README.md @@ -7,13 +7,15 @@ classDiagram Inputs <|-- Control Outputs <|-- Control +Sntp <|-- Control Inputs <|-- Safety Outputs <|--|> Safety -Inputs <|-- HTTP_Metrics -Outputs <|-- HTTP_Metrics -Control <|-- HTTP_Metrics -Safety <|-- HTTP_Metrics +Inputs <|-- Metrics +Outputs <|-- Metrics +Control <|-- Metrics +Safety <|-- Metrics +Sntp <|-- Metrics class Inputs{ +initInputs() @@ -47,6 +49,16 @@ Safety <|-- HTTP_Metrics +getSafetyState() } + + class Wifi{ + +initWifi() + } + + class Sntp{ + +initSntp() + +getSntpState() + } + class Metrics{ +initMetrics() -taskMetrics() diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index fda1709..cef8b5e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,7 +1,9 @@ -idf_component_register(SRCS "main.c" +idf_component_register(SRCS "sntp.c" "wifi.c" "main.c" "metrics.c" "inputs.c" "outputs.c" "control.c" "safety.c" + "wifi.c" + "sntp.c" INCLUDE_DIRS ".") diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 990fa8e..c855f47 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -15,5 +15,8 @@ menu "Smart Oil Heating Control System" config STATIC_GATEWAY_IP_ADDR string "Static IPv4 gateway address" default "192.168.0.1" + config SNTP_SERVER_IP_ADDR + string "SNTP IPv4 server address" + default "192.168.0.1" endmenu diff --git a/main/control.c b/main/control.c index 0b64e78..42f89f8 100644 --- a/main/control.c +++ b/main/control.c @@ -5,6 +5,7 @@ #include "outputs.h" #include "inputs.h" #include "safety.h" +#include "sntp.h" #define PERIODIC_INTERVAL 1U // run safety checks every 1sec @@ -40,16 +41,20 @@ void taskControl(void *pvParameters) { vTaskDelay(PERIODIC_INTERVAL * 1000U / portTICK_PERIOD_MS); - if (getSafetyState() == SAFETY_NO_ERROR) - { - // TODO: control the burner based on timetable - - setCirculationPumpState(DISABLED); - setBurnerState(ENABLED); - } - else + if (getSafetyState() != SAFETY_NO_ERROR) { ESP_LOGW(TAG, "Control not possible due to safety fault!"); + continue; } + + if (getSntpState() != SYNC_SUCCESSFUL) + { + ESP_LOGW(TAG, "Control not possible due to sntp fault!"); + continue; + } + + // TODO: control the burner based on timetable + setCirculationPumpState(DISABLED); + setBurnerState(ENABLED); } } \ No newline at end of file diff --git a/main/main.c b/main/main.c index 1ee85ff..82c2d63 100644 --- a/main/main.c +++ b/main/main.c @@ -1,15 +1,5 @@ -#include #include "esp_log.h" -#include "driver/i2c.h" #include -#include -#include -#include -#include -#include -#include -#include -#include "freertos/timers.h" #include "nvs_flash.h" #include "safety.h" @@ -17,9 +7,8 @@ #include "outputs.h" #include "inputs.h" #include "control.h" - -#define I2C_MASTER_SCL 19 -#define I2C_MASTER_SDA 18 +#include "wifi.h" +#include "sntp.h" static const char *TAG = "smart-oil-heater-control-system"; @@ -40,11 +29,14 @@ void app_main(void) initOutputs(); initInputs(); initSafety(); + initWifi(); + initSntp(); initControl(); initMetrics(); while (1) { - vTaskDelay(pdMS_TO_TICKS(2048)); + vTaskDelay(pdMS_TO_TICKS(1000)); + // Do nothing ;-) } } \ No newline at end of file diff --git a/main/metrics.c b/main/metrics.c index c7cce67..e0c8719 100644 --- a/main/metrics.c +++ b/main/metrics.c @@ -1,27 +1,17 @@ -#include -#include #include #include "esp_timer.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "esp_system.h" -#include "spi_flash_mmap.h" #include "esp_wifi.h" -#include "esp_event.h" -#include "freertos/event_groups.h" #include "esp_log.h" -#include "esp_netif.h" -#include -#include -#include -#include +#include +#include #include "metrics.h" #include "outputs.h" #include "inputs.h" #include "safety.h" - -static EventGroupHandle_t s_wifi_event_group; +#include "sntp.h" static const char *TAG = "smart-oil-heater-control-system-metrics"; @@ -31,13 +21,11 @@ static sMetric aMetrics[METRIC_MAX_COUNT]; static uint16_t u16MetricCounter = 0U; void taskMetrics(void *pvParameters); -void connect_wifi(void); httpd_handle_t setup_server(void); esp_err_t get_metrics_handler(httpd_req_t *req); void initMetrics(void) { - connect_wifi(); setup_server(); BaseType_t taskCreated = xTaskCreate( @@ -67,118 +55,113 @@ void taskMetrics(void *pvParameters) u16MetricCounter = 0U; - /*Uptime*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "uptime_seconds"); - aMetrics[u16MetricCounter].fMetricValue = (esp_timer_get_time() / 1000000U); - u16MetricCounter++; + /*Circulation Pump State*/ + if (getCirculationPumpState() == ENABLED) + { + strcpy(aMetrics[u16MetricCounter].caMetricName, "circulation_pump_enabled"); + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = 1U; + u16MetricCounter++; + } + else + { + strcpy(aMetrics[u16MetricCounter].caMetricName, "circulation_pump_enabled"); + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = 0U; + u16MetricCounter++; + } - /*Wifi RSSI*/ - wifi_ap_record_t ap; - esp_wifi_sta_get_ap_info(&ap); - // printf("WiFi RSSI: %d\n", ap.rssi); - strcpy(aMetrics[u16MetricCounter].caMetricName, "wifi_rssi"); - aMetrics[u16MetricCounter].fMetricValue = ap.rssi; + /*Burner Error State*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_fault_pending"); + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = getBurnerError(); u16MetricCounter++; /*Burner State*/ if (getBurnerState() == ENABLED) { strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_enabled"); - aMetrics[u16MetricCounter].fMetricValue = 1.0f; + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = 1U; u16MetricCounter++; } else { strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_enabled"); - aMetrics[u16MetricCounter].fMetricValue = 0.0f; - u16MetricCounter++; - } - - /*Circulation Pump State*/ - if (getCirculationPumpState() == ENABLED) - { - strcpy(aMetrics[u16MetricCounter].caMetricName, "circulation_pump_enabled"); - aMetrics[u16MetricCounter].fMetricValue = 1.0f; - u16MetricCounter++; - } - else - { - strcpy(aMetrics[u16MetricCounter].caMetricName, "circulation_pump_enabled"); - aMetrics[u16MetricCounter].fMetricValue = 0.0f; - u16MetricCounter++; - } - - /*Burner Error State*/ - if (getBurnerError() == FAULT) - { - strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_fault_pending"); - aMetrics[u16MetricCounter].fMetricValue = 1.0f; - u16MetricCounter++; - } - else - { - strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_fault_pending"); - aMetrics[u16MetricCounter].fMetricValue = 0.0f; + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = 0U; u16MetricCounter++; } /*Chamber Temperature*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature"); + aMetrics[u16MetricCounter].type = FLOAT; aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().fCurrentValue; u16MetricCounter++; - /*Outdoor Temperature*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature"); - aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().fCurrentValue; - u16MetricCounter++; - - /*Chamber Temperature*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature"); - aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().fCurrentValue; - u16MetricCounter++; - - /*Chamber Temperature*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature"); - aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().fCurrentValue; - u16MetricCounter++; - /*Chamber Temperature Average 10s*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_avg10"); + aMetrics[u16MetricCounter].type = FLOAT; aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average10s.fValue; u16MetricCounter++; - /*Outdoor Temperature Average 10s*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_avg10"); - aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average10s.fValue; - u16MetricCounter++; - - /*Chamber Temperature Average 10s*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg10"); - aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average10s.fValue; - u16MetricCounter++; - - /*Chamber Temperature Average 10s*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_avg10"); - aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average10s.fValue; - u16MetricCounter++; - /*Chamber Temperature Average 60s*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_avg60"); + aMetrics[u16MetricCounter].type = FLOAT; aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average60s.fValue; u16MetricCounter++; + /*Inlet Flow Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().fCurrentValue; + u16MetricCounter++; + + /*Inlet Flow Temperature Average 10s*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg10"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average10s.fValue; + u16MetricCounter++; + + /*Inlet Flow Temperature Average 60s*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg60"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average60s.fValue; + u16MetricCounter++; + + /*Outdoor Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().fCurrentValue; + u16MetricCounter++; + + /*Outdoor Temperature Average 10s*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_avg10"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average10s.fValue; + u16MetricCounter++; + /*Outdoor Temperature Average 60s*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_avg60"); + aMetrics[u16MetricCounter].type = FLOAT; aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average60s.fValue; u16MetricCounter++; - /*Chamber Temperature Average 60s*/ - strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_avg60"); - aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average60s.fValue; + /*Return Flow Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().fCurrentValue; u16MetricCounter++; - /*Chamber Temperature Average 60s*/ + /*Return Flow Temperature Average 10s*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_avg10"); + aMetrics[u16MetricCounter].type = FLOAT; + aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average10s.fValue; + u16MetricCounter++; + + /*Return Flow Temperature Average 60s*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_avg60"); + aMetrics[u16MetricCounter].type = FLOAT; aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue; u16MetricCounter++; @@ -189,13 +172,43 @@ void taskMetrics(void *pvParameters) { strcpy(aMetrics[u16MetricCounter].caMetricName, aChecks[i].name); strcat(aMetrics[u16MetricCounter].caMetricName, "_status"); - aMetrics[u16MetricCounter].fMetricValue = aChecks[i].status; + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = aChecks[i].status; u16MetricCounter++; } - /*Safety state*/ + /*Safety State*/ strcpy(aMetrics[u16MetricCounter].caMetricName, "safety_state"); - aMetrics[u16MetricCounter].fMetricValue = getSafetyState(); + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = getSafetyState(); + u16MetricCounter++; + + /*SNTP Status*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "sntp_status"); + aMetrics[u16MetricCounter].type = INTEGER_U8; + aMetrics[u16MetricCounter].u8MetricValue = getSntpState(); + u16MetricCounter++; + + /*System Time*/ + time_t now; + time(&now); + strcpy(aMetrics[u16MetricCounter].caMetricName, "system_unixtime"); + aMetrics[u16MetricCounter].type = INTEGER_64; + aMetrics[u16MetricCounter].i64MetricValue = now; + u16MetricCounter++; + + /*Uptime*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "uptime_seconds"); + aMetrics[u16MetricCounter].type = INTEGER_64; + aMetrics[u16MetricCounter].i64MetricValue = (esp_timer_get_time() / 1000000U); + u16MetricCounter++; + + /*Wifi RSSI*/ + wifi_ap_record_t ap; + esp_wifi_sta_get_ap_info(&ap); + strcpy(aMetrics[u16MetricCounter].caMetricName, "wifi_rssi"); + aMetrics[u16MetricCounter].type = INTEGER_64; + aMetrics[u16MetricCounter].i64MetricValue = ap.rssi; u16MetricCounter++; vSetMetrics(aMetrics, u16MetricCounter); @@ -211,7 +224,22 @@ void vSetMetrics(sMetric *paMetrics, uint16_t u16Size) for (uint16_t u16Index = 0U; u16Index < u16Size; u16Index++) { char caValueBuffer[64]; - sprintf(caValueBuffer, " %f", paMetrics[u16Index].fMetricValue); + + switch (paMetrics[u16Index].type) + { + case FLOAT: + sprintf(caValueBuffer, " %f", paMetrics[u16Index].fMetricValue); + break; + case INTEGER_64: + sprintf(caValueBuffer, " %lli", paMetrics[u16Index].i64MetricValue); + break; + case INTEGER_U8: + sprintf(caValueBuffer, " %u", paMetrics[u16Index].u8MetricValue); + break; + default: + break; + } + // printf("%s\n", caValueBuffer); strcat(caHtmlResponse, paMetrics[u16Index].caMetricName); strcat(caHtmlResponse, caValueBuffer); @@ -225,93 +253,6 @@ void vSetMetrics(sMetric *paMetrics, uint16_t u16Size) } } -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(); - } - else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) - { - esp_wifi_connect(); - ESP_LOGI(TAG, "Retry to connect to the AP"); - } - 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 connect_wifi(void) -{ - s_wifi_event_group = xEventGroupCreate(); - ESP_ERROR_CHECK(esp_netif_init()); - ESP_ERROR_CHECK(esp_event_loop_create_default()); - - esp_netif_t *my_sta = esp_netif_create_default_wifi_sta(); - esp_netif_dhcpc_stop(my_sta); - esp_netif_ip_info_t ip_info; - ip_info.ip.addr = ipaddr_addr(CONFIG_STATIC_IP_ADDR); - ip_info.gw.addr = ipaddr_addr(CONFIG_STATIC_GATEWAY_IP_ADDR); - ip_info.netmask.addr = ipaddr_addr(CONFIG_STATIC_IP_NETMASK); - esp_netif_set_ip_info(my_sta, &ip_info); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); - 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, - ESP_EVENT_ANY_ID, - &event_handler, - NULL, - &instance_any_id)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, - IP_EVENT_STA_GOT_IP, - &event_handler, - NULL, - &instance_got_ip)); - - wifi_config_t wifi_config = { - .sta = { - .ssid = CONFIG_SSID, - .password = CONFIG_WIFI_PASSWORD, - .threshold.authmode = WIFI_AUTH_WPA2_PSK, - }, - }; - ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); - ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); - - ESP_ERROR_CHECK(esp_wifi_start()); - - ESP_ERROR_CHECK(esp_wifi_set_max_tx_power(78)); // Set max power to 19.5 dBm (78 in units of 0.25 dBm) - ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MIN_MODEM)); // Use power-saving mode - - ESP_LOGI(TAG, "wifi_init_sta finished."); - - EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, - WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, - pdFALSE, - pdFALSE, - portMAX_DELAY); - - if (bits & WIFI_CONNECTED_BIT) - { - ESP_LOGI(TAG, "Connected to ap SSID:%s", CONFIG_SSID); - } - else if (bits & WIFI_FAIL_BIT) - { - ESP_LOGI(TAG, "Failed to connect to SSID:%s", CONFIG_SSID); - } - else - { - ESP_LOGE(TAG, "Unexpected event"); - } - vEventGroupDelete(s_wifi_event_group); -} - esp_err_t get_metrics_handler(httpd_req_t *req) { if (xSemaphoreTakeRecursive(xMutexAccessMetricResponse, pdMS_TO_TICKS(5000)) == pdTRUE) diff --git a/main/metrics.h b/main/metrics.h index 7e8a161..b02342a 100644 --- a/main/metrics.h +++ b/main/metrics.h @@ -2,16 +2,24 @@ #include -#define WIFI_CONNECTED_BIT BIT0 -#define WIFI_FAIL_BIT BIT1 #define HTML_RESPONSE_SIZE 1024U #define METRIC_NAME_MAX_SIZE 256U #define METRIC_MAX_COUNT 64U +typedef enum _MetricValueType +{ + FLOAT, + INTEGER_U8, + INTEGER_64, +} eMetricValueType; + typedef struct _metric { char caMetricName[METRIC_NAME_MAX_SIZE]; + eMetricValueType type; float fMetricValue; + uint8_t u8MetricValue; + int64_t i64MetricValue; } sMetric; void initMetrics(void); diff --git a/main/sntp.c b/main/sntp.c new file mode 100644 index 0000000..638bfa4 --- /dev/null +++ b/main/sntp.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include "esp_log.h" + +#include "sntp.h" + +static const char *TAG = "smart-oil-heater-control-system-sntp"; +static eSntpState sntpState = SYNC_NOT_STARTED; +void time_sync_notification_cb(struct timeval *tv); + +void initSntp(void) +{ + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setservername(0, CONFIG_SNTP_SERVER_IP_ADDR); + + sntp_set_time_sync_notification_cb(time_sync_notification_cb); + esp_sntp_init(); +} + +eSntpState getSntpState(void) +{ + return sntpState; +} + +void time_sync_notification_cb(struct timeval *tv) +{ + ESP_LOGI(TAG, "SNTP synchronization! Unix Time: %lld", tv->tv_sec); + sntpState = SYNC_SUCCESSFUL; +} diff --git a/main/sntp.h b/main/sntp.h new file mode 100644 index 0000000..4feb88b --- /dev/null +++ b/main/sntp.h @@ -0,0 +1,11 @@ +#pragma once + +typedef enum _SntpState +{ + SYNC_SUCCESSFUL, + SYNC_NOT_STARTED, + SYNC_FAILED, +} eSntpState; + +void initSntp(void); +eSntpState getSntpState(void); \ No newline at end of file diff --git a/main/wifi.c b/main/wifi.c new file mode 100644 index 0000000..d1fd0c1 --- /dev/null +++ b/main/wifi.c @@ -0,0 +1,108 @@ +#include +#include "esp_timer.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "freertos/event_groups.h" +#include "esp_log.h" +#include "esp_netif.h" +#include + +#include "wifi.h" + +#define WIFI_CONNECTED_BIT BIT0 +#define WIFI_FAIL_BIT BIT1 + +static const char *TAG = "smart-oil-heater-control-system-wifi"; + +static EventGroupHandle_t s_wifi_event_group; +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); + +void initWifi(void) +{ + s_wifi_event_group = xEventGroupCreate(); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + esp_netif_t *my_sta = esp_netif_create_default_wifi_sta(); + esp_netif_dhcpc_stop(my_sta); + esp_netif_ip_info_t ip_info; + ip_info.ip.addr = ipaddr_addr(CONFIG_STATIC_IP_ADDR); + ip_info.gw.addr = ipaddr_addr(CONFIG_STATIC_GATEWAY_IP_ADDR); + ip_info.netmask.addr = ipaddr_addr(CONFIG_STATIC_IP_NETMASK); + esp_netif_set_ip_info(my_sta, &ip_info); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + 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, + ESP_EVENT_ANY_ID, + &event_handler, + NULL, + &instance_any_id)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, + IP_EVENT_STA_GOT_IP, + &event_handler, + NULL, + &instance_got_ip)); + + wifi_config_t wifi_config = { + .sta = { + .ssid = CONFIG_SSID, + .password = CONFIG_WIFI_PASSWORD, + .threshold.authmode = WIFI_AUTH_WPA2_PSK, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_ERROR_CHECK(esp_wifi_set_max_tx_power(78)); // Set max power to 19.5 dBm (78 in units of 0.25 dBm) + ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MIN_MODEM)); // Use power-saving mode + + ESP_LOGI(TAG, "wifi_init_sta finished."); + + EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, + WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + if (bits & WIFI_CONNECTED_BIT) + { + ESP_LOGI(TAG, "Connected to ap SSID:%s", CONFIG_SSID); + } + else if (bits & WIFI_FAIL_BIT) + { + ESP_LOGI(TAG, "Failed to connect to SSID:%s", CONFIG_SSID); + } + else + { + ESP_LOGE(TAG, "Unexpected event"); + } + vEventGroupDelete(s_wifi_event_group); +} + +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(); + } + else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) + { + esp_wifi_connect(); + ESP_LOGI(TAG, "Retry to connect to the AP"); + } + 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); + } +} \ No newline at end of file diff --git a/main/wifi.h b/main/wifi.h new file mode 100644 index 0000000..380c625 --- /dev/null +++ b/main/wifi.h @@ -0,0 +1,3 @@ +#pragma once + +void initWifi(void); \ No newline at end of file