From 0ca948ce03062c1fba1b2427cf06d19a5c6b7326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olaf=20L=C3=BCke?= Date: Mon, 30 Sep 2024 23:44:40 +0200 Subject: [PATCH] heating, web/heating: Remove winter mode --- software/src/modules/heating/heating.cpp | 59 +++-- software/web/src/modules/heating/api.ts | 14 +- software/web/src/modules/heating/main.tsx | 213 +++++------------- .../src/modules/heating/translation_de.tsx | 14 +- .../src/modules/heating/translation_en.tsx | 2 +- 5 files changed, 102 insertions(+), 200 deletions(-) diff --git a/software/src/modules/heating/heating.cpp b/software/src/modules/heating/heating.cpp index 8d018e4fc..4e600be20 100644 --- a/software/src/modules/heating/heating.cpp +++ b/software/src/modules/heating/heating.cpp @@ -40,13 +40,13 @@ void Heating::pre_setup() {"minimum_control_holding_time", Config::Uint(15, 0, 60)}, {"meter_slot_grid_power", Config::Uint(POWER_MANAGER_DEFAULT_METER_SLOT, 0, METERS_SLOTS - 1)}, {"extended_logging_active", Config::Bool(false)}, - {"winter_start_day", Config::Uint(1, 1, 31)}, - {"winter_start_month", Config::Uint(11, 1, 12)}, - {"winter_end_day", Config::Uint(15, 1, 31)}, - {"winter_end_month", Config::Uint(3, 1, 12)}, - {"summer_block_time_active", Config::Bool(false)}, - {"summer_block_time_morning", Config::Int(8*60)}, // localtime in minutes since 00:00 - {"summer_block_time_evening", Config::Int(20*60)}, // localtime in minutes since 00:00 + {"summer_start_day", Config::Uint(15, 1, 31)}, + {"summer_start_month", Config::Uint(3, 1, 12)}, + {"summer_end_day", Config::Uint(1, 1, 31)}, + {"summer_end_month", Config::Uint(11, 1, 12)}, + {"summer_active_time_active", Config::Bool(false)}, + {"summer_active_time_start", Config::Int(8*60)}, // localtime in minutes since 00:00 + {"summer_active_time_end", Config::Int(20*60)}, // localtime in minutes since 00:00 {"summer_yield_forecast_active", Config::Bool(false)}, {"summer_yield_forecast_threshold", Config::Uint(0)}, {"dpc_extended_active", Config::Bool(false)}, @@ -55,7 +55,6 @@ void Heating::pre_setup() {"dpc_blocking_threshold", Config::Uint(120, 100, 1000)}, {"pv_excess_control_active", Config::Bool(false)}, {"pv_excess_control_threshold", Config::Uint(0)}, - {"pv_excess_control_holding_time", Config::Uint(15, 0, 12*60)}, {"p14enwg_active", Config::Bool(false)}, {"p14enwg_input", Config::Uint(0, 0, 3)}, {"p14enwg_active_type", Config::Uint(0, 0, 1)} @@ -94,10 +93,10 @@ bool Heating::is_active() { const bool dpc_extended_active = config.get("dpc_extended_active")->asBool(); const bool pv_excess_control_active = config.get("pv_excess_control_active")->asBool(); - const bool summer_block_time_active = config.get("summer_block_time_active")->asBool(); + const bool summer_active_time_active = config.get("summer_active_time_active")->asBool(); const bool summer_yield_forecast_active = config.get("summer_yield_forecast_active")->asBool(); - if(!summer_block_time_active && !summer_yield_forecast_active && !dpc_extended_active && !pv_excess_control_active) { + if(!summer_active_time_active && !summer_yield_forecast_active && !dpc_extended_active && !pv_excess_control_active) { return false; } @@ -159,13 +158,13 @@ void Heating::update() } const uint32_t meter_slot_grid_power = config.get("meter_slot_grid_power")->asUint(); - const uint32_t winter_start_day = config.get("winter_start_day")->asUint(); - const uint32_t winter_start_month = config.get("winter_start_month")->asUint(); - const uint32_t winter_end_day = config.get("winter_end_day")->asUint(); - const uint32_t winter_end_month = config.get("winter_end_month")->asUint(); - const bool summer_block_time_active = config.get("summer_block_time_active")->asBool(); - const int32_t summer_block_time_morning = config.get("summer_block_time_morning")->asInt(); - const int32_t summer_block_time_evening = config.get("summer_block_time_evening")->asInt(); + const uint32_t summer_start_day = config.get("summer_start_day")->asUint(); + const uint32_t summer_start_month = config.get("summer_start_month")->asUint(); + const uint32_t summer_end_day = config.get("summer_end_day")->asUint(); + const uint32_t summer_end_month = config.get("summer_end_month")->asUint(); + const bool summer_active_time_active = config.get("summer_active_time_active")->asBool(); + const int32_t summer_active_time_start = config.get("summer_active_time_start")->asInt(); + const int32_t summer_active_time_end = config.get("summer_active_time_end")->asInt(); const bool summer_yield_forecast_active = config.get("summer_yield_forecast_active")->asBool(); const uint32_t summer_yield_forecast_threshold = config.get("summer_yield_forecast_threshold")->asUint(); const bool dpc_extended_active = config.get("dpc_extended_active")->asBool(); @@ -173,7 +172,7 @@ void Heating::update() const bool pv_excess_control_active = config.get("pv_excess_control_active")->asBool(); const uint32_t pv_excess_control_threshold = config.get("pv_excess_control_threshold")->asUint(); - if(!summer_block_time_active && !summer_yield_forecast_active && !dpc_extended_active && !pv_excess_control_active) { + if(!summer_active_time_active && !summer_yield_forecast_active && !dpc_extended_active && !pv_excess_control_active) { extended_logging("No control active."); return; } @@ -184,9 +183,9 @@ void Heating::update() const int current_day = current_time->tm_mday; const int current_minutes = current_time->tm_hour * 60 + current_time->tm_min; - const bool is_winter = ((current_month == winter_start_month) && (current_day >= winter_start_day )) || - ((current_month == winter_end_month ) && (current_day <= winter_end_day )) || - ((current_month > winter_start_month ) && (current_month < winter_end_month)); + const bool is_summer = ((current_month == summer_start_month) && (current_day >= summer_start_day )) || + ((current_month == summer_end_month ) && (current_day <= summer_end_day )) || + ((current_month > summer_start_month ) && (current_month < summer_end_month)); bool sg_ready_on = false; @@ -222,8 +221,8 @@ void Heating::update() } }; - if (is_winter) { // Winter - extended_logging("It is winter. Current month: %d, winter start month: %d, winter end month: %d, current day: %d, winter start day: %d, winter end day: %d.", current_month, winter_start_month, winter_end_month, current_day, winter_start_day, winter_end_day); + if (!is_summer) { // Winter + extended_logging("It is winter. Current month: %d, winter start month: %d, winter end month: %d, current day: %d, winter start day: %d, winter end day: %d.", current_month, summer_start_month, summer_end_month, current_day, summer_start_day, summer_end_day); if (!dpc_extended_active && !pv_excess_control_active) { extended_logging("It is winter but no winter control active."); } else { @@ -236,21 +235,21 @@ void Heating::update() } } } else { // Summer - extended_logging("It is summer. Current month: %d, winter start month: %d, winter end month: %d, current day: %d, winter start day: %d, winter end day: %d.", current_month, winter_start_month, winter_end_month, current_day, winter_start_day, winter_end_day); + extended_logging("It is summer. Current month: %d, winter start month: %d, winter end month: %d, current day: %d, winter start day: %d, winter end day: %d.", current_month, summer_start_month, summer_end_month, current_day, summer_start_day, summer_end_day); bool blocked = false; bool is_morning = false; bool is_evening = false; - if (summer_block_time_active) { - if (current_minutes <= summer_block_time_morning) { // if is between 00:00 and summer_block_time_morning - extended_logging("We are in morning block time. Current time: %d, block time morning: %d.", current_minutes, summer_block_time_morning); + if (summer_active_time_active) { + if (current_minutes <= summer_active_time_start) { // if is between 00:00 and summer_active_time_start + extended_logging("We are in morning block time. Current time: %d, block time morning: %d.", current_minutes, summer_active_time_start); blocked = true; is_morning = true; - } else if(summer_block_time_evening <= current_minutes) { // if is between summer_block_time_evening and 23:59 - extended_logging("We are in evening block time. Current time: %d, block time evening: %d.", current_minutes, summer_block_time_evening); + } else if(summer_active_time_end <= current_minutes) { // if is between summer_active_time_end and 23:59 + extended_logging("We are in evening block time. Current time: %d, block time evening: %d.", current_minutes, summer_active_time_end); blocked = true; is_evening = true; } else { - extended_logging("We are not in block time. Current time: %d, block time morning: %d, block time evening: %d.", current_minutes, summer_block_time_morning, summer_block_time_evening); + extended_logging("We are not in block time. Current time: %d, block time morning: %d, block time evening: %d.", current_minutes, summer_active_time_start, summer_active_time_end); } } diff --git a/software/web/src/modules/heating/api.ts b/software/web/src/modules/heating/api.ts index 6e4fcb6f9..1f4c6f995 100644 --- a/software/web/src/modules/heating/api.ts +++ b/software/web/src/modules/heating/api.ts @@ -4,13 +4,13 @@ export interface config { minimum_control_holding_time: number; meter_slot_grid_power: number; extended_logging_active: boolean; - winter_start_day: number; - winter_start_month: number; - winter_end_day: number; - winter_end_month: number; - summer_block_time_active: boolean; - summer_block_time_morning: number; - summer_block_time_evening: number; + summer_start_day: number; + summer_start_month: number; + summer_end_day: number; + summer_end_month: number; + summer_active_time_active: boolean; + summer_active_time_start: number; + summer_active_time_end: number; summer_yield_forecast_active: boolean; summer_yield_forecast_threshold: number; dpc_extended_active: boolean; diff --git a/software/web/src/modules/heating/main.tsx b/software/web/src/modules/heating/main.tsx index 14306afe5..a62b85090 100644 --- a/software/web/src/modules/heating/main.tsx +++ b/software/web/src/modules/heating/main.tsx @@ -160,16 +160,19 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> data.values[1].push(this.state.dap_prices.prices[i]/1000.0 + grid_costs_and_taxes_and_supplier_markup); } - const num_per_day = 24*60/resolution_multiplier; - console.log(num_per_day) + const num_per_day = 24*60/resolution_multiplier; + const active_active = this.state.summer_active_time_active; + const active_start = this.state.summer_active_time_start/resolution_multiplier; + const active_end = this.state.summer_active_time_end/resolution_multiplier; if (this.state.dap_prices.prices.length >= num_per_day*2) { let avg_price_day1 = this.state.dap_prices.prices.slice(0, num_per_day).reduce((a, b) => a + b, 0) / num_per_day; let avg_price_day2 = this.state.dap_prices.prices.slice(num_per_day).reduce((a, b) => a + b, 0) / num_per_day; for (let i = 0; i < num_per_day; i++) { - console.log(this.state.dap_prices.prices[i], this.state.dpc_extended_threshold, avg_price_day1); - if (this.state.dap_prices.prices[i] < avg_price_day1*this.state.dpc_extended_threshold/100) { + if (((i < active_start) || (i >= active_end)) && active_active) { + data.lines_vertical.push({'index': i, 'text': '', 'color': [196, 196, 196, 0.5]}); + } else if (this.state.dap_prices.prices[i] < avg_price_day1*this.state.dpc_extended_threshold/100) { if (this.state.dpc_extended_active) { data.lines_vertical.push({'index': i, 'text': '', 'color': [0, 255, 0, 0.5]}); } @@ -180,7 +183,9 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> } } for (let i = num_per_day; i < num_per_day*2; i++) { - if (this.state.dap_prices.prices[i] < avg_price_day2*this.state.dpc_extended_threshold/100) { + if ((((i-num_per_day) < active_start) || ((i-num_per_day) >= active_end)) && active_active) { + data.lines_vertical.push({'index': i, 'text': '', 'color': [196, 196, 196, 0.5]}); + } else if (this.state.dap_prices.prices[i] < avg_price_day2*this.state.dpc_extended_threshold/100) { if (this.state.dpc_extended_active) { data.lines_vertical.push({'index': i, 'text': '', 'color': [0, 255, 0, 0.5]}); } @@ -224,32 +229,12 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> return Heating.days.slice(0, 31); } - recalculateSummer(state: Readonly) { - this.summer_start_day = state.winter_end_day + 1; - this.summer_start_month = state.winter_end_month; - if(this.summer_start_day > this.month_to_days(state.winter_end_month).length) { - this.summer_start_day = 1; - this.summer_start_month = state.winter_end_month + 1 > 12 ? 1 : state.winter_end_month + 1; - } - - this.summer_end_day = state.winter_start_day - 1; - this.summer_end_month = state.winter_start_month; - if(this.summer_end_day < 1) { - this.summer_end_month = state.winter_start_month - 1 < 1 ? 12 : state.winter_start_month - 1; - this.summer_end_day = this.month_to_days(this.summer_end_month).length; - } - } - render(props: {}, state: Readonly) { if (!util.render_allowed()) return ; - let days_winter_start = this.month_to_days(state.winter_start_month); - let days_winter_end = this.month_to_days(state.winter_end_month); - let days_summer_start = this.month_to_days(1); - let days_summer_end = this.month_to_days(1); - - this.recalculateSummer(state); + let days_summer_start = this.month_to_days(state.summer_start_month); + let days_summer_end = this.month_to_days(state.summer_end_month); const meter_slots = get_noninternal_meter_slots([MeterValueID.PowerActiveLSumImExDiff], __("power_manager.content.meter_slot_grid_power_missing_value")); @@ -305,9 +290,9 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> onClick={this.toggle('extended_logging_active')} /> - - + +
@@ -315,11 +300,10 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> { - this.setState({winter_start_month: parseInt(v)}); - days_winter_start = this.month_to_days(parseInt(v)); - this.recalculateSummer(state); + this.setState({summer_start_month: parseInt(v)}); + days_summer_start = this.month_to_days(parseInt(v)); }} />
@@ -329,18 +313,17 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState>
{__("heating.content.day")}
{ - this.setState({winter_start_day: parseInt(v)}) - this.recalculateSummer(state); + this.setState({summer_start_day: parseInt(v)}) }} />
- +
@@ -348,11 +331,10 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> { - this.setState({winter_end_month: parseInt(v)}); - days_winter_end = this.month_to_days(parseInt(v)); - this.recalculateSummer(state); + this.setState({summer_end_month: parseInt(v)}); + days_summer_end = this.month_to_days(parseInt(v)); }} />
@@ -362,141 +344,62 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState>
{__("heating.content.day")}
{ - this.setState({winter_end_day: parseInt(v)}) - this.recalculateSummer(state); + this.setState({summer_end_day: parseInt(v)}) }} />
- - - -
-
-
-
{__("heating.content.month")}
- -
-
-
-
-
{__("heating.content.day")}
- -
-
-
+ + - +
-
{__("heating.content.month")}
- {__("heating.content.from")}
+ this.setState({summer_active_time_start: this.get_minutes_from_date(d)}, this.update_uplot)} />
-
{__("heating.content.day")}
- {__("heating.content.to")}
+ this.setState({summer_active_time_end: this.get_minutes_from_date(d)}, this.update_uplot)} />
- - + - -
- -
-
-
-
{__("heating.content.from")}
- -
-
-
-
-
{__("heating.content.to")}
- this.setState({summer_block_time_morning: this.get_minutes_from_date(d)})} - /> -
-
-
-
- -
-
-
-
{__("heating.content.from")}
- this.setState({summer_block_time_evening: this.get_minutes_from_date(d)})} - /> -
-
-
-
-
{__("heating.content.to")}
- -
-
-
-
- - - -
-
@@ -541,7 +444,7 @@ export class Heating extends ConfigComponent<'heating/config', {}, HeatingState> switch_label_min_width="100px" /> - +
{/* this plain div is neccessary to make the size calculation stable in safari. without this div the height continues to grow */} + "active_time_help": <>

