diff --git a/CHANGELOG_LATEST.md b/CHANGELOG_LATEST.md
index bd71d324d..2a610339d 100644
--- a/CHANGELOG_LATEST.md
+++ b/CHANGELOG_LATEST.md
@@ -35,6 +35,8 @@
- Read time from IVT-controller [#439](https://github.com/emsesp/EMS-ESP32/issues/439)
- Hybrid Heatpump product-id 168 [#459](https://github.com/emsesp/EMS-ESP32/issues/459), thermostat settings
- Junkers ISM2 and IPM in warm water mode [#437](https://github.com/emsesp/EMS-ESP32/issues/437)
+- Added Shower Alert trigger time and cold shot time [#436](https://github.com/emsesp/EMS-ESP32/issues/436)
+- Improved Table layout in Web UI (searching, filtering, sorting, exporting to CSV)
### Fixed
@@ -53,6 +55,7 @@
- Burner selected max power can have a value higher than 100% [#314](https://github.com/emsesp/EMS-ESP32/issues/314)
- some missing fahrenheit calculations
- limited number of exclusions [#339](https://github.com/emsesp/EMS-ESP32/issues/339)
+- MQTT sometimes would not reconnect after a WiFi outage
### Changed
@@ -63,7 +66,7 @@
- Show Sensors quality in WebUI
- Controller not shown in WebUI dashboard
- renamed "Home Assistant Integration" to "MQTT Discovery" in MQTT Settings [#290](https://github.com/emsesp/EMS-ESP32/issues/290)
-- Show ems tx reads and writes separatly
+- Show ems tx reads and writes separately
- Show ems device handlers separated for received, fetched and pending handlers.
- Wired renamed to Ethernet
- removed system/pin command, new commands in analogsensors
diff --git a/interface/src/project/SettingsApplication.tsx b/interface/src/project/SettingsApplication.tsx
index 0ea86722b..353f1faf0 100644
--- a/interface/src/project/SettingsApplication.tsx
+++ b/interface/src/project/SettingsApplication.tsx
@@ -343,11 +343,6 @@ const SettingsApplication: FC = () => {
label="Convert temperature values to Fahrenheit"
disabled={saving}
/>
- }
- label="Underclock CPU speed"
- disabled={saving}
- />
}
label="Bypass Access Token authorization on API calls"
@@ -358,6 +353,11 @@ const SettingsApplication: FC = () => {
label="Enable Read only mode (blocks all outgoing EMS Tx write commands)"
disabled={saving}
/>
+ }
+ label="Underclock CPU speed"
+ disabled={saving}
+ />
}
@@ -367,8 +367,36 @@ const SettingsApplication: FC = () => {
}
label="Enable Shower Alert"
- disabled={saving}
+ disabled={!data.shower_timer}
/>
+ {data.shower_alert && (
+ <>
+
+
+
+
+
+
+ >
+ )}
Formatting Options
diff --git a/interface/src/project/types.ts b/interface/src/project/types.ts
index c78745e55..0d4d048b6 100644
--- a/interface/src/project/types.ts
+++ b/interface/src/project/types.ts
@@ -9,6 +9,8 @@ export interface Settings {
master_thermostat: number;
shower_timer: boolean;
shower_alert: boolean;
+ shower_alert_coldshot: number;
+ shower_alert_trigger: number;
rx_gpio: number;
tx_gpio: number;
telnet_enabled: boolean;
@@ -41,8 +43,8 @@ export enum busConnectionStatus {
export interface Stat {
id: string; // name
s: number; // success
- f: number; // fail
- q: number; // quality
+ f: number; // fail
+ q: number; // quality
}
export interface Status {
status: busConnectionStatus;
diff --git a/interface/src/project/validators.ts b/interface/src/project/validators.ts
index 88742d3e4..a626489d2 100644
--- a/interface/src/project/validators.ts
+++ b/interface/src/project/validators.ts
@@ -40,5 +40,9 @@ export const createSettingsValidator = (settings: Settings) =>
{ required: true, message: 'Mark interval is required' },
{ type: 'number', min: 0, max: 10, message: 'Port must be between 0 and 10' }
]
+ }),
+ ...(settings.shower_alert && {
+ shower_alert_trigger: [{ type: 'number', min: 1, max: 20, message: 'Time must be between 1 and 20 minutes' }],
+ shower_alert_coldshot: [{ type: 'number', min: 1, max: 10, message: 'Time must be between 1 and 10 seconds' }]
})
});
diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h
index 600a1c74a..4b31d671c 100644
--- a/lib_standalone/ESP8266React.h
+++ b/lib_standalone/ESP8266React.h
@@ -19,39 +19,41 @@
class DummySettings {
public:
- uint8_t tx_mode = 1;
- uint8_t ems_bus_id = 0x0B;
- bool syslog_enabled = false;
- int8_t syslog_level = 3; // uuid::log::Level
- uint32_t syslog_mark_interval = 0;
- String syslog_host = "192.168.1.4";
- uint16_t syslog_port = 514;
- uint8_t master_thermostat = 0;
- bool shower_timer = true;
- bool shower_alert = false;
- bool hide_led = false;
- bool notoken_api = false;
- bool readonly_mode = false;
- uint8_t bool_format = 1; // using "on" and "off"
- uint8_t enum_format = 1;
- bool nosleep = false;
- bool fahrenheit = false;
- bool bandwidth20 = false;
- bool telnet_enabled = false;
- String board_profile = "CUSTOM";
- bool trace_raw = false;
- bool analog_enabled = true; // analog is enabled
- int8_t weblog_level = 1;
- uint8_t weblog_buffer = 50;
- bool weblog_compact = true;
- uint8_t rx_gpio = 0;
- uint8_t tx_gpio = 0;
- uint8_t dallas_gpio = 16; // to ensure its enabled
- bool dallas_parasite = false;
- uint8_t led_gpio = 0;
- bool low_clock = false;
- uint8_t pbutton_gpio = false;
- uint8_t solar_maxflow = 30;
+ uint8_t tx_mode = 1;
+ uint8_t ems_bus_id = 0x0B;
+ bool syslog_enabled = false;
+ int8_t syslog_level = 3; // uuid::log::Level
+ uint32_t syslog_mark_interval = 0;
+ String syslog_host = "192.168.1.4";
+ uint16_t syslog_port = 514;
+ uint8_t master_thermostat = 0;
+ bool shower_timer = true;
+ bool shower_alert = false;
+ uint8_t shower_alert_coldshot = 10;
+ uint8_t shower_alert_trigger = 7;
+ bool hide_led = false;
+ bool notoken_api = false;
+ bool readonly_mode = false;
+ uint8_t bool_format = 1; // using "on" and "off"
+ uint8_t enum_format = 1;
+ bool nosleep = false;
+ bool fahrenheit = false;
+ bool bandwidth20 = false;
+ bool telnet_enabled = false;
+ String board_profile = "CUSTOM";
+ bool trace_raw = false;
+ bool analog_enabled = true; // analog is enabled
+ int8_t weblog_level = 1;
+ uint8_t weblog_buffer = 50;
+ bool weblog_compact = true;
+ uint8_t rx_gpio = 0;
+ uint8_t tx_gpio = 0;
+ uint8_t dallas_gpio = 16; // to ensure its enabled
+ bool dallas_parasite = false;
+ uint8_t led_gpio = 0;
+ bool low_clock = false;
+ uint8_t pbutton_gpio = false;
+ uint8_t solar_maxflow = 30;
// MQTT
uint16_t publish_time = 10;
diff --git a/mock-api/server.js b/mock-api/server.js
index 898d644e0..9f3666962 100644
--- a/mock-api/server.js
+++ b/mock-api/server.js
@@ -316,7 +316,9 @@ settings = {
syslog_port: 514,
master_thermostat: 0,
shower_timer: true,
- shower_alert: false,
+ shower_alert: true,
+ shower_alert_trigger: 7,
+ shower_alert_coldshot: 10,
rx_gpio: 23,
tx_gpio: 5,
phy_type: 0,
diff --git a/src/default_settings.h b/src/default_settings.h
index b70fef920..134ff4dc8 100644
--- a/src/default_settings.h
+++ b/src/default_settings.h
@@ -64,6 +64,14 @@
#define EMSESP_DEFAULT_SHOWER_ALERT false
#endif
+#ifndef EMSESP_DEFAULT_SHOWER_ALERT_TRIGGER
+#define EMSESP_DEFAULT_SHOWER_ALERT_TRIGGER 7
+#endif
+
+#ifndef EMSESP_DEFAULT_SHOWER_ALERT_COLDSHOT
+#define EMSESP_DEFAULT_SHOWER_ALERT_COLDSHOT 10
+#endif
+
#ifndef EMSESP_DEFAULT_HIDE_LED
#define EMSESP_DEFAULT_HIDE_LED false
#endif
diff --git a/src/shower.cpp b/src/shower.cpp
index f9c8a2e8e..8f024dfa4 100644
--- a/src/shower.cpp
+++ b/src/shower.cpp
@@ -24,8 +24,10 @@ uuid::log::Logger Shower::logger_{F_(shower), uuid::log::Facility::CONSOLE};
void Shower::start() {
EMSESP::webSettingsService.read([&](WebSettings & settings) {
- shower_timer_ = settings.shower_timer;
- shower_alert_ = settings.shower_alert;
+ shower_timer_ = settings.shower_timer;
+ shower_alert_ = settings.shower_alert;
+ shower_alert_trigger_ = settings.shower_alert_trigger * 60000; // convert from minutes
+ shower_alert_coldshot_ = settings.shower_alert_coldshot * 1000; // convert from seconds
});
set_shower_state(false, true); // turns shower to off and creates HA topic if not already done
@@ -59,7 +61,7 @@ void Shower::loop() {
LOG_DEBUG(F("[Shower] hot water still running, starting shower timer"));
}
// check if the shower has been on too long
- else if ((time_now - timer_start_) > SHOWER_MAX_DURATION) {
+ else if ((time_now - timer_start_) > shower_alert_trigger_) {
shower_alert_start();
}
}
@@ -95,7 +97,7 @@ void Shower::loop() {
// at this point we're in the shower cold shot (doing_cold_shot_ == true)
// keep repeating until the time is up
- if ((time_now - alert_timer_start_) > SHOWER_COLDSHOT_DURATION) {
+ if ((time_now - alert_timer_start_) > shower_alert_coldshot_) {
shower_alert_stop();
}
}
diff --git a/src/shower.h b/src/shower.h
index dc9dafda4..809a18031 100644
--- a/src/shower.h
+++ b/src/shower.h
@@ -49,11 +49,9 @@ class Shower {
private:
static uuid::log::Logger logger_;
- static constexpr uint32_t SHOWER_PAUSE_TIME = 15000; // in ms. 15 seconds, max time if water is switched off & on during a shower
- static constexpr uint32_t SHOWER_MIN_DURATION = 120000; // in ms. 2 minutes, before recognizing its a shower
- static constexpr uint32_t SHOWER_OFFSET_TIME = 5000; // in ms. 5 seconds grace time, to calibrate actual time under the shower
- static constexpr uint32_t SHOWER_COLDSHOT_DURATION = 10000; // 10 seconds for cold water before turning back hot water
- static constexpr uint32_t SHOWER_MAX_DURATION = 420000; // in ms. 7 minutes, before trigger a shot of cold water
+ static constexpr uint32_t SHOWER_PAUSE_TIME = 15000; // in ms. 15 seconds, max time if water is switched off & on during a shower
+ static constexpr uint32_t SHOWER_MIN_DURATION = 120000; // in ms. 2 minutes, before recognizing its a shower
+ static constexpr uint32_t SHOWER_OFFSET_TIME = 5000; // in ms. 5 seconds grace time, to calibrate actual time under the shower
void publish_shower_data() const;
void shower_alert_start();
@@ -61,6 +59,8 @@ class Shower {
bool shower_timer_; // true if we want to report back on shower times
bool shower_alert_; // true if we want the alert of cold water
+ uint32_t shower_alert_trigger_; // default 7 minutes, before trigger a shot of cold water
+ uint32_t shower_alert_coldshot_; // default 10 seconds for cold water before turning back hot water
bool ha_configdone_ = false; // for HA MQTT Discovery
bool shower_state_;
uint32_t timer_start_; // ms
diff --git a/src/system.cpp b/src/system.cpp
index 4eaa88ec0..8c3620941 100644
--- a/src/system.cpp
+++ b/src/system.cpp
@@ -998,6 +998,10 @@ bool System::command_settings(const char * value, const int8_t id, JsonObject &
node["shower_timer"] = settings.shower_timer;
node["shower_alert"] = settings.shower_alert;
+ if (settings.shower_alert) {
+ node["shower_alert_coldshot"] = settings.shower_alert_coldshot / 1000; // seconds
+ node["shower_alert_trigger"] = settings.shower_alert_trigger / 60000; // minutes
+ }
node["rx_gpio"] = settings.rx_gpio;
node["tx_gpio"] = settings.tx_gpio;
diff --git a/src/version.h b/src/version.h
index 4b88090e3..60abd800d 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1 +1 @@
-#define EMSESP_APP_VERSION "3.4.0b14"
+#define EMSESP_APP_VERSION "3.4.0b15"
diff --git a/src/web/WebDataService.cpp b/src/web/WebDataService.cpp
index 0d9347ce5..c32bed325 100644
--- a/src/web/WebDataService.cpp
+++ b/src/web/WebDataService.cpp
@@ -137,8 +137,9 @@ void WebDataService::sensor_data(AsyncWebServerRequest * request) {
for (const auto & sensor : EMSESP::analogsensor_.sensors()) {
// don't send if it's marked for removal
if (sensor.type() != AnalogSensor::AnalogType::MARK_DELETED) {
+ count++;
JsonObject obj = analogs.createNestedObject();
- obj["id"] = Helpers::smallitoa(buffer, ++count); // needed for sorting table
+ obj["id"] = Helpers::smallitoa(buffer, count); // needed for sorting table
obj["g"] = sensor.gpio();
obj["n"] = sensor.name();
obj["u"] = sensor.uom();
diff --git a/src/web/WebSettingsService.cpp b/src/web/WebSettingsService.cpp
index a5d9ef98d..dca3ab72f 100644
--- a/src/web/WebSettingsService.cpp
+++ b/src/web/WebSettingsService.cpp
@@ -37,41 +37,43 @@ WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, Securit
}
void WebSettings::read(WebSettings & settings, JsonObject & root) {
- root["tx_mode"] = settings.tx_mode;
- root["ems_bus_id"] = settings.ems_bus_id;
- root["syslog_enabled"] = settings.syslog_enabled;
- root["syslog_level"] = settings.syslog_level;
- root["trace_raw"] = settings.trace_raw;
- root["syslog_mark_interval"] = settings.syslog_mark_interval;
- root["syslog_host"] = settings.syslog_host;
- root["syslog_port"] = settings.syslog_port;
- root["master_thermostat"] = settings.master_thermostat;
- root["shower_timer"] = settings.shower_timer;
- root["shower_alert"] = settings.shower_alert;
- root["rx_gpio"] = settings.rx_gpio;
- root["tx_gpio"] = settings.tx_gpio;
- root["dallas_gpio"] = settings.dallas_gpio;
- root["dallas_parasite"] = settings.dallas_parasite;
- root["led_gpio"] = settings.led_gpio;
- root["hide_led"] = settings.hide_led;
- root["low_clock"] = settings.low_clock;
- root["telnet_enabled"] = settings.telnet_enabled;
- root["notoken_api"] = settings.notoken_api;
- root["readonly_mode"] = settings.readonly_mode;
- root["analog_enabled"] = settings.analog_enabled;
- root["pbutton_gpio"] = settings.pbutton_gpio;
- root["solar_maxflow"] = settings.solar_maxflow;
- root["board_profile"] = settings.board_profile;
- root["fahrenheit"] = settings.fahrenheit;
- root["bool_format"] = settings.bool_format;
- root["enum_format"] = settings.enum_format;
- root["weblog_level"] = settings.weblog_level;
- root["weblog_buffer"] = settings.weblog_buffer;
- root["weblog_compact"] = settings.weblog_compact;
- root["phy_type"] = settings.phy_type;
- root["eth_power"] = settings.eth_power;
- root["eth_phy_addr"] = settings.eth_phy_addr;
- root["eth_clock_mode"] = settings.eth_clock_mode;
+ root["tx_mode"] = settings.tx_mode;
+ root["ems_bus_id"] = settings.ems_bus_id;
+ root["syslog_enabled"] = settings.syslog_enabled;
+ root["syslog_level"] = settings.syslog_level;
+ root["trace_raw"] = settings.trace_raw;
+ root["syslog_mark_interval"] = settings.syslog_mark_interval;
+ root["syslog_host"] = settings.syslog_host;
+ root["syslog_port"] = settings.syslog_port;
+ root["master_thermostat"] = settings.master_thermostat;
+ root["shower_timer"] = settings.shower_timer;
+ root["shower_alert"] = settings.shower_alert;
+ root["shower_alert_coldshot"] = settings.shower_alert_coldshot;
+ root["shower_alert_trigger"] = settings.shower_alert_trigger;
+ root["rx_gpio"] = settings.rx_gpio;
+ root["tx_gpio"] = settings.tx_gpio;
+ root["dallas_gpio"] = settings.dallas_gpio;
+ root["dallas_parasite"] = settings.dallas_parasite;
+ root["led_gpio"] = settings.led_gpio;
+ root["hide_led"] = settings.hide_led;
+ root["low_clock"] = settings.low_clock;
+ root["telnet_enabled"] = settings.telnet_enabled;
+ root["notoken_api"] = settings.notoken_api;
+ root["readonly_mode"] = settings.readonly_mode;
+ root["analog_enabled"] = settings.analog_enabled;
+ root["pbutton_gpio"] = settings.pbutton_gpio;
+ root["solar_maxflow"] = settings.solar_maxflow;
+ root["board_profile"] = settings.board_profile;
+ root["fahrenheit"] = settings.fahrenheit;
+ root["bool_format"] = settings.bool_format;
+ root["enum_format"] = settings.enum_format;
+ root["weblog_level"] = settings.weblog_level;
+ root["weblog_buffer"] = settings.weblog_buffer;
+ root["weblog_compact"] = settings.weblog_compact;
+ root["phy_type"] = settings.phy_type;
+ root["eth_power"] = settings.eth_power;
+ root["eth_phy_addr"] = settings.eth_phy_addr;
+ root["eth_clock_mode"] = settings.eth_clock_mode;
}
// call on initialization and also when settings are updated via web or console
@@ -152,6 +154,12 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
prev = settings.shower_alert;
settings.shower_alert = root["shower_alert"] | EMSESP_DEFAULT_SHOWER_ALERT;
check_flag(prev, settings.shower_alert, ChangeFlags::SHOWER);
+ prev = settings.shower_alert_trigger;
+ settings.shower_alert_trigger = root["shower_alert_trigger"] | EMSESP_DEFAULT_SHOWER_ALERT_TRIGGER;
+ check_flag(prev, settings.shower_alert_trigger, ChangeFlags::SHOWER);
+ prev = settings.shower_alert_coldshot;
+ settings.shower_alert_coldshot = root["shower_alert_coldshot"] | EMSESP_DEFAULT_SHOWER_ALERT_COLDSHOT;
+ check_flag(prev, settings.shower_alert_coldshot, ChangeFlags::SHOWER);
// led
prev = settings.led_gpio;
diff --git a/src/web/WebSettingsService.h b/src/web/WebSettingsService.h
index 5ff6ef1c9..16bf3aa60 100644
--- a/src/web/WebSettingsService.h
+++ b/src/web/WebSettingsService.h
@@ -34,6 +34,8 @@ class WebSettings {
uint8_t master_thermostat;
bool shower_timer;
bool shower_alert;
+ uint8_t shower_alert_trigger;
+ uint8_t shower_alert_coldshot;
bool syslog_enabled;
int8_t syslog_level; // uuid::log::Level
uint32_t syslog_mark_interval;