完成初代的雏形设计
This commit is contained in:
199
main/auto_ctrl_thresholds.c
Normal file
199
main/auto_ctrl_thresholds.c
Normal file
@@ -0,0 +1,199 @@
|
||||
#include "auto_ctrl_thresholds.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
// 默认光照强度低于此值时开启补光灯(单位:lux)
|
||||
#define DEFAULT_LIGHT_ON_LUX_BELOW 200.0f
|
||||
// 默认光照强度高于此值时关闭补光灯(单位:lux)
|
||||
#define DEFAULT_LIGHT_OFF_LUX_ABOVE 350.0f
|
||||
// 默认温度低于此值时开启加热(单位:摄氏度)
|
||||
#define DEFAULT_HOT_ON_TEMP_BELOW_C 18.0f
|
||||
// 默认温度高于此值时关闭加热(单位:摄氏度)
|
||||
#define DEFAULT_HOT_OFF_TEMP_ABOVE_C 20.0f
|
||||
// 默认温度高于此值时开启制冷(单位:摄氏度)
|
||||
#define DEFAULT_COOL_ON_TEMP_ABOVE_C 30.0f
|
||||
// 默认温度低于此值时关闭制冷(单位:摄氏度)
|
||||
#define DEFAULT_COOL_OFF_TEMP_BELOW_C 28.0f
|
||||
// 默认湿度高于此值时开启风扇(单位:%RH)
|
||||
#define DEFAULT_FAN_ON_HUMIDITY_ABOVE_PCT 80.0f
|
||||
// 默认湿度低于此值时关闭风扇(单位:%RH)
|
||||
#define DEFAULT_FAN_OFF_HUMIDITY_BELOW_PCT 70.0f
|
||||
|
||||
// 用于保护阈值数据的自旋锁(临界区)
|
||||
static portMUX_TYPE s_thresholds_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// 全局阈值配置结构体,初始化为默认值
|
||||
static auto_ctrl_thresholds_t s_thresholds = {
|
||||
.light_on_lux_below = DEFAULT_LIGHT_ON_LUX_BELOW,
|
||||
.light_off_lux_above = DEFAULT_LIGHT_OFF_LUX_ABOVE,
|
||||
.hot_on_temp_below_c = DEFAULT_HOT_ON_TEMP_BELOW_C,
|
||||
.hot_off_temp_above_c = DEFAULT_HOT_OFF_TEMP_ABOVE_C,
|
||||
.cool_on_temp_above_c = DEFAULT_COOL_ON_TEMP_ABOVE_C,
|
||||
.cool_off_temp_below_c = DEFAULT_COOL_OFF_TEMP_BELOW_C,
|
||||
.fan_on_humidity_above_pct = DEFAULT_FAN_ON_HUMIDITY_ABOVE_PCT,
|
||||
.fan_off_humidity_below_pct = DEFAULT_FAN_OFF_HUMIDITY_BELOW_PCT,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 验证自动控制阈值配置的有效性
|
||||
*
|
||||
* 检查指针非空、数值范围合法、启停阈值满足 on < off 等条件。
|
||||
*
|
||||
* @param cfg 待验证的阈值配置指针
|
||||
* @return esp_err_t 验证结果,ESP_OK 表示有效
|
||||
*/
|
||||
static esp_err_t auto_ctrl_thresholds_validate(const auto_ctrl_thresholds_t *cfg)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(cfg != NULL, ESP_ERR_INVALID_ARG, "auto_ctrl_thresholds", "cfg is null");
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->light_on_lux_below >= 0.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"light_on_lux_below out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->light_off_lux_above >= 0.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"light_off_lux_above out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->light_on_lux_below < cfg->light_off_lux_above,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"light thresholds must satisfy on < off");
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->hot_on_temp_below_c >= -40.0f && cfg->hot_on_temp_below_c <= 125.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"hot_on_temp_below_c out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->hot_off_temp_above_c >= -40.0f && cfg->hot_off_temp_above_c <= 125.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"hot_off_temp_above_c out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->hot_on_temp_below_c < cfg->hot_off_temp_above_c,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"hot thresholds must satisfy on < off");
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->cool_off_temp_below_c >= -40.0f && cfg->cool_off_temp_below_c <= 125.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"cool_off_temp_below_c out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->cool_on_temp_above_c >= -40.0f && cfg->cool_on_temp_above_c <= 125.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"cool_on_temp_above_c out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->cool_off_temp_below_c < cfg->cool_on_temp_above_c,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"cool thresholds must satisfy off < on");
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->hot_off_temp_above_c <= cfg->cool_off_temp_below_c,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"temperature thresholds overlap excessively");
|
||||
|
||||
ESP_RETURN_ON_FALSE(cfg->fan_on_humidity_above_pct >= 0.0f && cfg->fan_on_humidity_above_pct <= 100.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"fan_on_humidity_above_pct out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->fan_off_humidity_below_pct >= 0.0f && cfg->fan_off_humidity_below_pct <= 100.0f,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"fan_off_humidity_below_pct out of range");
|
||||
ESP_RETURN_ON_FALSE(cfg->fan_off_humidity_below_pct < cfg->fan_on_humidity_above_pct,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
"auto_ctrl_thresholds",
|
||||
"fan humidity thresholds must satisfy off < on");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化阈值为默认值
|
||||
*
|
||||
* 将全局阈值结构体重置为预设的默认配置。
|
||||
*/
|
||||
void auto_ctrl_thresholds_init_defaults(void)
|
||||
{
|
||||
const auto_ctrl_thresholds_t defaults = {
|
||||
.light_on_lux_below = DEFAULT_LIGHT_ON_LUX_BELOW,
|
||||
.light_off_lux_above = DEFAULT_LIGHT_OFF_LUX_ABOVE,
|
||||
.hot_on_temp_below_c = DEFAULT_HOT_ON_TEMP_BELOW_C,
|
||||
.hot_off_temp_above_c = DEFAULT_HOT_OFF_TEMP_ABOVE_C,
|
||||
.cool_on_temp_above_c = DEFAULT_COOL_ON_TEMP_ABOVE_C,
|
||||
.cool_off_temp_below_c = DEFAULT_COOL_OFF_TEMP_BELOW_C,
|
||||
.fan_on_humidity_above_pct = DEFAULT_FAN_ON_HUMIDITY_ABOVE_PCT,
|
||||
.fan_off_humidity_below_pct = DEFAULT_FAN_OFF_HUMIDITY_BELOW_PCT,
|
||||
};
|
||||
|
||||
taskENTER_CRITICAL(&s_thresholds_lock);
|
||||
s_thresholds = defaults;
|
||||
taskEXIT_CRITICAL(&s_thresholds_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取当前阈值配置
|
||||
*
|
||||
* 安全地复制当前阈值到输出参数中。
|
||||
*
|
||||
* @param out 输出参数,指向接收阈值的结构体
|
||||
*/
|
||||
void auto_ctrl_thresholds_get(auto_ctrl_thresholds_t *out)
|
||||
{
|
||||
if (out == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
taskENTER_CRITICAL(&s_thresholds_lock);
|
||||
*out = s_thresholds;
|
||||
taskEXIT_CRITICAL(&s_thresholds_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 设置新的阈值配置
|
||||
*
|
||||
* 验证输入配置有效性后,安全更新全局阈值。
|
||||
*
|
||||
* @param cfg 新的阈值配置指针
|
||||
* @return esp_err_t 设置结果,ESP_OK 表示成功
|
||||
*/
|
||||
esp_err_t auto_ctrl_thresholds_set(const auto_ctrl_thresholds_t *cfg)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(auto_ctrl_thresholds_validate(cfg), "auto_ctrl_thresholds", "invalid thresholds");
|
||||
|
||||
taskENTER_CRITICAL(&s_thresholds_lock);
|
||||
s_thresholds = *cfg;
|
||||
taskEXIT_CRITICAL(&s_thresholds_lock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过独立参数设置阈值
|
||||
*
|
||||
* 提供一种更便捷的阈值设置方式,内部封装为结构体后调用 set 接口。
|
||||
*
|
||||
* @param light_on_lux_below 补光灯开启光照阈值(lux)
|
||||
* @param light_off_lux_above 补光灯关闭光照阈值(lux)
|
||||
* @return esp_err_t 设置结果
|
||||
*/
|
||||
esp_err_t auto_ctrl_thresholds_set_values(float light_on_lux_below,
|
||||
float light_off_lux_above,
|
||||
float hot_on_temp_below_c,
|
||||
float hot_off_temp_above_c,
|
||||
float cool_on_temp_above_c,
|
||||
float cool_off_temp_below_c,
|
||||
float fan_on_humidity_above_pct,
|
||||
float fan_off_humidity_below_pct)
|
||||
{
|
||||
const auto_ctrl_thresholds_t cfg = {
|
||||
.light_on_lux_below = light_on_lux_below,
|
||||
.light_off_lux_above = light_off_lux_above,
|
||||
.hot_on_temp_below_c = hot_on_temp_below_c,
|
||||
.hot_off_temp_above_c = hot_off_temp_above_c,
|
||||
.cool_on_temp_above_c = cool_on_temp_above_c,
|
||||
.cool_off_temp_below_c = cool_off_temp_below_c,
|
||||
.fan_on_humidity_above_pct = fan_on_humidity_above_pct,
|
||||
.fan_off_humidity_below_pct = fan_off_humidity_below_pct,
|
||||
};
|
||||
|
||||
return auto_ctrl_thresholds_set(&cfg);
|
||||
}
|
||||
Reference in New Issue
Block a user