Skip to content

Commit 7db9f7e

Browse files
introducing dynamic discharge depending SOC
1 parent cf18dc4 commit 7db9f7e

File tree

1 file changed

+122
-11
lines changed

1 file changed

+122
-11
lines changed

scripts/controller.sh

Lines changed: 122 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/bash
22

3-
VERSION="2.5.4"
3+
VERSION="2.5.5-DEV"
44

55
if [ -z "$LANG" ]; then
66
export LANG="C"
@@ -120,7 +120,7 @@ parse_and_validate_config() {
120120
else
121121
# Advanced validation for Bash > 4
122122
declare -A valid_vars=(
123-
["config_version"]="12" # Updated to 12 for the new version
123+
["config_version"]="13"
124124
["use_fritz_dect_sockets"]="0|1"
125125
["fbox"]="^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$"
126126
["user"]="string"
@@ -749,6 +749,58 @@ manage_discharging() {
749749
fi
750750
}
751751

752+
get_dynamic_target_hours() {
753+
local current_soc=$1
754+
local matrix_name=$2
755+
local -n matrix_ref="${matrix_name}" # Use nameref to access the specified global array
756+
757+
# Check if the matrix is defined and not empty
758+
if [ -z "${matrix_ref+x}" ] || [ ${#matrix_ref[@]} -eq 0 ]; then
759+
# log_message >&2 "W: Matrix '$matrix_name' is not defined or empty. Returning 0 hours."
760+
echo "0.0"
761+
return
762+
fi
763+
764+
local result_hours=""
765+
766+
# Sort the matrix by SoC to ensure correct interpolation
767+
IFS=$'\n' sorted_matrix=($(sort -n -k1 <<<"${matrix_ref[*]}"))
768+
unset IFS
769+
770+
# Handle edge case: SoC is lower than the lowest defined point
771+
IFS=' ' read -r min_soc min_hours <<< "${sorted_matrix[0]}"
772+
if (( $(awk -v current="$current_soc" -v min="$min_soc" 'BEGIN {print (current <= min)}') )); then
773+
echo "$min_hours"
774+
return
775+
fi
776+
777+
# Handle edge case: SoC is higher than the highest defined point
778+
IFS=' ' read -r max_soc max_hours <<< "${sorted_matrix[-1]}"
779+
if (( $(awk -v current="$current_soc" -v max="$max_soc" 'BEGIN {print (current >= max)}') )); then
780+
echo "$max_hours"
781+
return
782+
fi
783+
784+
# Find the two points to interpolate between
785+
for ((i = 0; i < ${#sorted_matrix[@]} - 1; i++)); do
786+
IFS=' ' read -r lower_soc lower_hours <<< "${sorted_matrix[$i]}"
787+
IFS=' ' read -r upper_soc upper_hours <<< "${sorted_matrix[$((i + 1))]}"
788+
789+
if (( $(awk -v current="$current_soc" -v lower="$lower_soc" -v upper="$upper_soc" 'BEGIN {print (current >= lower && current < upper)}') )); then
790+
# Perform linear interpolation
791+
result_hours=$(awk -v x="$current_soc" \
792+
-v x1="$lower_soc" -v y1="$lower_hours" \
793+
-v x2="$upper_soc" -v y2="$upper_hours" \
794+
'BEGIN {printf "%.2f", y1 + (x - x1) * (y2 - y1) / (x2 - x1)}')
795+
echo "$result_hours"
796+
return
797+
fi
798+
done
799+
800+
# Fallback to the minimum hours if no range is found (should not happen with sorted array)
801+
echo "$min_hours"
802+
}
803+
752804
manage_fritz_sockets() {
753805
local action=$1
754806
[ "$action" != "off" ] && action=$([ "$execute_fritzsocket_on" == "1" ] && echo "on" || echo "off")
@@ -1818,24 +1870,83 @@ shelly_sockets_state="unknown"
18181870
fritz_sockets_state="unknown"
18191871
fritz_switchable_sockets_table=""
18201872
shelly_switchable_sockets_table=""
1873+
1874+
# 1. Calculate Discharge Hours
1875+
discharge_hours="0.0"
1876+
if [ "$discharge_strategy" == "dynamic" ]; then
1877+
discharge_hours=$(get_dynamic_target_hours "$SOC_percent" "discharge_hours_matrix")
1878+
log_message >&2 "I: Dynamic Discharge: SoC is $SOC_percent%. Targeting the most expensive $discharge_hours hours."
1879+
fi
1880+
1881+
# 2. Calculate Fritz Socket ON-Hours
1882+
fritz_hours="0.0"
1883+
if (( use_fritz_dect_sockets == 1 )) && [ "$fritz_socket_strategy" == "dynamic" ]; then
1884+
fritz_hours=$(get_dynamic_target_hours "$SOC_percent" "fritz_socket_hours_matrix")
1885+
log_message >&2 "I: Dynamic Fritz Sockets: SoC is $SOC_percent%. Targeting $fritz_hours ON-hours."
1886+
fi
1887+
1888+
# 3. Calculate Shelly Socket ON-Hours
1889+
shelly_hours="0.0"
1890+
if (( use_shelly_wlan_sockets == 1 )) && [ "$shelly_socket_strategy" == "dynamic" ]; then
1891+
shelly_hours=$(get_dynamic_target_hours "$SOC_percent" "shelly_socket_hours_matrix")
1892+
log_message >&2 "I: Dynamic Shelly Sockets: SoC is $SOC_percent%. Targeting $shelly_hours ON-hours."
1893+
fi
1894+
18211895
for idx in "${!sorted_prices[@]}"; do
18221896
i=$((idx + 1))
18231897
charge_value="${charge_array[$idx]}"
1824-
discharge_value="${discharge_array[$idx]}"
1825-
fritzsocket_value="${fritzsocket_array[$idx]}"
1826-
shellysocket_value="${shellysocket_array[$idx]}"
1898+
discharge_value="${discharge_array[$idx]}" # For static mode
1899+
fritzsocket_value="${fritzsocket_array[$idx]}" # For static mode
1900+
shellysocket_value="${shellysocket_array[$idx]}" # For static mode
18271901

1902+
# --- Charge Logic (unchanged) ---
18281903
if [ "$charge_value" -eq 1 ]; then
18291904
charge_table="$charge_table $i"
18301905
fi
1831-
if [ "$use_charger" -ne 0 ] && [ "$SOC_percent" -ge "$discharge_value" ]; then
1832-
discharge_table="$discharge_table $i"
1906+
1907+
# --- Universal Dynamic/Static Logic for all components ---
1908+
1909+
# 1. Discharge Table Population
1910+
if [ "$discharge_strategy" == "dynamic" ]; then
1911+
num_slots=$(awk -v h="$discharge_hours" 'BEGIN {printf "%.0f", h * 4}')
1912+
start_idx=$(( ${#sorted_prices[@]} - num_slots ))
1913+
if (( idx >= start_idx && SOC_percent > sonnen_minimum_SoC )); then
1914+
discharge_table="$discharge_table $i"
1915+
fi
1916+
else # Static
1917+
if [ "$use_charger" -ne 0 ] && [ "$SOC_percent" -ge "$discharge_value" ]; then
1918+
discharge_table="$discharge_table $i"
1919+
fi
18331920
fi
1834-
if [ "$fritzsocket_value" -eq 1 ]; then
1835-
fritz_switchable_sockets_table="$fritz_switchable_sockets_table $i"
1921+
1922+
# 2. Fritz Socket Table Population
1923+
if (( use_fritz_dect_sockets == 1 )); then
1924+
if [ "$fritz_socket_strategy" == "dynamic" ]; then
1925+
num_slots=$(awk -v h="$fritz_hours" 'BEGIN {printf "%.0f", h * 4}')
1926+
start_idx=$(( ${#sorted_prices[@]} - num_slots ))
1927+
if (( idx >= start_idx )); then
1928+
fritz_switchable_sockets_table="$fritz_switchable_sockets_table $i"
1929+
fi
1930+
else # Static
1931+
if [ "$fritzsocket_value" -eq 1 ]; then
1932+
fritz_switchable_sockets_table="$fritz_switchable_sockets_table $i"
1933+
fi
1934+
fi
18361935
fi
1837-
if [ "$shellysocket_value" -eq 1 ]; then
1838-
shelly_switchable_sockets_table="$shelly_switchable_sockets_table $i"
1936+
1937+
# 3. Shelly Socket Table Population
1938+
if (( use_shelly_wlan_sockets == 1 )); then
1939+
if [ "$shelly_socket_strategy" == "dynamic" ]; then
1940+
num_slots=$(awk -v h="$shelly_hours" 'BEGIN {printf "%.0f", h * 4}')
1941+
start_idx=$(( ${#sorted_prices[@]} - num_slots ))
1942+
if (( idx >= start_idx )); then
1943+
shelly_switchable_sockets_table="$shelly_switchable_sockets_table $i"
1944+
fi
1945+
else # Static
1946+
if [ "$shellysocket_value" -eq 1 ]; then
1947+
shelly_switchable_sockets_table="$shelly_switchable_sockets_table $i"
1948+
fi
1949+
fi
18391950
fi
18401951
done
18411952

0 commit comments

Comments
 (0)