diff --git a/README.md b/README.md index 3eee925..30bd38a 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,8 @@ Control <|-- HTTP_Metrics Safety <|-- HTTP_Metrics class Inputs{ - + initInputs() - -loop() + +initInputs() + -taskInput() +getChamberTemperature() +getOutdoorTemperature() +getInletFlowTemperature() @@ -34,22 +34,24 @@ Safety <|-- HTTP_Metrics } class Control{ - +loop() + +taskControl() -timetable } class Safety{ - + loop() - + setSafeState() - - checkSensorSanity() - + getSafetyState() + +taskSafety() + +setSafeState() + -checkSensorSanity() + +getSafetyState() } - class HTTP_Metrics{ - - metrics - + event_handler() - + connect_wifi() - + setMetrics() + class Metrics{ + +initMetrics() + -taskMetrics() + -metrics + +event_handler() + +connect_wifi() + +setMetrics() } ``` diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 4991960..fda1709 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register(SRCS "main.c" - "http_metrics.c" + "metrics.c" "inputs.c" "outputs.c" "control.c" diff --git a/main/http_metrics.c b/main/http_metrics.c deleted file mode 100644 index c333c97..0000000 --- a/main/http_metrics.c +++ /dev/null @@ -1,154 +0,0 @@ -#include "http_metrics.h" - -static EventGroupHandle_t s_wifi_event_group; - -static const char *TAG = "smart-oil-heater-control-system-http_metrics"; - -char caHtmlResponse[HTML_RESPONSE_SIZE]; -SemaphoreHandle_t xMutexAccessMetricResponse = NULL; - -void vSetMetrics(sMetric* paMetrics, uint16_t u16Size) { - - if( xSemaphoreTake( xMutexAccessMetricResponse, ( TickType_t ) 100 ) == pdTRUE ) - { - memset(caHtmlResponse,0,strlen(caHtmlResponse)); - for(uint16_t u16Index = 0U; u16Index < u16Size; u16Index++) { - char caValueBuffer[64]; - sprintf(caValueBuffer, " %f", paMetrics[u16Index].fMetricValue); - //printf("%s\n", caValueBuffer); - strcat(caHtmlResponse, paMetrics[u16Index].caMetricName); - strcat(caHtmlResponse, caValueBuffer); - strcat(caHtmlResponse, "\n"); - } - xSemaphoreGive( xMutexAccessMetricResponse ); - } else { - ESP_LOGI(TAG, "[SET] Unable to obtain mutex for metric response"); - } -} - -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_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( xSemaphoreTake( xMutexAccessMetricResponse, ( TickType_t ) 100 ) == pdTRUE ) - { - esp_err_t err = httpd_resp_send(req, caHtmlResponse, HTTPD_RESP_USE_STRLEN); - xSemaphoreGive( xMutexAccessMetricResponse ); - return err; - } else - { - ESP_LOGI(TAG, "[GET] Unable to obtain mutex for metric response"); - return httpd_resp_send(req, 0, 0); - } -} - -httpd_uri_t uri_get = { - .uri = "/metrics", - .method = HTTP_GET, - .handler = get_metrics_handler, - .user_ctx = NULL -}; - -httpd_handle_t setup_server(void) -{ - httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.server_port = 9100; - httpd_handle_t server = NULL; - - - xMutexAccessMetricResponse = xSemaphoreCreateBinary(); - if(xMutexAccessMetricResponse == NULL) { - ESP_LOGE(TAG, "Unable to create mutex for metric response"); - vTaskDelay(pdMS_TO_TICKS(300*60)); //wait 5min before restart - esp_restart(); - } - xSemaphoreGive( xMutexAccessMetricResponse ); - - if (httpd_start(&server, &config) == ESP_OK) - { - httpd_register_uri_handler(server, &uri_get); - } - - return server; -} diff --git a/main/inputs.c b/main/inputs.c index 8814114..bc146bd 100644 --- a/main/inputs.c +++ b/main/inputs.c @@ -26,7 +26,7 @@ static float fOutdoorTemperature; static float fInletFlowTemperature; static float fReturnFlowTemperature; -void loop(void *pvParameters); +void taskInput(void *pvParameters); void initInputs(void) { @@ -42,12 +42,12 @@ void initInputs(void) gpio_config(&ioConfBurnerFault); BaseType_t taskCreated = xTaskCreate( - loop, // Function to implement the task - "loop_inputs", // Task name - 2048, // Stack size (in words, not bytes) - NULL, // Parameters to the task function (none in this case) - 5, // Task priority (higher number = higher priority) - NULL // Task handle (optional) + taskInput, // Function to implement the task + "taskInput", // Task name + 2048, // Stack size (in words, not bytes) + NULL, // Parameters to the task function (none in this case) + 5, // Task priority (higher number = higher priority) + NULL // Task handle (optional) ); if (taskCreated == pdPASS) @@ -60,7 +60,7 @@ void initInputs(void) } } -void loop(void *pvParameters) +void taskInput(void *pvParameters) { while (1) { diff --git a/main/main.c b/main/main.c index ecbdac9..57353a8 100644 --- a/main/main.c +++ b/main/main.c @@ -11,7 +11,7 @@ #include #include "freertos/timers.h" -#include "http_metrics.h" +#include "metrics.h" #include "outputs.h" #include "inputs.h" @@ -33,34 +33,22 @@ void app_main(void) } ESP_ERROR_CHECK(ret); - connect_wifi(); // will return if successful - setup_server(); - - sMetric aMetrics[METRIC_MAX_COUNT]; - - /*Sensor Init*/ - ESP_ERROR_CHECK(i2cdev_init()); - + initMetrics(); initOutputs(); initInputs(); - ESP_LOGI(TAG, "running"); + /*TODO: will be done by safety on the future*/ + setCirculationPumpState(DISABLED); + setBurnerState(DISABLED); + + ESP_LOGI(TAG, "running main loop now"); while (1) { ESP_LOGI(TAG, "\n"); - vTaskDelay(pdMS_TO_TICKS(5000)); - uint16_t u16MetricCounter = 0U; + vTaskDelay(pdMS_TO_TICKS(2048)); - /*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[0].fMetricValue = ap.rssi; - u16MetricCounter++; - - vSetMetrics(aMetrics, u16MetricCounter); + /* if (getBurnerError() == FAULT) { @@ -70,8 +58,6 @@ void app_main(void) { ESP_LOGI(TAG, "Burner OK"); } - - /* setCirculationPumpState(ENABLED); setBurnerState(ENABLED); diff --git a/main/metrics.c b/main/metrics.c new file mode 100644 index 0000000..d960498 --- /dev/null +++ b/main/metrics.c @@ -0,0 +1,271 @@ +#include "metrics.h" +#include "outputs.h" +#include "inputs.h" + +static EventGroupHandle_t s_wifi_event_group; + +static const char *TAG = "smart-oil-heater-control-system-metrics"; + +char caHtmlResponse[HTML_RESPONSE_SIZE]; +SemaphoreHandle_t xMutexAccessMetricResponse = NULL; +static sMetric aMetrics[METRIC_MAX_COUNT]; +static uint16_t u16MetricCounter = 0U; + +void taskMetrics(void *pvParameters); + +void initMetrics(void) +{ + connect_wifi(); + setup_server(); + + BaseType_t taskCreated = xTaskCreate( + taskMetrics, // Function to implement the task + "taskMetrics", // Task name + 2048, // Stack size (in words, not bytes) + NULL, // Parameters to the task function (none in this case) + 5, // Task priority (higher number = higher priority) + NULL // Task handle (optional) + ); + + if (taskCreated == pdPASS) + { + ESP_LOGI(TAG, "Task created successfully!"); + } + else + { + ESP_LOGE(TAG, "Failed to create task"); + } +} + +void taskMetrics(void *pvParameters) +{ + while (1) + { + ESP_LOGI(TAG, "Running task Metrics..."); + vTaskDelay(1000U / portTICK_PERIOD_MS); + + u16MetricCounter = 0U; + + /*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; + u16MetricCounter++; + + /*Burner State*/ + if (getBurnerState() == ENABLED) + { + strcpy(aMetrics[u16MetricCounter].caMetricName, "burner_enabled"); + aMetrics[u16MetricCounter].fMetricValue = 1.0f; + 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; + u16MetricCounter++; + } + + /*Chamber Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature"); + aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature(); + u16MetricCounter++; + + /*Outdoor Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature"); + aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature(); + u16MetricCounter++; + + /*Chamber Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature"); + aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature(); + u16MetricCounter++; + + /*Chamber Temperature*/ + strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature"); + aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature(); + u16MetricCounter++; + + vSetMetrics(aMetrics, u16MetricCounter); + } +} + +void vSetMetrics(sMetric *paMetrics, uint16_t u16Size) +{ + + if (xSemaphoreTake(xMutexAccessMetricResponse, (TickType_t)100) == pdTRUE) + { + memset(caHtmlResponse, 0, strlen(caHtmlResponse)); + for (uint16_t u16Index = 0U; u16Index < u16Size; u16Index++) + { + char caValueBuffer[64]; + sprintf(caValueBuffer, " %f", paMetrics[u16Index].fMetricValue); + // printf("%s\n", caValueBuffer); + strcat(caHtmlResponse, paMetrics[u16Index].caMetricName); + strcat(caHtmlResponse, caValueBuffer); + strcat(caHtmlResponse, "\n"); + } + xSemaphoreGive(xMutexAccessMetricResponse); + } + else + { + ESP_LOGI(TAG, "[SET] Unable to obtain mutex for metric response"); + } +} + +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_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 (xSemaphoreTake(xMutexAccessMetricResponse, (TickType_t)100) == pdTRUE) + { + esp_err_t err = httpd_resp_send(req, caHtmlResponse, HTTPD_RESP_USE_STRLEN); + xSemaphoreGive(xMutexAccessMetricResponse); + return err; + } + else + { + ESP_LOGI(TAG, "[GET] Unable to obtain mutex for metric response"); + return httpd_resp_send(req, 0, 0); + } +} + +httpd_uri_t uri_get = { + .uri = "/metrics", + .method = HTTP_GET, + .handler = get_metrics_handler, + .user_ctx = NULL}; + +httpd_handle_t setup_server(void) +{ + httpd_config_t config = HTTPD_DEFAULT_CONFIG(); + config.server_port = 9100; + httpd_handle_t server = NULL; + + xMutexAccessMetricResponse = xSemaphoreCreateBinary(); + if (xMutexAccessMetricResponse == NULL) + { + ESP_LOGE(TAG, "Unable to create mutex for metric response"); + vTaskDelay(pdMS_TO_TICKS(300 * 60)); // wait 5min before restart + esp_restart(); + } + xSemaphoreGive(xMutexAccessMetricResponse); + + if (httpd_start(&server, &config) == ESP_OK) + { + httpd_register_uri_handler(server, &uri_get); + } + + return server; +} diff --git a/main/http_metrics.h b/main/metrics.h similarity index 88% rename from main/http_metrics.h rename to main/metrics.h index 779780d..174909a 100644 --- a/main/http_metrics.h +++ b/main/metrics.h @@ -27,14 +27,16 @@ #define METRIC_NAME_MAX_SIZE 64U #define METRIC_MAX_COUNT 32U -typedef struct _metric { +typedef struct _metric +{ char caMetricName[METRIC_NAME_MAX_SIZE]; float fMetricValue; } sMetric; +void initMetrics(void); void connect_wifi(void); httpd_handle_t setup_server(void); -void vSetMetrics(sMetric* paMetrics, uint16_t u16Size); +void vSetMetrics(sMetric *paMetrics, uint16_t u16Size); #endif /* H_HTTPS_METRICS */ \ No newline at end of file