Compare commits
	
		
			1 Commits
		
	
	
		
			bugfix/con
			...
			feature/wi
		
	
	| Author | SHA256 | Date | |
|---|---|---|---|
| d14ae528c0 | 
							
								
								
									
										56
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								README.md
									
									
									
									
									
								
							@ -19,11 +19,7 @@ Sntp <|-- Metrics
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    class Inputs{
 | 
					    class Inputs{
 | 
				
			||||||
        +initInputs()
 | 
					        +initInputs()
 | 
				
			||||||
        -initMeasurement()
 | 
					 | 
				
			||||||
        -updateAverage()
 | 
					 | 
				
			||||||
        -updatePrediction()
 | 
					 | 
				
			||||||
        -taskInput()
 | 
					        -taskInput()
 | 
				
			||||||
        -linearRegressionPredict()
 | 
					 | 
				
			||||||
        +getChamberTemperature()
 | 
					        +getChamberTemperature()
 | 
				
			||||||
        +getOutdoorTemperature()
 | 
					        +getOutdoorTemperature()
 | 
				
			||||||
        +getInletFlowTemperature()
 | 
					        +getInletFlowTemperature()
 | 
				
			||||||
@ -42,11 +38,7 @@ Sntp <|-- Metrics
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Control{
 | 
					    class Control{
 | 
				
			||||||
        initControl()
 | 
					 | 
				
			||||||
        +taskControl()
 | 
					        +taskControl()
 | 
				
			||||||
        +getControlCurrentWeekday()
 | 
					 | 
				
			||||||
        -findControlCurrentTemperatureEntry()
 | 
					 | 
				
			||||||
        +getControlCurrentTemperatureEntry()
 | 
					 | 
				
			||||||
        -controlTable
 | 
					        -controlTable
 | 
				
			||||||
        +getControlState()
 | 
					        +getControlState()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -87,41 +79,33 @@ Sntp <|-- Metrics
 | 
				
			|||||||
burner_fault_pending 1
 | 
					burner_fault_pending 1
 | 
				
			||||||
circulation_pump_enabled 1
 | 
					circulation_pump_enabled 1
 | 
				
			||||||
burner_enabled 0
 | 
					burner_enabled 0
 | 
				
			||||||
safety_contact_enabled 1
 | 
					safety_contact_enabled 0
 | 
				
			||||||
chamber_temperature 37.250000
 | 
					chamber_temperature 58.750000
 | 
				
			||||||
chamber_temperature_avg10 37.237499
 | 
					chamber_temperature_avg10 58.931252
 | 
				
			||||||
chamber_temperature_avg60 37.438541
 | 
					chamber_temperature_avg60 59.190475
 | 
				
			||||||
chamber_temperature_damped 42.185040
 | 
					chamber_temperature_pred60 55.870998
 | 
				
			||||||
chamber_temperature_pred60 36.638443
 | 
					inlet_flow_temperature 53.875000
 | 
				
			||||||
inlet_flow_temperature 35.625000
 | 
					inlet_flow_temperature_avg10 53.900002
 | 
				
			||||||
inlet_flow_temperature_avg10 35.618752
 | 
					inlet_flow_temperature_avg60 53.994320
 | 
				
			||||||
inlet_flow_temperature_avg60 35.415627
 | 
					inlet_flow_temperature_pred60 52.848743
 | 
				
			||||||
inlet_flow_temperature_damped 39.431259
 | 
					outdoor_temperature 18.000000
 | 
				
			||||||
inlet_flow_temperature_pred60 36.078678
 | 
					outdoor_temperature_avg10 18.006250
 | 
				
			||||||
outdoor_temperature 14.687500
 | 
					outdoor_temperature_avg60 18.002840
 | 
				
			||||||
outdoor_temperature_avg10 14.662500
 | 
					outdoor_temperature_pred60 18.050785
 | 
				
			||||||
outdoor_temperature_avg60 14.646875
 | 
					return_flow_temperature 48.625000
 | 
				
			||||||
outdoor_temperature_damped 9.169084
 | 
					return_flow_temperature_avg10 48.718750
 | 
				
			||||||
outdoor_temperature_pred60 14.660233
 | 
					return_flow_temperature_avg60 48.846592
 | 
				
			||||||
return_flow_temperature 39.937500
 | 
					return_flow_temperature_pred60 47.383083
 | 
				
			||||||
return_flow_temperature_avg10 40.087502
 | 
					 | 
				
			||||||
return_flow_temperature_avg60 41.146873
 | 
					 | 
				
			||||||
return_flow_temperature_damped 32.385151
 | 
					 | 
				
			||||||
return_flow_temperature_pred60 37.311958
 | 
					 | 
				
			||||||
chamber_temperature_state 0
 | 
					chamber_temperature_state 0
 | 
				
			||||||
outdoor_temperature_state 0
 | 
					outdoor_temperature_state 0
 | 
				
			||||||
inlet_flow_temperature_state 0
 | 
					inlet_flow_temperature_state 0
 | 
				
			||||||
return_flow_temperature_state 0
 | 
					return_flow_temperature_state 0
 | 
				
			||||||
safety_state 0
 | 
					safety_state 0
 | 
				
			||||||
control_state 3
 | 
					control_state 3
 | 
				
			||||||
control_current_weekday 5
 | 
					 | 
				
			||||||
control_current_entry_time 17100
 | 
					 | 
				
			||||||
control_current_entry_chamber_temperature 80.000000
 | 
					 | 
				
			||||||
control_current_entry_return_flow_temperature 30.000000
 | 
					 | 
				
			||||||
sntp_state 0
 | 
					sntp_state 0
 | 
				
			||||||
system_unixtime 1762012743
 | 
					system_unixtime 1735242392
 | 
				
			||||||
uptime_seconds 465229
 | 
					uptime_seconds 40
 | 
				
			||||||
wifi_rssi -72
 | 
					wifi_rssi -74
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Status Encoding
 | 
					#### Status Encoding
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										392
									
								
								main/control.c
									
									
									
									
									
								
							
							
						
						
									
										392
									
								
								main/control.c
									
									
									
									
									
								
							@ -1,101 +1,41 @@
 | 
				
			|||||||
#include "control.h"
 | 
					 | 
				
			||||||
#include "esp_log.h"
 | 
					 | 
				
			||||||
#include "esp_timer.h"
 | 
					 | 
				
			||||||
#include "freertos/FreeRTOS.h"
 | 
					#include "freertos/FreeRTOS.h"
 | 
				
			||||||
#include "freertos/task.h"
 | 
					#include "freertos/task.h"
 | 
				
			||||||
#include "inputs.h"
 | 
					#include "esp_timer.h"
 | 
				
			||||||
 | 
					#include "esp_log.h"
 | 
				
			||||||
 | 
					#include "control.h"
 | 
				
			||||||
#include "outputs.h"
 | 
					#include "outputs.h"
 | 
				
			||||||
 | 
					#include "inputs.h"
 | 
				
			||||||
#include "safety.h"
 | 
					#include "safety.h"
 | 
				
			||||||
#include "sntp.h"
 | 
					#include "sntp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PERIODIC_INTERVAL 1U // Run control loop every 1 second
 | 
					#define PERIODIC_INTERVAL 1U // run control loop every 1sec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Temperature thresholds
 | 
					#define RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY 30.0
 | 
				
			||||||
#define RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY 30.0f
 | 
					#define RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT 25.0
 | 
				
			||||||
#define RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT 25.0f
 | 
					#define CHAMPER_TEMPERATURE_TARGET 80.0
 | 
				
			||||||
#define CHAMBER_TEMPERATURE_TARGET 80.0f    // Max cutoff temperature
 | 
					#define BURNER_FAULT_DETECTION_THRESHOLD (60U * 3U) // Detect burner fault if after 3 minutes no burner start detected
 | 
				
			||||||
#define CHAMBER_TEMPERATURE_THRESHOLD 45.0f // Min threshold for burner enable
 | 
					 | 
				
			||||||
#define SUMMER_MODE_TEMPERATURE_THRESHOLD_HIGH \
 | 
					 | 
				
			||||||
    20.0f // Summer mode will be activated
 | 
					 | 
				
			||||||
#define SUMMER_MODE_TEMPERATURE_THRESHOLD_LOW \
 | 
					 | 
				
			||||||
    15.0f // Summer mode will be deactivated --> Heating starts
 | 
					 | 
				
			||||||
#define CIRCULATION_PUMP_TEMPERATURE_THRESHOLD \
 | 
					 | 
				
			||||||
    30.0f // Min threshold of chamber for circulation pump enable
 | 
					 | 
				
			||||||
#define BURNER_FAULT_DETECTION_THRESHOLD \
 | 
					 | 
				
			||||||
    (60U * 4U) // Burner fault detection after 4 minutes
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *TAG = "smart-oil-heater-control-system-control";
 | 
					static const char *TAG = "smart-oil-heater-control-system-control";
 | 
				
			||||||
static eControlState sControlState = CONTROL_STARTING;
 | 
					static eControlState sControlState = CONTROL_STARTING;
 | 
				
			||||||
// Control table for daily schedules
 | 
					 | 
				
			||||||
static const sControlDay aControlTable[] = {
 | 
					 | 
				
			||||||
    {MONDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{4, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{22, 0},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {TUESDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{4, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{22, 0},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {WEDNESDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{4, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{22, 0},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {THURSDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{4, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{22, 0},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {FRIDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{4, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{23, 0},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {SATURDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{6, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{23, 30},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
    {SUNDAY,
 | 
					 | 
				
			||||||
     2U,
 | 
					 | 
				
			||||||
     {{{6, 45},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET},
 | 
					 | 
				
			||||||
      {{22, 30},
 | 
					 | 
				
			||||||
       RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT,
 | 
					 | 
				
			||||||
       CHAMBER_TEMPERATURE_TARGET}}},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static sControlTemperatureEntry currentControlEntry =
 | 
					 | 
				
			||||||
    aControlTable[0].aTemperatureEntries[0];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Function prototypes
 | 
					static sControlDay aControlTable[] = {
 | 
				
			||||||
 | 
					    {MONDAY, 2U, {{{4, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{22, 0}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {TUESDAY, 2U, {{{4, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{22, 0}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {WEDNESDAY, 2U, {{{4, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{22, 0}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {THURSDAY, 2U, {{{4, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{22, 0}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {FRIDAY, 2U, {{{4, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{23, 0}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {SATURDAY, 2U, {{{6, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{23, 30}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					    {SUNDAY, 2U, {{{6, 45}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_DAY, CHAMPER_TEMPERATURE_TARGET}, {{22, 30}, RETURN_FLOW_TEMPERATURE_LOWER_LIMIT_NIGHT, CHAMPER_TEMPERATURE_TARGET}}},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void taskControl(void *pvParameters);
 | 
					void taskControl(void *pvParameters);
 | 
				
			||||||
void findControlCurrentTemperatureEntry(void);
 | 
					eControlWeekday getCurrentWeekday(void);
 | 
				
			||||||
 | 
					sControlTemperatureEntry getCurrentTemperatureEntry(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void initControl(void)
 | 
					void initControl(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BaseType_t taskCreated =
 | 
					    BaseType_t taskCreated = xTaskCreate(
 | 
				
			||||||
        xTaskCreate(taskControl,   // Function to implement the task
 | 
					        taskControl,   // Function to implement the task
 | 
				
			||||||
        "taskControl", // Task name
 | 
					        "taskControl", // Task name
 | 
				
			||||||
        8192,          // Stack size (in words, not bytes)
 | 
					        8192,          // Stack size (in words, not bytes)
 | 
				
			||||||
        NULL,          // Parameters to the task function (none in this case)
 | 
					        NULL,          // Parameters to the task function (none in this case)
 | 
				
			||||||
@ -116,79 +56,92 @@ void initControl(void)
 | 
				
			|||||||
void taskControl(void *pvParameters)
 | 
					void taskControl(void *pvParameters)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bool bHeatingInAction = false;
 | 
					    bool bHeatingInAction = false;
 | 
				
			||||||
    bool bSummerMode = false;
 | 
					    bool bBurnerFaultDetected = false;
 | 
				
			||||||
    eBurnerState eBurnerState = BURNER_UNKNOWN;
 | 
					 | 
				
			||||||
    int64_t i64BurnerEnableTimestamp = esp_timer_get_time();
 | 
					    int64_t i64BurnerEnableTimestamp = esp_timer_get_time();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    time_t now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while (1)
 | 
					    while (1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        // Get the current time
 | 
				
			||||||
 | 
					        time(&now);
 | 
				
			||||||
 | 
					        ESP_LOGW(TAG, "Control loop time: %lli", now);
 | 
				
			||||||
        vTaskDelay(PERIODIC_INTERVAL * 1000U / portTICK_PERIOD_MS);
 | 
					        vTaskDelay(PERIODIC_INTERVAL * 1000U / portTICK_PERIOD_MS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check for safety faults
 | 
					 | 
				
			||||||
        if (getSafetyState() != SAFETY_NO_ERROR)
 | 
					        if (getSafetyState() != SAFETY_NO_ERROR)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ESP_LOGW(TAG, "Control not possible due to safety fault!");
 | 
					            //ESP_LOGW(TAG, "Control not possible due to safety fault!");
 | 
				
			||||||
            sControlState = CONTROL_FAULT_SAFETY;
 | 
					            sControlState = CONTROL_FAULT_SAFETY;
 | 
				
			||||||
            if (bHeatingInAction)
 | 
					            if (bHeatingInAction == true)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ESP_LOGW(TAG, "Disabling burner due to safety fault");
 | 
					                ESP_LOGW(TAG, "Control not possible due to safety fault: Disable burner");
 | 
				
			||||||
                bHeatingInAction = false;
 | 
					                bHeatingInAction = false;
 | 
				
			||||||
 | 
					                setCirculationPumpState(ENABLED);
 | 
				
			||||||
                setBurnerState(DISABLED);
 | 
					                setBurnerState(DISABLED);
 | 
				
			||||||
                setSafetyControlState(ENABLED);
 | 
					                setSafetyControlState(ENABLED);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Check for SNTP faults
 | 
					 | 
				
			||||||
        if (getSntpState() != SYNC_SUCCESSFUL)
 | 
					        if (getSntpState() != SYNC_SUCCESSFUL)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ESP_LOGW(TAG, "Control not possible due to SNTP fault!");
 | 
					            ESP_LOGW(TAG, "Control not possible due to sntp fault!");
 | 
				
			||||||
            sControlState = CONTROL_FAULT_SNTP;
 | 
					            sControlState = CONTROL_FAULT_SNTP;
 | 
				
			||||||
            if (bHeatingInAction)
 | 
					            if (bHeatingInAction == true)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ESP_LOGW(TAG, "Disabling burner due to SNTP fault");
 | 
					                ESP_LOGW(TAG, "Control not possible due to sntp fault: Disable burner");
 | 
				
			||||||
                bHeatingInAction = false;
 | 
					                bHeatingInAction = false;
 | 
				
			||||||
 | 
					                setCirculationPumpState(ENABLED);
 | 
				
			||||||
                setBurnerState(DISABLED);
 | 
					                setBurnerState(DISABLED);
 | 
				
			||||||
                setSafetyControlState(ENABLED);
 | 
					                setSafetyControlState(ENABLED);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        findControlCurrentTemperatureEntry();
 | 
					        sControlTemperatureEntry currentControlEntry = getCurrentTemperatureEntry();
 | 
				
			||||||
        sControlTemperatureEntry currentControlEntry =
 | 
					        // ESP_LOGI(TAG, "Control Entry Hour: %i Minute: %i ChamberTemp: %lf ReturnFlowTemp: %lf", currentControlEntry.timestamp.hour, currentControlEntry.timestamp.minute, currentControlEntry.fChamberTemperature, currentControlEntry.fReturnFlowTemperature);
 | 
				
			||||||
            getControlCurrentTemperatureEntry();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (getOutdoorTemperature().fDampedValue >=
 | 
					        if (bHeatingInAction == true)
 | 
				
			||||||
            SUMMER_MODE_TEMPERATURE_THRESHOLD_HIGH)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            bSummerMode = true;
 | 
					            if ((getChamberTemperature().fCurrentValue >= currentControlEntry.fChamberTemperature) || (getChamberTemperature().predict60s.fValue >= currentControlEntry.fChamberTemperature))
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else if (getOutdoorTemperature().fDampedValue <=
 | 
					 | 
				
			||||||
                 SUMMER_MODE_TEMPERATURE_THRESHOLD_LOW)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
            bSummerMode = false;
 | 
					                ESP_LOGI(TAG, "Chamber Target Temperature reached: Disable burner");
 | 
				
			||||||
        }
 | 
					                bHeatingInAction = false;
 | 
				
			||||||
 | 
					                setCirculationPumpState(ENABLED);
 | 
				
			||||||
        // Enable burner if outdoor temperature is low and return flow temperature
 | 
					 | 
				
			||||||
        // is cooled down
 | 
					 | 
				
			||||||
        if (!bHeatingInAction && (eBurnerState != BURNER_FAULT))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (bSummerMode)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // ESP_LOGI(TAG, "Outdoor temperature too warm: Disabling heating");
 | 
					 | 
				
			||||||
                setBurnerState(DISABLED);
 | 
					                setBurnerState(DISABLED);
 | 
				
			||||||
                setSafetyControlState(DISABLED);
 | 
					                setSafetyControlState(ENABLED);
 | 
				
			||||||
                sControlState = CONTROL_OUTDOOR_TOO_WARM;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if ((getReturnFlowTemperature().average60s.fValue <=
 | 
					            else
 | 
				
			||||||
                      currentControlEntry.fReturnFlowTemperature) &&
 | 
					 | 
				
			||||||
                     (getChamberTemperature().fCurrentValue <=
 | 
					 | 
				
			||||||
                      CHAMBER_TEMPERATURE_THRESHOLD))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ESP_LOGI(TAG,
 | 
					                if (bHeatingInAction)
 | 
				
			||||||
                         "Enabling burner: Return flow temperature target reached");
 | 
					                {
 | 
				
			||||||
                eBurnerState = BURNER_UNKNOWN;
 | 
					                    int64_t i64Delta = esp_timer_get_time() - i64BurnerEnableTimestamp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if ((i64Delta / 1000000U) >= BURNER_FAULT_DETECTION_THRESHOLD)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if (getBurnerError() == FAULT)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            ESP_LOGW(TAG, "Detected burner fault after %lli seconds!", (i64Delta / 1000000U));
 | 
				
			||||||
 | 
					                            ESP_LOGW(TAG, "Control not possible due to burner fault: Disable burner");
 | 
				
			||||||
 | 
					                            sControlState = CONTROL_FAULT_BURNER;
 | 
				
			||||||
 | 
					                            bHeatingInAction = false;
 | 
				
			||||||
 | 
					                            bBurnerFaultDetected = true;
 | 
				
			||||||
 | 
					                            setCirculationPumpState(ENABLED);
 | 
				
			||||||
 | 
					                            setBurnerState(DISABLED);
 | 
				
			||||||
 | 
					                            setSafetyControlState(ENABLED);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((bHeatingInAction == false) && (bBurnerFaultDetected == false))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((getReturnFlowTemperature().average60s.fValue <= currentControlEntry.fReturnFlowTemperature) && (getChamberTemperature().fCurrentValue <= 45.0))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ESP_LOGI(TAG, "Return Flow Target Temperature reached: Enable Burner");
 | 
				
			||||||
                bHeatingInAction = true;
 | 
					                bHeatingInAction = true;
 | 
				
			||||||
 | 
					                setCirculationPumpState(ENABLED);
 | 
				
			||||||
                setBurnerState(ENABLED);
 | 
					                setBurnerState(ENABLED);
 | 
				
			||||||
                setSafetyControlState(ENABLED);
 | 
					                setSafetyControlState(ENABLED);
 | 
				
			||||||
                i64BurnerEnableTimestamp = esp_timer_get_time();
 | 
					                i64BurnerEnableTimestamp = esp_timer_get_time();
 | 
				
			||||||
@ -196,164 +149,89 @@ void taskControl(void *pvParameters)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // ESP_LOGI(TAG, "Return flow temperature too warm: Disabling heating");
 | 
					 | 
				
			||||||
                sControlState = CONTROL_RETURN_FLOW_TOO_WARM;
 | 
					                sControlState = CONTROL_RETURN_FLOW_TOO_WARM;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Disable burner if target temperature is reached or a fault occurred
 | 
					 | 
				
			||||||
        if (bHeatingInAction)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if ((getChamberTemperature().fCurrentValue >=
 | 
					 | 
				
			||||||
                 currentControlEntry.fChamberTemperature) ||
 | 
					 | 
				
			||||||
                (getChamberTemperature().predict60s.fValue >=
 | 
					 | 
				
			||||||
                 currentControlEntry.fChamberTemperature))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ESP_LOGI(TAG, "Chamber target temperature reached: Disabling burner");
 | 
					 | 
				
			||||||
                bHeatingInAction = false;
 | 
					 | 
				
			||||||
                setBurnerState(DISABLED);
 | 
					 | 
				
			||||||
                setSafetyControlState(ENABLED);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
            else if (esp_timer_get_time() - i64BurnerEnableTimestamp >=
 | 
					 | 
				
			||||||
                     BURNER_FAULT_DETECTION_THRESHOLD * 1000000U)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                if (eBurnerState == BURNER_UNKNOWN)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    if (getBurnerError() == FAULT)
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        // ESP_LOGW(TAG, "Burner fault detected: Disabling burner");
 | 
					 | 
				
			||||||
                        bHeatingInAction = false;
 | 
					 | 
				
			||||||
                        eBurnerState = BURNER_FAULT;
 | 
					 | 
				
			||||||
                        sControlState = CONTROL_FAULT_BURNER;
 | 
					 | 
				
			||||||
                        setBurnerState(DISABLED);
 | 
					 | 
				
			||||||
                        setSafetyControlState(ENABLED);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    else
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        // ESP_LOGI(TAG, "No burner fault detected: Marking burner as
 | 
					 | 
				
			||||||
                        // fired");
 | 
					 | 
				
			||||||
                        eBurnerState = BURNER_FIRED;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Manage circulation pump
 | 
					 | 
				
			||||||
        if (getChamberTemperature().fCurrentValue <=
 | 
					 | 
				
			||||||
            CIRCULATION_PUMP_TEMPERATURE_THRESHOLD)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // ESP_LOGI(TAG, "Burner cooled down: Disabling circulation pump");
 | 
					 | 
				
			||||||
            setCirculationPumpState(DISABLED);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // ESP_LOGI(TAG, "Burner heated: Enabling circulation pump");
 | 
					 | 
				
			||||||
            setCirculationPumpState(ENABLED);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } // End of while(1)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
eControlState getControlState(void) { return sControlState; }
 | 
					eControlState getControlState(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return sControlState;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
eControlWeekday getControlCurrentWeekday(void)
 | 
					eControlWeekday getCurrentWeekday(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    time_t now;
 | 
					    time_t now;
 | 
				
			||||||
    struct tm *timeinfo;
 | 
					    struct tm *timeinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get the current time
 | 
				
			||||||
    time(&now);
 | 
					    time(&now);
 | 
				
			||||||
    timeinfo = localtime(&now);
 | 
					    timeinfo = localtime(&now); // Convert to local time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get the day of the week (0 = Sunday, 1 = Monday, ..., 6 = Saturday)
 | 
				
			||||||
    int day = timeinfo->tm_wday;
 | 
					    int day = timeinfo->tm_wday;
 | 
				
			||||||
    return (eControlWeekday)((day == 0) ? 6 : day - 1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					    // Adjust so that Monday = 0, Sunday = 6
 | 
				
			||||||
 * @brief Finds the active temperature control entry for the current time.
 | 
					    if (day == 0)
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Searches through the weekly schedule to find the most recent entry
 | 
					 | 
				
			||||||
 * that should be active at the current date/time. Falls back to the
 | 
					 | 
				
			||||||
 * last entry in the week if no suitable entry is found.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @brief Finds the active temperature control entry for the current time.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Searches through the weekly schedule to find the most recent entry
 | 
					 | 
				
			||||||
 * that should be active at the current date/time. Falls back to the
 | 
					 | 
				
			||||||
 * last entry in the week if no suitable entry is found.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void findControlCurrentTemperatureEntry(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    eControlWeekday currentDay = getControlCurrentWeekday();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Get current time
 | 
					 | 
				
			||||||
    time_t now;
 | 
					 | 
				
			||||||
    struct tm timeinfo;
 | 
					 | 
				
			||||||
    time(&now);
 | 
					 | 
				
			||||||
    localtime_r(&now, &timeinfo);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    int currentHour = timeinfo.tm_hour;
 | 
					 | 
				
			||||||
    int currentMinute = timeinfo.tm_min;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // ESP_LOGI(TAG, "Searching for control entry - Day: %d, Time: %02d:%02d", currentDay, currentHour, currentMinute);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Search through all days and entries
 | 
					 | 
				
			||||||
    for (int dayIndex = 0; dayIndex < 7; dayIndex++)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        const sControlDay *day = &aControlTable[dayIndex];
 | 
					        day = 6; // Sunday becomes 6
 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int entryIndex = 0; entryIndex < day->entryCount; entryIndex++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            const sControlTemperatureEntry *entry = &day->aTemperatureEntries[entryIndex];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Check if this entry is in the future (next active entry)
 | 
					 | 
				
			||||||
            bool isFutureDay = (day->day > currentDay);
 | 
					 | 
				
			||||||
            bool isTodayFutureTime = (day->day == currentDay) &&
 | 
					 | 
				
			||||||
                                     ((entry->timestamp.hour > currentHour) ||
 | 
					 | 
				
			||||||
                                      (entry->timestamp.hour == currentHour &&
 | 
					 | 
				
			||||||
                                       entry->timestamp.minute > currentMinute));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (isFutureDay || isTodayFutureTime)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                // Found next scheduled entry, so determine the previous (active) one
 | 
					 | 
				
			||||||
                if (entryIndex > 0)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // Use previous entry from same day
 | 
					 | 
				
			||||||
                    currentControlEntry = day->aTemperatureEntries[entryIndex - 1];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                else if (dayIndex > 0)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // Use last entry from previous day
 | 
					 | 
				
			||||||
                    const sControlDay *previousDay = &aControlTable[dayIndex - 1];
 | 
					 | 
				
			||||||
                    currentControlEntry = previousDay->aTemperatureEntries[previousDay->entryCount - 1];
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
                    // First entry of the week - wrap to last entry of Sunday
 | 
					        day -= 1; // Shift other days to make Monday = 0
 | 
				
			||||||
                    const sControlDay *sunday = &aControlTable[6];
 | 
					 | 
				
			||||||
                    currentControlEntry = sunday->aTemperatureEntries[sunday->entryCount - 1];
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                /*
 | 
					 | 
				
			||||||
                ESP_LOGI(TAG, "Active entry found - Time: %02d:%02d, "
 | 
					 | 
				
			||||||
                         "Return Temp: %lf, Chamber Temp: %lf",
 | 
					 | 
				
			||||||
                         currentControlEntry.timestamp.hour,
 | 
					 | 
				
			||||||
                         currentControlEntry.timestamp.minute,
 | 
					 | 
				
			||||||
                         currentControlEntry.fReturnFlowTemperature,
 | 
					 | 
				
			||||||
                         currentControlEntry.fChamberTemperature);
 | 
					 | 
				
			||||||
                         */
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // If we reached here, current time is after all entries this week
 | 
					    return (eControlWeekday)day;
 | 
				
			||||||
    // Use the last entry (Sunday evening)
 | 
					 | 
				
			||||||
    const sControlDay *sunday = &aControlTable[6];
 | 
					 | 
				
			||||||
    currentControlEntry = sunday->aTemperatureEntries[sunday->entryCount - 1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // ESP_LOGI(TAG, "Using last entry of week - Time: %02d:%02d", currentControlEntry.timestamp.hour, currentControlEntry.timestamp.minute);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sControlTemperatureEntry getControlCurrentTemperatureEntry(void)
 | 
					sControlTemperatureEntry getCurrentTemperatureEntry(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return currentControlEntry;
 | 
					    sControlTemperatureEntry result = aControlTable[0].aTemperatureEntries[0];
 | 
				
			||||||
 | 
					    eControlWeekday currentDay = getCurrentWeekday();
 | 
				
			||||||
 | 
					    time_t now;
 | 
				
			||||||
 | 
					    struct tm timeinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Get the current time
 | 
				
			||||||
 | 
					    time(&now);
 | 
				
			||||||
 | 
					    // Convert to local time structure
 | 
				
			||||||
 | 
					    localtime_r(&now, &timeinfo);
 | 
				
			||||||
 | 
					    // Extract hour and minute
 | 
				
			||||||
 | 
					    int hour = timeinfo.tm_hour;  // Hour (0-23)
 | 
				
			||||||
 | 
					    int minute = timeinfo.tm_min; // Minute (0-59)u
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ESP_LOGI(TAG, "Current Day: %i Hour: %i Minute: %i", currentDay, hour, minute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < sizeof(aControlTable) / sizeof(aControlTable[0]); i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /// loops through days
 | 
				
			||||||
 | 
					        // ESP_LOGI(TAG, "Day %d: %d", i + 1, aControlTable[i].day);
 | 
				
			||||||
 | 
					        // int numberOfEntries = aControlTable[i].entryCount;
 | 
				
			||||||
 | 
					        // ESP_LOGI(TAG, "Number of entries: %i", numberOfEntries);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int j = 0; j < aControlTable[i].entryCount; j++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if ((aControlTable[i].day) > currentDay)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // ESP_LOGI(TAG, "DAY Return Control Entry Day: %i Hour: %i Minute: %i ChamberTemp: %lf ReturnFlowTemp: %lf", aControlTable[i].day, aControlTable[i].aTemperatureEntries[j].timestamp.hour, aControlTable[i].aTemperatureEntries[j].timestamp.minute, aControlTable[i].aTemperatureEntries[j].fChamberTemperature, aControlTable[i].aTemperatureEntries[j].fReturnFlowTemperature);
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((aControlTable[i].day == currentDay) && (aControlTable[i].aTemperatureEntries[j].timestamp.hour > hour))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // ESP_LOGI(TAG, "HOUR Return Control Entry Day: %i Hour: %i Minute: %i ChamberTemp: %lf ReturnFlowTemp: %lf", aControlTable[i].day, aControlTable[i].aTemperatureEntries[j].timestamp.hour, aControlTable[i].aTemperatureEntries[j].timestamp.minute, aControlTable[i].aTemperatureEntries[j].fChamberTemperature, aControlTable[i].aTemperatureEntries[j].fReturnFlowTemperature);
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((aControlTable[i].day == currentDay) && (aControlTable[i].aTemperatureEntries[j].timestamp.hour == hour) && (aControlTable[i].aTemperatureEntries[j].timestamp.minute == minute))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // ESP_LOGI(TAG, "MINUTE Return Control Entry Day: %i Hour: %i Minute: %i ChamberTemp: %lf ReturnFlowTemp: %lf", aControlTable[i].day, aControlTable[i].aTemperatureEntries[j].timestamp.hour, aControlTable[i].aTemperatureEntries[j].timestamp.minute, aControlTable[i].aTemperatureEntries[j].fChamberTemperature, aControlTable[i].aTemperatureEntries[j].fReturnFlowTemperature);
 | 
				
			||||||
 | 
					                return result;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // ESP_LOGI(TAG, "SET Return Control Entry Day: %i Hour: %i Minute: %i ChamberTemp: %lf ReturnFlowTemp: %lf", aControlTable[i].day, aControlTable[i].aTemperatureEntries[j].timestamp.hour, aControlTable[i].aTemperatureEntries[j].timestamp.minute, aControlTable[i].aTemperatureEntries[j].fChamberTemperature, aControlTable[i].aTemperatureEntries[j].fReturnFlowTemperature);
 | 
				
			||||||
 | 
					            result = aControlTable[i].aTemperatureEntries[j];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -14,13 +14,6 @@ typedef enum _ControlState
 | 
				
			|||||||
    CONTROL_FAULT_SNTP,
 | 
					    CONTROL_FAULT_SNTP,
 | 
				
			||||||
} eControlState;
 | 
					} eControlState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum _BurnerState
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    BURNER_UNKNOWN, // Burner is disabled or state after enabling is still unkown
 | 
					 | 
				
			||||||
    BURNER_FIRED,   // Burner fired successfully
 | 
					 | 
				
			||||||
    BURNER_FAULT    // Burner was unable to fire successfully
 | 
					 | 
				
			||||||
} eBurnerState;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef enum _ControlWeekday
 | 
					typedef enum _ControlWeekday
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MONDAY,
 | 
					    MONDAY,
 | 
				
			||||||
@ -54,5 +47,3 @@ typedef struct _ControlDay
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void initControl(void);
 | 
					void initControl(void);
 | 
				
			||||||
eControlState getControlState(void);
 | 
					eControlState getControlState(void);
 | 
				
			||||||
eControlWeekday getControlCurrentWeekday(void);
 | 
					 | 
				
			||||||
sControlTemperatureEntry getControlCurrentTemperatureEntry(void);
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ const uint8_t uBurnerFaultPin = 19U;
 | 
				
			|||||||
const uint8_t uDS18B20Pin = 4U;
 | 
					const uint8_t uDS18B20Pin = 4U;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onewire_addr_t uChamperTempSensorAddr = 0xd00000108cd01d28;
 | 
					const onewire_addr_t uChamperTempSensorAddr = 0xd00000108cd01d28;
 | 
				
			||||||
const onewire_addr_t uOutdoorTempSensorAddr = 0xd70000108a9b9128;
 | 
					const onewire_addr_t uOutdoorTempSensorAddr = 0x78000000c6c2f728;
 | 
				
			||||||
const onewire_addr_t uInletFlowTempSensorAddr = 0x410000108b8c0628;
 | 
					const onewire_addr_t uInletFlowTempSensorAddr = 0x410000108b8c0628;
 | 
				
			||||||
const onewire_addr_t uReturnFlowTempSensorAddr = 0x90000108cc77c28;
 | 
					const onewire_addr_t uReturnFlowTempSensorAddr = 0x90000108cc77c28;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -88,23 +88,22 @@ void initMeasurement(sMeasurement *pMeasurement)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pMeasurement->state = MEASUREMENT_FAULT;
 | 
					    pMeasurement->state = MEASUREMENT_FAULT;
 | 
				
			||||||
    pMeasurement->fCurrentValue = INITIALISATION_VALUE;
 | 
					    pMeasurement->fCurrentValue = 0.0f;
 | 
				
			||||||
    pMeasurement->fDampedValue = INITIALISATION_VALUE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pMeasurement->average10s.fValue = INITIALISATION_VALUE;
 | 
					    pMeasurement->average10s.fValue = 0.0f;
 | 
				
			||||||
    pMeasurement->average10s.bufferCount = 0U;
 | 
					    pMeasurement->average10s.bufferCount = 0U;
 | 
				
			||||||
    pMeasurement->average10s.bufferIndex = 0U;
 | 
					    pMeasurement->average10s.bufferIndex = 0U;
 | 
				
			||||||
    memset(pMeasurement->average10s.samples, 0U, AVG10S_SAMPLE_SIZE);
 | 
					    memset(pMeasurement->average10s.samples, 0U, AVG10_SAMPLE_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pMeasurement->average60s.fValue = INITIALISATION_VALUE;
 | 
					    pMeasurement->average60s.fValue = 0.0f;
 | 
				
			||||||
    pMeasurement->average60s.bufferCount = 0U;
 | 
					    pMeasurement->average60s.bufferCount = 0U;
 | 
				
			||||||
    pMeasurement->average60s.bufferIndex = 0U;
 | 
					    pMeasurement->average60s.bufferIndex = 0U;
 | 
				
			||||||
    memset(pMeasurement->average60s.samples, 0U, AVG60S_SAMPLE_SIZE);
 | 
					    memset(pMeasurement->average60s.samples, 0U, AVG60_SAMPLE_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pMeasurement->predict60s.fValue = INITIALISATION_VALUE;
 | 
					    pMeasurement->predict60s.fValue = 0.0f;
 | 
				
			||||||
    pMeasurement->predict60s.bufferCount = 0U;
 | 
					    pMeasurement->predict60s.bufferCount = 0U;
 | 
				
			||||||
    pMeasurement->predict60s.bufferIndex = 0U;
 | 
					    pMeasurement->predict60s.bufferIndex = 0U;
 | 
				
			||||||
    memset(pMeasurement->predict60s.samples, 0U, PRED60S_SAMPLE_SIZE);
 | 
					    memset(pMeasurement->predict60s.samples, 0U, PRED60_SAMPLE_SIZE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void updateAverage(sMeasurement *pMeasurement)
 | 
					void updateAverage(sMeasurement *pMeasurement)
 | 
				
			||||||
@ -114,9 +113,9 @@ void updateAverage(sMeasurement *pMeasurement)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Average form the last 10sec
 | 
					    // Average form the last 10sec
 | 
				
			||||||
    pMeasurement->average10s.samples[pMeasurement->average10s.bufferIndex] = pMeasurement->fCurrentValue;
 | 
					    pMeasurement->average10s.samples[pMeasurement->average10s.bufferIndex] = pMeasurement->fCurrentValue;
 | 
				
			||||||
    pMeasurement->average10s.bufferIndex = (pMeasurement->average10s.bufferIndex + 1) % AVG10S_SAMPLE_SIZE;
 | 
					    pMeasurement->average10s.bufferIndex = (pMeasurement->average10s.bufferIndex + 1) % AVG10_SAMPLE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pMeasurement->average10s.bufferCount < AVG10S_SAMPLE_SIZE)
 | 
					    if (pMeasurement->average10s.bufferCount < AVG10_SAMPLE_SIZE)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        pMeasurement->average10s.bufferCount++;
 | 
					        pMeasurement->average10s.bufferCount++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -131,9 +130,9 @@ void updateAverage(sMeasurement *pMeasurement)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Average form the last 60sec
 | 
					    // Average form the last 60sec
 | 
				
			||||||
    pMeasurement->average60s.samples[pMeasurement->average60s.bufferIndex] = pMeasurement->fCurrentValue;
 | 
					    pMeasurement->average60s.samples[pMeasurement->average60s.bufferIndex] = pMeasurement->fCurrentValue;
 | 
				
			||||||
    pMeasurement->average60s.bufferIndex = (pMeasurement->average60s.bufferIndex + 1) % AVG60S_SAMPLE_SIZE;
 | 
					    pMeasurement->average60s.bufferIndex = (pMeasurement->average60s.bufferIndex + 1) % AVG60_SAMPLE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (pMeasurement->average60s.bufferCount < AVG60S_SAMPLE_SIZE)
 | 
					    if (pMeasurement->average60s.bufferCount < AVG60_SAMPLE_SIZE)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        pMeasurement->average60s.bufferCount++;
 | 
					        pMeasurement->average60s.bufferCount++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -145,24 +144,6 @@ void updateAverage(sMeasurement *pMeasurement)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pMeasurement->average60s.fValue = sum / pMeasurement->average60s.bufferCount;
 | 
					    pMeasurement->average60s.fValue = sum / pMeasurement->average60s.bufferCount;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Damped current value
 | 
					 | 
				
			||||||
    if (pMeasurement->fDampedValue == INITIALISATION_VALUE)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        pMeasurement->fDampedValue = pMeasurement->fCurrentValue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (pMeasurement->fCurrentValue > pMeasurement->fDampedValue)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            pMeasurement->fDampedValue = pMeasurement->fDampedValue + (DAMPING_FACTOR_WARMER * (pMeasurement->fCurrentValue - pMeasurement->fDampedValue));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pMeasurement->fCurrentValue < pMeasurement->fDampedValue)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            pMeasurement->fDampedValue = pMeasurement->fDampedValue - (DAMPING_FACTOR_COLDER * (pMeasurement->fDampedValue - pMeasurement->fCurrentValue));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void updatePrediction(sMeasurement *pMeasurement)
 | 
					void updatePrediction(sMeasurement *pMeasurement)
 | 
				
			||||||
@ -173,8 +154,8 @@ void updatePrediction(sMeasurement *pMeasurement)
 | 
				
			|||||||
    // Update predict60s buffer
 | 
					    // Update predict60s buffer
 | 
				
			||||||
    sPredict *predict60s = &pMeasurement->predict60s;
 | 
					    sPredict *predict60s = &pMeasurement->predict60s;
 | 
				
			||||||
    predict60s->samples[predict60s->bufferIndex] = pMeasurement->fCurrentValue;
 | 
					    predict60s->samples[predict60s->bufferIndex] = pMeasurement->fCurrentValue;
 | 
				
			||||||
    predict60s->bufferIndex = (predict60s->bufferIndex + 1) % PRED60S_SAMPLE_SIZE;
 | 
					    predict60s->bufferIndex = (predict60s->bufferIndex + 1) % PRED60_SAMPLE_SIZE;
 | 
				
			||||||
    if (predict60s->bufferCount < PRED60S_SAMPLE_SIZE)
 | 
					    if (predict60s->bufferCount < PRED60_SAMPLE_SIZE)
 | 
				
			||||||
        predict60s->bufferCount++;
 | 
					        predict60s->bufferCount++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Predict 60s future value using linear regression
 | 
					    // Predict 60s future value using linear regression
 | 
				
			||||||
@ -208,12 +189,12 @@ void taskInput(void *pvParameters)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (ds18x20_scan_devices(uDS18B20Pin, uOneWireAddresses, MAX_DN18B20_SENSORS, &sSensorCount) != ESP_OK)
 | 
					            if (ds18x20_scan_devices(uDS18B20Pin, uOneWireAddresses, MAX_DN18B20_SENSORS, &sSensorCount) != ESP_OK)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ESP_LOGE(TAG, "1-Wire device scan error!");
 | 
					               // ESP_LOGE(TAG, "1-Wire device scan error!");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!sSensorCount)
 | 
					            if (!sSensorCount)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                ESP_LOGW(TAG, "No 1-Wire devices detected!");
 | 
					               // ESP_LOGW(TAG, "No 1-Wire devices detected!");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -222,14 +203,14 @@ void taskInput(void *pvParameters)
 | 
				
			|||||||
                if (sSensorCount > MAX_DN18B20_SENSORS)
 | 
					                if (sSensorCount > MAX_DN18B20_SENSORS)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    sSensorCount = MAX_DN18B20_SENSORS;
 | 
					                    sSensorCount = MAX_DN18B20_SENSORS;
 | 
				
			||||||
                    ESP_LOGW(TAG, "More 1-Wire devices found than expected!");
 | 
					                   // ESP_LOGW(TAG, "More 1-Wire devices found than expected!");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for (size_t iReadLoop = 0; iReadLoop < ONE_WIRE_LOOPS; iReadLoop++)
 | 
					                for (size_t iReadLoop = 0; iReadLoop < ONE_WIRE_LOOPS; iReadLoop++)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (ds18x20_measure_and_read_multi(uDS18B20Pin, uOneWireAddresses, sSensorCount, fDS18B20Temps) != ESP_OK)
 | 
					                    if (ds18x20_measure_and_read_multi(uDS18B20Pin, uOneWireAddresses, sSensorCount, fDS18B20Temps) != ESP_OK)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        ESP_LOGE(TAG, "1-Wire devices read error");
 | 
					                      //  ESP_LOGE(TAG, "1-Wire devices read error");
 | 
				
			||||||
                        vTaskDelay(PERIODIC_INTERVAL * 100U / portTICK_PERIOD_MS); // Wait 100ms if bus error occurred
 | 
					                        vTaskDelay(PERIODIC_INTERVAL * 100U / portTICK_PERIOD_MS); // Wait 100ms if bus error occurred
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else
 | 
					                    else
 | 
				
			||||||
@ -290,9 +271,9 @@ void taskInput(void *pvParameters)
 | 
				
			|||||||
float linearRegressionPredict(const float *samples, size_t count, size_t bufferIndex, float futureIndex)
 | 
					float linearRegressionPredict(const float *samples, size_t count, size_t bufferIndex, float futureIndex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (count == 0)
 | 
					    if (count == 0)
 | 
				
			||||||
        return INITIALISATION_VALUE; // No prediction possible with no data
 | 
					        return 0.0f; // No prediction possible with no data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    float sumX = INITIALISATION_VALUE, sumY = INITIALISATION_VALUE, sumXY = INITIALISATION_VALUE, sumX2 = INITIALISATION_VALUE;
 | 
					    float sumX = 0.0f, sumY = 0.0f, sumXY = 0.0f, sumX2 = 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (size_t i = 0; i < count; i++)
 | 
					    for (size_t i = 0; i < count; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,9 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
 | 
					#define MAX(a, b) ((a) > (b) ? (a) : (b))
 | 
				
			||||||
#define INITIALISATION_VALUE 0.0f
 | 
					#define AVG10_SAMPLE_SIZE 10U
 | 
				
			||||||
#define AVG10S_SAMPLE_SIZE 10U
 | 
					#define AVG60_SAMPLE_SIZE 60U
 | 
				
			||||||
#define AVG60S_SAMPLE_SIZE 60U
 | 
					#define PRED60_SAMPLE_SIZE 60U
 | 
				
			||||||
#define AVG24H_SAMPLE_SIZE 24U
 | 
					 | 
				
			||||||
#define PRED60S_SAMPLE_SIZE 60U
 | 
					 | 
				
			||||||
#define DAMPING_FACTOR_WARMER 0.00001f // 0.001%
 | 
					 | 
				
			||||||
#define DAMPING_FACTOR_COLDER 0.00005f // 0.005%
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum _BurnerErrorState
 | 
					typedef enum _BurnerErrorState
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -24,7 +20,7 @@ typedef enum _MeasurementErrorState
 | 
				
			|||||||
typedef struct _Average
 | 
					typedef struct _Average
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    float fValue;
 | 
					    float fValue;
 | 
				
			||||||
    float samples[MAX(AVG10S_SAMPLE_SIZE, MAX(AVG60S_SAMPLE_SIZE, AVG24H_SAMPLE_SIZE))];
 | 
					    float samples[MAX(AVG10_SAMPLE_SIZE, AVG60_SAMPLE_SIZE)];
 | 
				
			||||||
    size_t bufferIndex;
 | 
					    size_t bufferIndex;
 | 
				
			||||||
    size_t bufferCount;
 | 
					    size_t bufferCount;
 | 
				
			||||||
} sAverage;
 | 
					} sAverage;
 | 
				
			||||||
@ -32,7 +28,7 @@ typedef struct _Average
 | 
				
			|||||||
typedef struct _Predict
 | 
					typedef struct _Predict
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    float fValue;
 | 
					    float fValue;
 | 
				
			||||||
    float samples[PRED60S_SAMPLE_SIZE];
 | 
					    float samples[PRED60_SAMPLE_SIZE];
 | 
				
			||||||
    size_t bufferIndex;
 | 
					    size_t bufferIndex;
 | 
				
			||||||
    size_t bufferCount;
 | 
					    size_t bufferCount;
 | 
				
			||||||
} sPredict;
 | 
					} sPredict;
 | 
				
			||||||
@ -40,7 +36,6 @@ typedef struct _Predict
 | 
				
			|||||||
typedef struct _Measurement
 | 
					typedef struct _Measurement
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    float fCurrentValue;
 | 
					    float fCurrentValue;
 | 
				
			||||||
    float fDampedValue;
 | 
					 | 
				
			||||||
    sAverage average10s;
 | 
					    sAverage average10s;
 | 
				
			||||||
    sAverage average60s;
 | 
					    sAverage average60s;
 | 
				
			||||||
    sPredict predict60s;
 | 
					    sPredict predict60s;
 | 
				
			||||||
 | 
				
			|||||||
@ -128,12 +128,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average60s.fValue;
 | 
					        aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().average60s.fValue;
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Chamber Temperature Damped
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_damped");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getChamberTemperature().fDampedValue;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Chamber Temperature Predict 60s
 | 
					        // Chamber Temperature Predict 60s
 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_pred60");
 | 
					        strcpy(aMetrics[u16MetricCounter].caMetricName, "chamber_temperature_pred60");
 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					        aMetrics[u16MetricCounter].type = FLOAT;
 | 
				
			||||||
@ -158,12 +152,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average60s.fValue;
 | 
					        aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().average60s.fValue;
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Inlet Flow Temperature Damped
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_damped");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getInletFlowTemperature().fDampedValue;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Inlet Flow Temperature Predict 60s
 | 
					        // Inlet Flow Temperature Predict 60s
 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_pred60");
 | 
					        strcpy(aMetrics[u16MetricCounter].caMetricName, "inlet_flow_temperature_pred60");
 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					        aMetrics[u16MetricCounter].type = FLOAT;
 | 
				
			||||||
@ -188,12 +176,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average60s.fValue;
 | 
					        aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().average60s.fValue;
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Outdoor Temperature Average Damped
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_damped");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getOutdoorTemperature().fDampedValue;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Outdoor Temperature Predict 60s
 | 
					        // Outdoor Temperature Predict 60s
 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_pred60");
 | 
					        strcpy(aMetrics[u16MetricCounter].caMetricName, "outdoor_temperature_pred60");
 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					        aMetrics[u16MetricCounter].type = FLOAT;
 | 
				
			||||||
@ -218,12 +200,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue;
 | 
					        aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().average60s.fValue;
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Return Flow Temperature Damped
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_damped");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getReturnFlowTemperature().fDampedValue;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Return Flow Temperature Predict 60s
 | 
					        // Return Flow Temperature Predict 60s
 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_pred60");
 | 
					        strcpy(aMetrics[u16MetricCounter].caMetricName, "return_flow_temperature_pred60");
 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					        aMetrics[u16MetricCounter].type = FLOAT;
 | 
				
			||||||
@ -254,31 +230,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].u8MetricValue = getControlState();
 | 
					        aMetrics[u16MetricCounter].u8MetricValue = getControlState();
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Control Current Weekday
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "control_current_weekday");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = INTEGER_U8;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].u8MetricValue = getControlCurrentWeekday();
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Control Current Entry Time
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "control_current_entry_time");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = INTEGER_64;
 | 
					 | 
				
			||||||
        int64_t i64SecondsSinceMidnight = (getControlCurrentTemperatureEntry().timestamp.hour * 60U * 60U) + (getControlCurrentTemperatureEntry().timestamp.minute * 60U);
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].i64MetricValue = i64SecondsSinceMidnight;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Control Current Entry Chamber Temperature
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "control_current_entry_chamber_temperature");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getControlCurrentTemperatureEntry().fChamberTemperature;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Control Current Entry Return Flow Temperature
 | 
					 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "control_current_entry_return_flow_temperature");
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].type = FLOAT;
 | 
					 | 
				
			||||||
        aMetrics[u16MetricCounter].fMetricValue = getControlCurrentTemperatureEntry().fReturnFlowTemperature;
 | 
					 | 
				
			||||||
        u16MetricCounter++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // SNTP State
 | 
					        // SNTP State
 | 
				
			||||||
        strcpy(aMetrics[u16MetricCounter].caMetricName, "sntp_state");
 | 
					        strcpy(aMetrics[u16MetricCounter].caMetricName, "sntp_state");
 | 
				
			||||||
        aMetrics[u16MetricCounter].type = INTEGER_U8;
 | 
					        aMetrics[u16MetricCounter].type = INTEGER_U8;
 | 
				
			||||||
@ -307,7 +258,6 @@ void taskMetrics(void *pvParameters)
 | 
				
			|||||||
        aMetrics[u16MetricCounter].i64MetricValue = ap.rssi;
 | 
					        aMetrics[u16MetricCounter].i64MetricValue = ap.rssi;
 | 
				
			||||||
        u16MetricCounter++;
 | 
					        u16MetricCounter++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ESP_ERROR_CHECK(u16MetricCounter > METRIC_MAX_COUNT);
 | 
					 | 
				
			||||||
        vSetMetrics(aMetrics, u16MetricCounter);
 | 
					        vSetMetrics(aMetrics, u16MetricCounter);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define HTML_RESPONSE_SIZE 4096U
 | 
					#define HTML_RESPONSE_SIZE 4096U
 | 
				
			||||||
#define METRIC_NAME_MAX_SIZE 64U
 | 
					#define METRIC_NAME_MAX_SIZE 64U
 | 
				
			||||||
#define METRIC_MAX_COUNT 38U
 | 
					#define METRIC_MAX_COUNT 32U
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef enum _MetricValueType
 | 
					typedef enum _MetricValueType
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ void checkSensorSanity(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (sCurrentMeasurement.state == MEASUREMENT_FAULT)
 | 
					        if (sCurrentMeasurement.state == MEASUREMENT_FAULT)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ESP_LOGE(TAG, "%s Sensor not found!", sanityChecks[i].name);
 | 
					            //ESP_LOGE(TAG, "%s Sensor not found!", sanityChecks[i].name);
 | 
				
			||||||
            sanityChecks[i].state = SENSOR_NOT_FOUND;
 | 
					            sanityChecks[i].state = SENSOR_NOT_FOUND;
 | 
				
			||||||
            sSafetyState = SAFETY_SENSOR_ERROR;
 | 
					            sSafetyState = SAFETY_SENSOR_ERROR;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user