Diese Einstellung steuert die Einschaltempfehlung (SG-Ready-Ausgang 2).

-

Wenn die Blockzierzeit aktiviert ist und die aktuelle Uhrzeit innerhalb der Blockierzeit liegt, wird keine Einschaltempfehlung gegeben. Somit kann in der Sommerzeit verhindert werden dass morgens teurer Strom eingekauft wird, wenn Tagsüber die PV-Anlage Strom liefert.

-

Hinweis: Die Blockierzeit kann über eine PV-Ertragsprognose optimiert werden (siehe unten).

+

Wenn die aktuelle Uhrzeit außerhalb der Aktivzeit liegt, wird keine Einschaltempfehlung gegeben. Somit kann in der Sommerzeit verhindert werden dass morgens teurer Strom eingekauft wird, wenn Tagsüber die PV-Anlage Strom liefert.

+

Hinweis: Die Aktivzeit kann von der PV-Ertragsprognose überschrieben werden (siehe unten).

, "enable_daily_block_period": "Täglicher Blockierzeitraum aktiviert", @@ -92,8 +92,8 @@ let x = { "pv_yield_forecast_help": <>

Diese Einstellung steuert die Einschaltempfehlung (SG-Ready-Ausgang 2).

-

Wenn die PV-Ertragsprognose aktiviert ist, kann der Heizung eine Einschaltempfehlung innerhalb der Blockierzeit gegeben werden, wenn die PV-Ertragsprognose (Summe des Ertrags von einem Tag in kWh) die eingetellte Schwelle unterschreitet.

-

Beispiel: Es ist 05:00 morgens und die Blockierzeit ist von 00:00 bis 06:00 aktiv. Die PV-Ertragsprognose ist aktiviert und die Schwelle ist auf 50kWh eingestellt, die Prognose sagt allerdings nur einen Ertrag von 10kWh voraus. In diesem Fall würde trotz der Blockierzeit eine Einschaltempfehlung an die Heizung gesendet, wenn der Strom günstig ist.

+

Wenn die PV-Ertragsprognose aktiviert ist, kann der Heizung eine Einschaltempfehlung auch außerhalb der Aktivzeit gegeben werden, wenn die PV-Ertragsprognose (Summe des Ertrags von einem Tag in kWh) die eingetellte Schwelle unterschreitet.

+

Beispiel: Es ist 05:00 morgens und die Aktivzeit ist von 06:00 bis 18:00. Die PV-Ertragsprognose ist aktiviert und die Schwelle ist auf 50kWh eingestellt, die Prognose sagt allerdings nur einen Ertrag von 10kWh voraus. In diesem Fall würde trotz der Uhrzeit außerhalb der Aktivzeit eine Einschaltempfehlung an die Heizung gesendet, wenn der Strom günstig ist.

Die Idee ist es, Nachts den günstigen Strom zu nutzen wenn bekannt ist das am Tag die Sonne nicht scheinen wird.

, diff --git a/software/web/src/modules/heating/translation_en.tsx b/software/web/src/modules/heating/translation_en.tsx index 4305c2338..3ff21dc48 100644 --- a/software/web/src/modules/heating/translation_en.tsx +++ b/software/web/src/modules/heating/translation_en.tsx @@ -76,7 +76,7 @@ let x = { "summer_start": "Summer Start", "summer_end": "Summer End", "block_time": "Block Time", - "block_time_help": <> + "active_time_help": <>

Diese Einstellung steuert die Einschaltempfehlung (SG-Ready-Ausgang 2).

Wenn die Blockzierzeit aktiviert ist und die aktuelle Uhrzeit innerhalb der Blockierzeit liegt, wird keine Einschaltempfehlung gegeben. Somit kann in der Sommerzeit verhindert werden dass morgens teurer Strom eingekauft wird, wenn Tagsüber die PV-Anlage Strom liefert.