diff --git a/aircon.sh b/aircon.sh index 5438adc..2ee0500 100755 --- a/aircon.sh +++ b/aircon.sh @@ -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() { @@ -854,7 +899,7 @@ function weekdaytonum() { "mon") num=1;; "tue") num=2;; "wed") num=3;; - "thu") num=4;; + "thu") num=4;; "fri") num=5;; "sat") num=6;; "sun") num=7;; @@ -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)