dashboard: add temperature high alerts
This commit is contained in:
+10
@@ -963,3 +963,13 @@ The Cargo ESP currently supports 4 temperature sensor slots.
|
|||||||
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
||||||
|
|
||||||
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
||||||
|
|
||||||
|
### Temperature High Alerts
|
||||||
|
|
||||||
|
Each temperature sensor supports optional high-temperature alerting:
|
||||||
|
|
||||||
|
- `high_alert_enabled`
|
||||||
|
- `high_alert_f`
|
||||||
|
- `high_alert`
|
||||||
|
|
||||||
|
When enabled and the live sensor temperature exceeds the configured threshold, the Cargo ESP includes `high_alert: true` for that sensor in `/api/v1/status`. The ESP32-S3 dashboard colors the affected grouped temperature tile red if any sensor in that displayed group is in alert.
|
||||||
|
|||||||
@@ -281,3 +281,13 @@ The Cargo ESP currently supports 4 temperature sensor slots.
|
|||||||
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
||||||
|
|
||||||
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
||||||
|
|
||||||
|
### Temperature High Alerts
|
||||||
|
|
||||||
|
Each temperature sensor supports optional high-temperature alerting:
|
||||||
|
|
||||||
|
- `high_alert_enabled`
|
||||||
|
- `high_alert_f`
|
||||||
|
- `high_alert`
|
||||||
|
|
||||||
|
When enabled and the live sensor temperature exceeds the configured threshold, the Cargo ESP includes `high_alert: true` for that sensor in `/api/v1/status`. The ESP32-S3 dashboard colors the affected grouped temperature tile red if any sensor in that displayed group is in alert.
|
||||||
|
|||||||
@@ -348,3 +348,13 @@ The Cargo ESP currently supports 4 temperature sensor slots.
|
|||||||
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
Temperature sensor `group` values are free-form text in the WebUI. Entering a new group name effectively creates that group. The dashboard overview shows the first two available non-weather groups by priority. Multiple sensors in the same group are combined into one tile, such as `34°/45°`.
|
||||||
|
|
||||||
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
Sensors marked `weather: true` are excluded from the temperature card and shown in the top status strip as `OUT ##°`.
|
||||||
|
|
||||||
|
### Temperature High Alerts
|
||||||
|
|
||||||
|
Each temperature sensor supports optional high-temperature alerting:
|
||||||
|
|
||||||
|
- `high_alert_enabled`
|
||||||
|
- `high_alert_f`
|
||||||
|
- `high_alert`
|
||||||
|
|
||||||
|
When enabled and the live sensor temperature exceeds the configured threshold, the Cargo ESP includes `high_alert: true` for that sensor in `/api/v1/status`. The ESP32-S3 dashboard colors the affected grouped temperature tile red if any sensor in that displayed group is in alert.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static const char *DASHBOARD_VERSION = "0.1.40-temp-two-groups";
|
static const char *DASHBOARD_VERSION = "0.1.41-temp-alerts";
|
||||||
|
|
||||||
// Update these if your Cargo ESP AP credentials are different.
|
// Update these if your Cargo ESP AP credentials are different.
|
||||||
static const char *CARGO_WIFI_SSID = "OverlandController";
|
static const char *CARGO_WIFI_SSID = "OverlandController";
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ static lv_obj_t *battery_charge_pulse_arc = nullptr;
|
|||||||
static lv_obj_t *battery_current_label = nullptr;
|
static lv_obj_t *battery_current_label = nullptr;
|
||||||
static lv_obj_t *battery_estimate_label = nullptr;
|
static lv_obj_t *battery_estimate_label = nullptr;
|
||||||
static lv_obj_t *battery_soc_label = nullptr;
|
static lv_obj_t *battery_soc_label = nullptr;
|
||||||
|
static lv_obj_t *temp_tile_objs[2] = {nullptr};
|
||||||
static lv_obj_t *temp_tile_value_labels[2] = {nullptr};
|
static lv_obj_t *temp_tile_value_labels[2] = {nullptr};
|
||||||
static lv_obj_t *temp_tile_name_labels[2] = {nullptr};
|
static lv_obj_t *temp_tile_name_labels[2] = {nullptr};
|
||||||
|
static bool last_temp_tile_alert[2] = {false, false};
|
||||||
static lv_obj_t *system_status_label = nullptr;
|
static lv_obj_t *system_status_label = nullptr;
|
||||||
static lv_obj_t *wifi_icon_label = nullptr;
|
static lv_obj_t *wifi_icon_label = nullptr;
|
||||||
static lv_obj_t *wifi_bars_obj[4] = {nullptr};
|
static lv_obj_t *wifi_bars_obj[4] = {nullptr};
|
||||||
@@ -597,6 +599,34 @@ static void update_system_status_label()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void update_temp_tile_alert_style(int index, bool alert)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= 2 || temp_tile_objs[index] == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (last_temp_tile_alert[index] == alert) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_temp_tile_alert[index] = alert;
|
||||||
|
|
||||||
|
lvgl_port_lock(-1);
|
||||||
|
|
||||||
|
if (alert) {
|
||||||
|
lv_obj_set_style_bg_color(temp_tile_objs[index], lv_color_hex(0x7A271A), 0);
|
||||||
|
lv_obj_set_style_border_color(temp_tile_objs[index], lv_color_hex(0xF97066), 0);
|
||||||
|
lv_obj_set_style_border_width(temp_tile_objs[index], 3, 0);
|
||||||
|
} else {
|
||||||
|
lv_obj_set_style_bg_color(temp_tile_objs[index], lv_color_hex(0x17202A), 0);
|
||||||
|
lv_obj_set_style_border_color(temp_tile_objs[index], lv_color_hex(0x2F3A46), 0);
|
||||||
|
lv_obj_set_style_border_width(temp_tile_objs[index], 2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
lvgl_port_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
static void update_overview_widgets()
|
static void update_overview_widgets()
|
||||||
{
|
{
|
||||||
String current_text = "Idle";
|
String current_text = "Idle";
|
||||||
@@ -687,6 +717,7 @@ static void parse_status_json(const String &body)
|
|||||||
String group;
|
String group;
|
||||||
int priority;
|
int priority;
|
||||||
int rounded_f;
|
int rounded_f;
|
||||||
|
bool high_alert;
|
||||||
};
|
};
|
||||||
|
|
||||||
TempDisplayItem items[4];
|
TempDisplayItem items[4];
|
||||||
@@ -702,6 +733,7 @@ static void parse_status_json(const String &body)
|
|||||||
}
|
}
|
||||||
|
|
||||||
float temp_f = (float)(temp["temperature_f"] | 0.0);
|
float temp_f = (float)(temp["temperature_f"] | 0.0);
|
||||||
|
bool high_alert = temp["high_alert"] | false;
|
||||||
|
|
||||||
if (weather) {
|
if (weather) {
|
||||||
outside_status = "OUT ";
|
outside_status = "OUT ";
|
||||||
@@ -716,7 +748,6 @@ static void parse_status_json(const String &body)
|
|||||||
String name = raw_name && raw_name[0] ? String(raw_name) : String("cabin");
|
String name = raw_name && raw_name[0] ? String(raw_name) : String("cabin");
|
||||||
String group = normalize_temp_group(String(raw_group), name, false);
|
String group = normalize_temp_group(String(raw_group), name, false);
|
||||||
|
|
||||||
// Outside/weather is shown in the status strip, not the main temp card.
|
|
||||||
if (group == "outside") {
|
if (group == "outside") {
|
||||||
outside_status = "OUT ";
|
outside_status = "OUT ";
|
||||||
outside_status += String((int)round(temp_f));
|
outside_status += String((int)round(temp_f));
|
||||||
@@ -728,7 +759,8 @@ static void parse_status_json(const String &body)
|
|||||||
items[item_count] = {
|
items[item_count] = {
|
||||||
group,
|
group,
|
||||||
temp["priority"] | 99,
|
temp["priority"] | 99,
|
||||||
(int)round(temp_f)
|
(int)round(temp_f),
|
||||||
|
high_alert
|
||||||
};
|
};
|
||||||
item_count++;
|
item_count++;
|
||||||
}
|
}
|
||||||
@@ -749,13 +781,15 @@ static void parse_status_json(const String &body)
|
|||||||
|
|
||||||
String group_names[2] = {"--", "--"};
|
String group_names[2] = {"--", "--"};
|
||||||
String group_values[2] = {"--", "--"};
|
String group_values[2] = {"--", "--"};
|
||||||
|
bool group_alerts[2] = {false, false};
|
||||||
int group_count = 0;
|
int group_count = 0;
|
||||||
|
|
||||||
for (int i = 0; i < item_count; i++) {
|
for (int i = 0; i < item_count; i++) {
|
||||||
int slot = -1;
|
int slot = -1;
|
||||||
|
String display_group = display_temp_group_name(items[i].group);
|
||||||
|
|
||||||
for (int g = 0; g < group_count; g++) {
|
for (int g = 0; g < group_count; g++) {
|
||||||
if (group_names[g] == display_temp_group_name(items[i].group)) {
|
if (group_names[g] == display_group) {
|
||||||
slot = g;
|
slot = g;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -767,7 +801,7 @@ static void parse_status_json(const String &body)
|
|||||||
}
|
}
|
||||||
|
|
||||||
slot = group_count;
|
slot = group_count;
|
||||||
group_names[slot] = display_temp_group_name(items[i].group);
|
group_names[slot] = display_group;
|
||||||
group_values[slot] = "";
|
group_values[slot] = "";
|
||||||
group_count++;
|
group_count++;
|
||||||
}
|
}
|
||||||
@@ -780,6 +814,10 @@ static void parse_status_json(const String &body)
|
|||||||
}
|
}
|
||||||
|
|
||||||
group_values[slot] += value;
|
group_values[slot] += value;
|
||||||
|
|
||||||
|
if (items[i].high_alert) {
|
||||||
|
group_alerts[slot] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_outside_status_temp(outside_status);
|
update_outside_status_temp(outside_status);
|
||||||
@@ -787,6 +825,7 @@ static void parse_status_json(const String &body)
|
|||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
set_label_text_if_changed(temp_tile_value_labels[i], last_temp_tile_value_text[i], group_values[i]);
|
set_label_text_if_changed(temp_tile_value_labels[i], last_temp_tile_value_text[i], group_values[i]);
|
||||||
set_label_text_if_changed(temp_tile_name_labels[i], last_temp_tile_name_text[i], group_names[i]);
|
set_label_text_if_changed(temp_tile_name_labels[i], last_temp_tile_name_text[i], group_names[i]);
|
||||||
|
update_temp_tile_alert_style(i, group_alerts[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1016,6 +1055,7 @@ static void create_overland_overview_screen()
|
|||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
lv_obj_t *tile = lv_obj_create(temp_card);
|
lv_obj_t *tile = lv_obj_create(temp_card);
|
||||||
|
temp_tile_objs[i] = tile;
|
||||||
lv_obj_set_size(tile, temp_tile_w, temp_tile_h);
|
lv_obj_set_size(tile, temp_tile_w, temp_tile_h);
|
||||||
lv_obj_align(tile, LV_ALIGN_TOP_MID, 0, temp_tile_y[i]);
|
lv_obj_align(tile, LV_ALIGN_TOP_MID, 0, temp_tile_y[i]);
|
||||||
lv_obj_set_style_radius(tile, 18, 0);
|
lv_obj_set_style_radius(tile, 18, 0);
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ void loadDefaultConfig() {
|
|||||||
i < appConfig.tempSensorCount,
|
i < appConfig.tempSensorCount,
|
||||||
false,
|
false,
|
||||||
"cabin",
|
"cabin",
|
||||||
i + 1
|
i + 1,
|
||||||
|
false,
|
||||||
|
90.0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +113,14 @@ void loadConfig() {
|
|||||||
(prefix + "priority").c_str(),
|
(prefix + "priority").c_str(),
|
||||||
appConfig.tempSensors[i].priority
|
appConfig.tempSensors[i].priority
|
||||||
);
|
);
|
||||||
|
appConfig.tempSensors[i].highAlertEnabled = preferences.getBool(
|
||||||
|
(prefix + "high_alert_enabled").c_str(),
|
||||||
|
appConfig.tempSensors[i].highAlertEnabled
|
||||||
|
);
|
||||||
|
appConfig.tempSensors[i].highAlertF = preferences.getFloat(
|
||||||
|
(prefix + "high_alert_f").c_str(),
|
||||||
|
appConfig.tempSensors[i].highAlertF
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
appConfig.bms.enabled = preferences.getBool("bms_enabled", appConfig.bms.enabled);
|
appConfig.bms.enabled = preferences.getBool("bms_enabled", appConfig.bms.enabled);
|
||||||
@@ -203,7 +213,11 @@ void printConfig() {
|
|||||||
Serial.print(" / group ");
|
Serial.print(" / group ");
|
||||||
Serial.print(appConfig.tempSensors[i].group);
|
Serial.print(appConfig.tempSensors[i].group);
|
||||||
Serial.print(" / priority ");
|
Serial.print(" / priority ");
|
||||||
Serial.println(appConfig.tempSensors[i].priority);
|
Serial.print(appConfig.tempSensors[i].priority);
|
||||||
|
Serial.print(" / high alert ");
|
||||||
|
Serial.print(appConfig.tempSensors[i].highAlertEnabled ? "on" : "off");
|
||||||
|
Serial.print(" @ ");
|
||||||
|
Serial.println(appConfig.tempSensors[i].highAlertF);
|
||||||
}
|
}
|
||||||
|
|
||||||
Serial.println(" BMS:");
|
Serial.println(" BMS:");
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ struct TempSensorConfig {
|
|||||||
bool weather;
|
bool weather;
|
||||||
String group;
|
String group;
|
||||||
int priority;
|
int priority;
|
||||||
|
bool highAlertEnabled;
|
||||||
|
float highAlertF;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BmsConfig {
|
struct BmsConfig {
|
||||||
|
|||||||
@@ -1196,6 +1196,14 @@ function renderConfigControls(data){
|
|||||||
<label class="inputHelp" for="tempPriority${i}">Priority</label>
|
<label class="inputHelp" for="tempPriority${i}">Priority</label>
|
||||||
<input id="tempPriority${i}" type="number" min="1" max="99" step="1" placeholder="1" oninput="markConfigFieldTouched('tempPriority${i}')">
|
<input id="tempPriority${i}" type="number" min="1" max="99" step="1" placeholder="1" oninput="markConfigFieldTouched('tempPriority${i}')">
|
||||||
|
|
||||||
|
<div class="tempAlertConfig">
|
||||||
|
<label class="tempCheck">
|
||||||
|
<input id="tempHighAlertEnabled${i}" type="checkbox" onchange="markConfigFieldTouched('tempHighAlertEnabled${i}')">
|
||||||
|
High Alert
|
||||||
|
</label>
|
||||||
|
<input id="tempHighAlertF${i}" type="number" min="-40" max="200" step="1" placeholder="90" oninput="markConfigFieldTouched('tempHighAlertF${i}')">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="tempConfigControls">
|
<div class="tempConfigControls">
|
||||||
<label class="tempCheck">
|
<label class="tempCheck">
|
||||||
<input id="tempEnabled${i}" type="checkbox" onchange="markConfigFieldTouched('tempEnabled${i}'); saveTempConfig()">
|
<input id="tempEnabled${i}" type="checkbox" onchange="markConfigFieldTouched('tempEnabled${i}'); saveTempConfig()">
|
||||||
@@ -1234,6 +1242,16 @@ function renderConfigControls(data){
|
|||||||
if(priority && !configTouched["tempPriority"+i] && document.activeElement!==priority){
|
if(priority && !configTouched["tempPriority"+i] && document.activeElement!==priority){
|
||||||
priority.value=t.priority||i+1;
|
priority.value=t.priority||i+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const highAlertEnabled=$("tempHighAlertEnabled"+i);
|
||||||
|
if(highAlertEnabled && !configTouched["tempHighAlertEnabled"+i] && document.activeElement!==highAlertEnabled){
|
||||||
|
highAlertEnabled.checked=!!t.high_alert_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
const highAlertF=$("tempHighAlertF"+i);
|
||||||
|
if(highAlertF && !configTouched["tempHighAlertF"+i] && document.activeElement!==highAlertF){
|
||||||
|
highAlertF.value=t.high_alert_f ?? 90;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1278,6 +1296,8 @@ async function saveTempConfig(){
|
|||||||
const weather=$("tempWeather"+i)?.checked || false;
|
const weather=$("tempWeather"+i)?.checked || false;
|
||||||
const group=$("tempGroup"+i)?.value || temps[i].group || "cabin";
|
const group=$("tempGroup"+i)?.value || temps[i].group || "cabin";
|
||||||
const priority=parseInt($("tempPriority"+i)?.value || temps[i].priority || (i+1),10);
|
const priority=parseInt($("tempPriority"+i)?.value || temps[i].priority || (i+1),10);
|
||||||
|
const highAlertEnabled=$("tempHighAlertEnabled"+i)?.checked || false;
|
||||||
|
const highAlertF=parseFloat($("tempHighAlertF"+i)?.value || temps[i].high_alert_f || 90);
|
||||||
|
|
||||||
await fetch(api("/config/temp"),{
|
await fetch(api("/config/temp"),{
|
||||||
method:"POST",
|
method:"POST",
|
||||||
@@ -1289,7 +1309,9 @@ async function saveTempConfig(){
|
|||||||
enabled:enabled,
|
enabled:enabled,
|
||||||
weather:weather,
|
weather:weather,
|
||||||
group:group,
|
group:group,
|
||||||
priority:priority
|
priority:priority,
|
||||||
|
high_alert_enabled:highAlertEnabled,
|
||||||
|
high_alert_f:highAlertF
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1299,7 +1321,7 @@ async function saveTempConfig(){
|
|||||||
alert("Temperature config saved");
|
alert("Temperature config saved");
|
||||||
clearConfigTouched([
|
clearConfigTouched([
|
||||||
"tempEnabledCount",
|
"tempEnabledCount",
|
||||||
...temps.flatMap((_,i)=>["tempName"+i,"tempEnabled"+i,"tempWeather"+i,"tempGroup"+i,"tempPriority"+i])
|
...temps.flatMap((_,i)=>["tempName"+i,"tempEnabled"+i,"tempWeather"+i,"tempGroup"+i,"tempPriority"+i,"tempHighAlertEnabled"+i,"tempHighAlertF"+i])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2029,6 +2051,8 @@ void buildConfigDocument(JsonObject doc) {
|
|||||||
temp["weather"] = appConfig.tempSensors[i].weather;
|
temp["weather"] = appConfig.tempSensors[i].weather;
|
||||||
temp["group"] = appConfig.tempSensors[i].group;
|
temp["group"] = appConfig.tempSensors[i].group;
|
||||||
temp["priority"] = appConfig.tempSensors[i].priority;
|
temp["priority"] = appConfig.tempSensors[i].priority;
|
||||||
|
temp["high_alert_enabled"] = appConfig.tempSensors[i].highAlertEnabled;
|
||||||
|
temp["high_alert_f"] = appConfig.tempSensors[i].highAlertF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2224,6 +2248,8 @@ void applyImportedConfig(JsonObject doc) {
|
|||||||
if (temp["weather"].is<bool>()) appConfig.tempSensors[index].weather = temp["weather"].as<bool>();
|
if (temp["weather"].is<bool>()) appConfig.tempSensors[index].weather = temp["weather"].as<bool>();
|
||||||
if (temp["group"].is<String>()) appConfig.tempSensors[index].group = temp["group"].as<String>();
|
if (temp["group"].is<String>()) appConfig.tempSensors[index].group = temp["group"].as<String>();
|
||||||
if (temp["priority"].is<int>()) appConfig.tempSensors[index].priority = temp["priority"].as<int>();
|
if (temp["priority"].is<int>()) appConfig.tempSensors[index].priority = temp["priority"].as<int>();
|
||||||
|
if (temp["high_alert_enabled"].is<bool>()) appConfig.tempSensors[index].highAlertEnabled = temp["high_alert_enabled"].as<bool>();
|
||||||
|
if (temp["high_alert_f"].is<float>()) appConfig.tempSensors[index].highAlertF = temp["high_alert_f"].as<float>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2331,9 +2357,15 @@ void buildStatusDocument(JsonDocument& doc) {
|
|||||||
temp["weather"] = appConfig.tempSensors[i].weather;
|
temp["weather"] = appConfig.tempSensors[i].weather;
|
||||||
temp["group"] = appConfig.tempSensors[i].group;
|
temp["group"] = appConfig.tempSensors[i].group;
|
||||||
temp["priority"] = appConfig.tempSensors[i].priority;
|
temp["priority"] = appConfig.tempSensors[i].priority;
|
||||||
|
temp["high_alert_enabled"] = appConfig.tempSensors[i].highAlertEnabled;
|
||||||
|
temp["high_alert_f"] = appConfig.tempSensors[i].highAlertF;
|
||||||
temp["online"] = sensors.online[i];
|
temp["online"] = sensors.online[i];
|
||||||
if (sensors.online[i]) {
|
if (sensors.online[i]) {
|
||||||
temp["temperature_f"] = sensors.tempsF[i];
|
temp["temperature_f"] = sensors.tempsF[i];
|
||||||
|
temp["high_alert"] =
|
||||||
|
appConfig.tempSensors[i].highAlertEnabled &&
|
||||||
|
sensors.tempOnline[i] &&
|
||||||
|
sensors.tempsF[i] > appConfig.tempSensors[i].highAlertF;
|
||||||
} else {
|
} else {
|
||||||
temp["temperature_f"] = nullptr;
|
temp["temperature_f"] = nullptr;
|
||||||
}
|
}
|
||||||
@@ -2477,6 +2509,8 @@ void sendConfigResponse(Stream& output, bool ok = true) {
|
|||||||
temp["weather"] = appConfig.tempSensors[i].weather;
|
temp["weather"] = appConfig.tempSensors[i].weather;
|
||||||
temp["group"] = appConfig.tempSensors[i].group;
|
temp["group"] = appConfig.tempSensors[i].group;
|
||||||
temp["priority"] = appConfig.tempSensors[i].priority;
|
temp["priority"] = appConfig.tempSensors[i].priority;
|
||||||
|
temp["high_alert_enabled"] = appConfig.tempSensors[i].highAlertEnabled;
|
||||||
|
temp["high_alert_f"] = appConfig.tempSensors[i].highAlertF;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializeJson(doc, output);
|
serializeJson(doc, output);
|
||||||
@@ -3460,6 +3494,8 @@ void handleUpdateTempSensorConfig() {
|
|||||||
if (doc["weather"].is<bool>()) appConfig.tempSensors[index].weather = doc["weather"].as<bool>();
|
if (doc["weather"].is<bool>()) appConfig.tempSensors[index].weather = doc["weather"].as<bool>();
|
||||||
if (doc["group"].is<String>()) appConfig.tempSensors[index].group = doc["group"].as<String>();
|
if (doc["group"].is<String>()) appConfig.tempSensors[index].group = doc["group"].as<String>();
|
||||||
if (doc["priority"].is<int>()) appConfig.tempSensors[index].priority = doc["priority"].as<int>();
|
if (doc["priority"].is<int>()) appConfig.tempSensors[index].priority = doc["priority"].as<int>();
|
||||||
|
if (doc["high_alert_enabled"].is<bool>()) appConfig.tempSensors[index].highAlertEnabled = doc["high_alert_enabled"].as<bool>();
|
||||||
|
if (doc["high_alert_f"].is<float>()) appConfig.tempSensors[index].highAlertF = doc["high_alert_f"].as<float>();
|
||||||
|
|
||||||
sendOkConfig();
|
sendOkConfig();
|
||||||
}
|
}
|
||||||
@@ -3602,6 +3638,8 @@ void handleTempClear() {
|
|||||||
appConfig.tempSensors[i].weather = false;
|
appConfig.tempSensors[i].weather = false;
|
||||||
appConfig.tempSensors[i].group = "cabin";
|
appConfig.tempSensors[i].group = "cabin";
|
||||||
appConfig.tempSensors[i].priority = i + 1;
|
appConfig.tempSensors[i].priority = i + 1;
|
||||||
|
appConfig.tempSensors[i].highAlertEnabled = false;
|
||||||
|
appConfig.tempSensors[i].highAlertF = 90.0;
|
||||||
sensors.tempsF[i] = -127.0;
|
sensors.tempsF[i] = -127.0;
|
||||||
sensors.online[i] = false;
|
sensors.online[i] = false;
|
||||||
}
|
}
|
||||||
@@ -3640,6 +3678,8 @@ void handleTempClear() {
|
|||||||
appConfig.tempSensors[configIndex].weather = false;
|
appConfig.tempSensors[configIndex].weather = false;
|
||||||
appConfig.tempSensors[configIndex].group = "cabin";
|
appConfig.tempSensors[configIndex].group = "cabin";
|
||||||
appConfig.tempSensors[configIndex].priority = configIndex + 1;
|
appConfig.tempSensors[configIndex].priority = configIndex + 1;
|
||||||
|
appConfig.tempSensors[configIndex].highAlertEnabled = false;
|
||||||
|
appConfig.tempSensors[configIndex].highAlertF = 90.0;
|
||||||
sensors.tempsF[configIndex] = -127.0;
|
sensors.tempsF[configIndex] = -127.0;
|
||||||
sensors.online[configIndex] = false;
|
sensors.online[configIndex] = false;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user