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

131
aircon.sh
View File

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