Add concept of a "perfect" temperature when a zone's temperature is within 25% of the desired range midpoint

If all zones are "perfect", turn the system off
This commit is contained in:
Rob Pearce 2022-05-29 10:27:40 +10:00
parent a821b1efb2
commit e16f18e7da
1 changed files with 92 additions and 39 deletions

129
aircon.sh
View File

@ -97,6 +97,14 @@ function get_midrange() { # outputs midpoint of temperature range for given zon
echo "($min + $max) / 2" | bc
}
# get_perfect_tolerance zone_idx
function get_perfect_tolerance() { # outputs the difference from midpoint inside which temperature is considered "perfect"
local min max
min=${zwantmin[$idx]}
max=${zwantmax[$idx]}
echo "scale=2; ($max - $min) / 4" | bc
}
function getoppositestate() {
if [[ $1 == "open" ]]; then
echo "close"
@ -107,13 +115,14 @@ function getoppositestate() {
function getzoneaction() { # populates zproblem[] and zaction[]
local idx problem num thisaction priority pingok fv
local donearby
local donearby thisperfect=0
idx=$1
profile "getzoneaction for idx ${zname[$idx]}"
thisaction="n/a"
if [[ ${zignore[$idx]} -eq 1 ]]; then
problem="n/a"
thisperfect=1
else
if [[ -z ${zowner[$idx]} ]]; then
pingok=1
@ -121,12 +130,13 @@ function getzoneaction() { # populates zproblem[] and zaction[]
pingok=1
else
pingok=0
thisperfect=1
fi
fv=$(getforcevent ${zname[$idx]})
donearby=0
if [[ ! -z $fv && ${zstate[$idx]} == $(getoppositestate ${fv}) ]]; then
if [[ -n $fv && ${zstate[$idx]} == $(getoppositestate ${fv}) ]]; then
problem="force_${fv}"
priority=99
elif [[ $airconmode != "off" && ${zstate[$idx]} != "close" && $pingok -eq 0 ]]; then
@ -147,8 +157,23 @@ function getzoneaction() { # populates zproblem[] and zaction[]
else
problem="n/a"
priority=0
if [[ $pingok -eq 1 ]]; then
# check for 'perfect' zones
if [[ ${zwanttemp[$idx]} != *-* ]]; then
thisperfect=1
else
local mid midtol
mid=$(get_midrange $idx)
midtol=$(get_perfect_tolerance $idx)
#echo "zone ${zname[$idx]} temp ${ztemp[$idx]} mid is $mid midtol is $midtol perfect is >= $(echo "$mid - $midtol" | bc)"
if [[ $airconmode == "heat" ]]; then
thisperfect=$(echo "${ztemp[$idx]} >= (${mid} - ${midtol})" | bc)
elif [[ $airconmode == "cool" ]]; then
thisperfect=$(echo "${ztemp[$idx]} <= (${mid} + ${midtol})" | bc)
fi
fi
fi
fi
#info "${zname[$idx]} priority is $priority"
zproblem[$idx]="$problem"
zpri[$idx]="$priority"
zownerhome[$idx]="$pingok"
@ -243,6 +268,7 @@ function getzoneaction() { # populates zproblem[] and zaction[]
fi
fi
zaction[$idx]="$thisaction"
zperfect[$idx]=$thisperfect
profile "getzoneaction for idx ${zname[$idx]}"
}
@ -325,8 +351,17 @@ function find_nearby_zones() { # zone_idx filter1 filter2 ... filter is: o
echo "$nearbyzones"
}
function all_zones_perfect() {
local x
for x in ${zperfect[@]}; do
if [[ $x -ne 1 ]]; then
return 1
fi
done
return 0
}
function generate_actions() { # populates global: nairconcommands & airconcmd[]
function generate_actions() { # populates global: nairconcommands & airconcmd[] & globprob
local x y z adj tempstr nhot ncold
local powerchange nmyzones maxpri bestidx
local globaction mzmustmove poss nomyzone
@ -396,16 +431,23 @@ function generate_actions() { # populates global: nairconcommands & airconcmd
globsetmode=" set_mode:cool"
fi
fi
[[ ! -z $globsetmode ]] && globaction="power_on"
[[ -n $globsetmode ]] && globaction="power_on"
else
if [[ $airconmode == "heat" && $nhot -ge $limit ]]; then
globprob="too_hot"
elif [[ $airconmode == "cool" && $ncold -ge $limit ]]; then
globprob="too_cold"
elif [[ $ncold -eq 0 && $nhot -eq 0 ]]; then
if all_zones_perfect; then
globprob="not_needed"
fi
[[ ! -z $globprob ]] && globaction="power_off"
fi
if [[ -n $globprob ]]; then
globaction="power_off"
[[ -z $powerchange ]] && powerchange="power_off"
fi
if [[ ! -z $globprob ]]; then
fi
if [[ -n $globprob ]]; then
for x in ${!zname[@]}; do
if [[ ${zproblem[$x]} == $globprob && ${zaction[$x]} != *${globaction}* ]]; then
zaction[$x]="$globaction$globsetmode ${zaction[$x]}"
@ -431,7 +473,7 @@ function generate_actions() { # populates global: nairconcommands & airconcmd
fi
# pass 3 - If we're powering the whole system on/off, don't do anything else
if [[ ! -z $powerchange ]]; then
if [[ -n $powerchange ]]; then
for x in ${!zname[@]}; do
if [[ ${powerchange} == "power_off" && ${zaction[$x]} != $powerchange ]]; then
zactionfail[$x]=1
@ -447,10 +489,10 @@ function generate_actions() { # populates global: nairconcommands & airconcmd
# get list of all zones which can't be myzone
nomyzone=""
for x in ${!zname[@]}; do
if [[ ${znomyzone[$x]} -eq 1 ]]; then
nomyzone="$nomyzone ${zname[$x]} "
fi
done
if [[ ${znomyzone[$x]} -eq 1 ]]; then
nomyzone="$nomyzone ${zname[$x]} "
fi
done
for x in ${!zname[@]}; do
if [[ $airconmyzoneid == ${zid[$x]} || ${zaction[$x]} == *set_myzone* ]]; then
if [[ ${zstate[$x]} == "close" || ${zaction[$x]} == *close_vent* ]]; then
@ -541,9 +583,11 @@ function generate_actions() { # populates global: nairconcommands & airconcmd
gen_aircon_command ${x} ${zaction[$x]}
fi
done
if [[ -n $globaction ]]; then
gen_aircon_command -1 ${globaction}
fi
}
# gen_aircon_command zone_idx "command1 command2 etc"
function gen_aircon_command() {
local idx allactions this toadd num doneset othername otherid otheridx db donemode str
@ -563,13 +607,16 @@ function gen_aircon_command() {
elif [[ $this == *power_off* ]]; then
add_aircon_command $idx -1 "Power off system" "off"
elif [[ $this == *set_myzone* && $airconmyzoneid != ${zid[$idx]} ]]; then
[[ $idx -eq -1 ]] && continue
add_aircon_command $idx -1 "Set MyZone to ${zname[$idx]}" "myzone --zone ${zid[$idx]}"
elif [[ $this == *open:* ]]; then
[[ $idx -eq -1 ]] && continue
othername=$(echo "$this" | sed -e 's/^.*open://;s/ .*//')
otheridx=$(getidxfromname $othername)
otherid=${zid[$otheridx]}
add_aircon_command $idx $otheridx "Open vent in ${zname[$otheridx]}" "set --zone ${otherid} --state on --temp ${zsettemp[$otheridx]}"
elif [[ $this == *close:* ]]; then
[[ $idx -eq -1 ]] && continue
othername=$(echo "$this" | sed -e 's/^.*close://;s/ .*//')
otheridx=$(getidxfromname $othername)
otherid=${zid[$otheridx]}
@ -578,6 +625,7 @@ function gen_aircon_command() {
str=$(echo "$this" | sed -e 's/^.*set_mode://;s/ .*//')
add_aircon_command $idx -1 "Set system mode to '$str'" "$str"
elif [[ $this == *set_temp* || $this == *open_vent* || $this == *close_vent* ]]; then
[[ $idx -eq -1 ]] && continue
if [[ $doneset -eq 0 ]]; then
toadd=""
comm=""
@ -591,12 +639,12 @@ function gen_aircon_command() {
if [[ $allactions == *set_temp* ]]; then
num=$(echo "$this" | sed -e 's/^.*set_temp://;s/ .*//')
toadd="$toadd --temp $num"
[[ ! -z $comm ]] && comm="${comm} and "
[[ -n $comm ]] && comm="${comm} and "
comm="${comm}set temperature to $num degrees"
else
toadd="$toadd --temp ${zsettemp[$idx]}"
fi
if [[ ! -z $toadd ]]; then
if [[ -n $toadd ]]; then
add_aircon_command $idx -1 "In zone ${zname[$idx]}, $comm" "set --zone ${zid[$idx]}$toadd"
doneset=1
fi
@ -619,7 +667,7 @@ function add_aircon_command() {
shift
if [[ $otheridx -ne -1 ]]; then
if [[ ! -z $comment ]]; then
if [[ -n $comment ]]; then
comment="${comment} (to fix ${zname[$idx]})"
fi
fi
@ -629,6 +677,7 @@ function add_aircon_command() {
[[ -z $* ]] && return 1
# already got this command queued?
for x in ${airconcmd[@]}; do
if [[ $x == "$*" ]]; then
return 1
@ -636,10 +685,18 @@ function add_aircon_command() {
done
airconcmd[$nairconcommands]="$*"
airconcomment[$nairconcommands]="$comment"
airconcmdzone[$nairconcommands]="${zname[$idx]}"
airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}"
airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }"
ooooooooooo
if [[ $idx -eq -1 ]]; then
airconcmdzone[$nairconcommands]="Aircon"
airconproblem[$nairconcommands]="Aircon is not needed at this time."
else
airconcmdzone[$nairconcommands]="${zname[$idx]}"
airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }"
fi
if [[ $otheridx -eq -1 ]]; then
airconcmdotherzone[$nairconcommands]=""
else
airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}"
fi
#if [[ $otheridx -ne -1 ]]; then
# airconcomment[$nairconcommands]="${airconcomment[$nairconcommands]}, update nearby zone ${zname[$otheridx]}"
#fi
@ -647,7 +704,6 @@ ooooooooooo
return 0
}
function addnoop() {
local idx
idx=$(getidxfromname "$1")
@ -706,18 +762,7 @@ function addtemprange() { # [-s] idx min-max -s means 'set zwanttemp+z
zwantmax[$zidx]="${wanttemp#*-}"
fi
fi
[[ $idx == $ntempranges ]] && ntempranges=$((ntempranges + 1))
}
function addadj() {
@ -995,7 +1040,7 @@ function processtimeconditions() {
return 1
fi
fi
if [[ ! -z $starth ]]; then
if [[ -n $starth ]]; then
[[ $db -eq 1 ]] && info " check if $nowh is between $starth and $endh"
ok=0
if [[ $(echo "$starth < $endh" | bc) == "1" ]]; then
@ -1117,7 +1162,7 @@ function parse_config() {
line=${line%%#*} # remove comments
thisignored=0
line_human=""
if [[ ! -z ${line// } ]]; then
if [[ -n ${line// } ]]; then
# time based options
if [[ ${line:0:1} == "@" ]]; then
# strip condition off the front
@ -1263,6 +1308,7 @@ function addzone() {
ztemp[$nzones]="$temp"
zid[$nzones]="$id"
zwanttemp[$nzones]="n/a"
zperfect[$nzones]=0
zproblem[$nzones]="n/a"
zaction[$nzones]="n/a"
zactionfail[$nzones]=0
@ -1375,6 +1421,7 @@ function show_aircon_status() {
FORMATHOT="${RED}%-7s${PLAIN}"
FORMATCOLD="${CYAN}%-7s${PLAIN}"
FORMATOK="${WHITE}%-7s${PLAIN}"
FORMATPERFECT="${GREEN}%-7s${PLAIN}"
CLOSEDFORM="$GREY%-8s$PLAIN"
OPENFORM="$PLAIN%-8s$PLAIN"
@ -1398,6 +1445,8 @@ function show_aircon_status() {
actualtempformat="${FORMATHOT}"
elif [[ ${zproblem[$x]} == "too_cold" ]]; then
actualtempformat="${FORMATCOLD}"
elif [[ ${zperfect[$x]} -eq 1 ]]; then
actualtempformat="${FORMATPERFECT}"
else
actualtempformat="${FORMATOK}"
fi
@ -1507,6 +1556,10 @@ function show_analysis() {
done
if [[ $globprob == too_* ]]; then
echo "- $limit or more zones are ${globprob/_/ }"
count=$((count + 1))
elif [[ $globprob == "not_needed" ]]; then
echo "- System is on but all zones at optimal temperature"
count=$((count + 1))
fi
[[ $count -eq 0 ]] && echo -e "${GREEN}All is good!${PLAIN}"
}
@ -1536,7 +1589,7 @@ function show_proposed_commands() {
for x in ${!airconcmd[@]}; do
fullcmd="myair $AIRCON_IP ${airconcmd[$x]}"
printf -- "$cmdformat" "$fullcmd"
[[ ! -z ${airconcomment[$x]} ]] && printf " $GREEN$BOLD# $PLAIN$GREEN%s$PLAIN\n" "${airconcomment[$x]}" || echo
[[ -n ${airconcomment[$x]} ]] && printf " $GREEN$BOLD# $PLAIN$GREEN%s$PLAIN\n" "${airconcomment[$x]}" || echo
count=$((count + 1))
done
[[ $count -eq 0 ]] && echo -e "${GREY}n/a${PLAIN}"
@ -1545,7 +1598,7 @@ function show_proposed_commands() {
function run_commands() {
local x
for x in ${!airconcmd[@]}; do
[[ ! -z ${airconcomment[$x]} ]] && action "${airconcomment[$x]}"
[[ -n ${airconcomment[$x]} ]] && action "${airconcomment[$x]}"
echo RUNNING myair $AIRCON_IP ${airconcmd[$x]}
myair $AIRCON_IP ${airconcmd[$x]} >/dev/null 2>&1
influx_insert "INSERT aircon action=\"${airconcomment[$x]}\",comment=\"${airconproblem[$x]}\""
@ -1657,7 +1710,7 @@ RULEFORMAT=ansi
# check for config file option first
if [[ $* == *-f\ * ]]; then
cf=$(echo "$*" | sed -e 's/.*-f //;s/ .*//')
if [[ ! -z $cf ]]; then
if [[ -n $cf ]]; then
CONFIGFILE="$cf"
fi
fi
@ -1718,7 +1771,7 @@ while getopts "$optstring" i $ALLARGS; do
enable_cronmode
;;
p)
profiler=1
profiler=1
info "Profiler mode enabled"
;;
m)