diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/aircon.sh b/aircon.sh index e435648..c365955 100755 --- a/aircon.sh +++ b/aircon.sh @@ -17,54 +17,61 @@ VALID_ZONE_STATES=" open close " BOLD="\033[1m" PLAIN="\033[0m" +STRIKE="\033[9m" UNDERLINE="\033[4m" -GREY="\033[1;30m" +DARKGREY="\033[38;2;90;90;90m" RED="\033[31m" +ORANGE="\033[38;2;255;165;0m" +PINK="\033[38;2;255;151;198m" +MAGENTA="\033[35m" GREEN="\033[32m" YELLOW="\033[33m" BLUE="\033[34m" CYAN="\033[36m" +GREY="\033[2;37m" WHITE="\033[37m" LINK="$BLUE$UNDERLINE" function enable_cronmode() { - cronmode=1 - BOLD="" - PLAIN="" - UNDERLINE="" - GREY="" - RED="" - GREEN="" - YELLOW="" - BLUE="" - CYAN="" - WHITE="" - LINK="$BLUE$UNDERLINE" + cronmode=1 + BOLD="" + PLAIN="" + UNDERLINE="" + GREY="" + RED="" + GREEN="" + YELLOW="" + BLUE="" + CYAN="" + WHITE="" + LINK="$BLUE$UNDERLINE" } function usage() { - echo "usage: $0 [options]" - echo - echo " Modifies aircon based on configured parameters in $DEFAULT_CONFIGFILE." - echo - echo " -h Show this text." - echo " -c Cron mode. Only show output if actions were taken." - echo " -i x.x.x.x Specify IP address for aircon (default is $DEFAULT_AIRCON_IP)" - echo " -I db Log all zone temperatures to given influxdb database, then exit (see -o)." - echo " -A db Log actions to given influxdb database." - echo " -f file Specify an alternate config file." - echo " -k file If file exists, never change aircon settings (default: $DEFAULT_KILLFILE)." - echo " -l num Set number of too hot/cold zones at which to taking action." - echo " -L Log all zone temperatures to CSV file, then exit (see -o)." - echo " -o file Specify CSV output file. Default: $DEFAULT_CSVFILE" - echo " -m Generate a config file based on current aircon setup." - echo " -p Profiler mode." - echo " -w List which zone owners' devices are available then exit." - echo " -t num Specify degrees below min temperature before taking action." - echo " -T num Specify degrees above max temperature before taking action." - echo " -y Actually run commands/db inserts. By default, commands are just displayed." - echo + echo "usage: $0 [options]" + echo + echo " Modifies aircon based on configured parameters in $DEFAULT_CONFIGFILE." + echo + echo " -h Show this text." + echo " -c Cron mode. Only show output if actions were taken." + echo " -i x.x.x.x Specify IP address for aircon (default is $DEFAULT_AIRCON_IP)" + echo " -I db Log all zone temperatures to given influxdb database, then exit (see -o)." + echo " -A db Log actions to given influxdb database." + echo " -f file Specify an alternate config file." + echo " -k file If file exists, never change aircon settings (default: $DEFAULT_KILLFILE)." + echo " -l num Set number of too hot/cold zones at which to taking action." + echo " -L Log all zone temperatures to CSV file, then exit (see -o)." + echo " -o file Specify CSV output file. Default: $DEFAULT_CSVFILE" + echo " -m Generate a config file based on current aircon setup." + echo " -p Profiler mode." + echo " -s Validate config file then exit." + echo " -S Show configured rules in human-readable format." + echo " -w List which zone owners' devices are available then exit." + echo " -t num Specify degrees below min temperature before taking action." + echo " -T num Specify degrees above max temperature before taking action." + echo " -y Actually run commands/db inserts. By default, commands are just displayed." + echo } function action() { @@ -81,1182 +88,1336 @@ function info() { # get_midrange zone_idx function get_midrange() { # outputs midpoint of temperature range for given zone - local min max - min=${zwantmin[$idx]} - max=${zwantmax[$idx]} - echo "($min + $max) / 2" | bc + local min max + min=${zwantmin[$idx]} + max=${zwantmax[$idx]} + echo "($min + $max) / 2" | bc } function getoppositestate() { - if [[ $1 == "open" ]]; then - echo "close" - elif [[ $1 == "close" ]]; then - echo "open" - fi + if [[ $1 == "open" ]]; then + echo "close" + elif [[ $1 == "close" ]]; then + echo "open" + fi } function getzoneaction() { # populates zproblem[] and zaction[] - local idx problem num thisaction priority pingok fv - local donearby - idx=$1 + local idx problem num thisaction priority pingok fv + local donearby + idx=$1 - profile "getzoneaction for idx ${zname[$idx]}" - thisaction="n/a" - if [[ ${zignore[$idx]} -eq 1 ]]; then - problem="n/a" - else - if [[ -z ${zowner[$idx]} ]]; then - pingok=1 - elif canping "${zowner[$idx]}"; then - pingok=1 - else - pingok=0 - fi - fv=$(getforcevent ${zname[$idx]}) + profile "getzoneaction for idx ${zname[$idx]}" + thisaction="n/a" + if [[ ${zignore[$idx]} -eq 1 ]]; then + problem="n/a" + else + if [[ -z ${zowner[$idx]} ]]; then + pingok=1 + elif canping "${zowner[$idx]}"; then + pingok=1 + else + pingok=0 + fi + fv=$(getforcevent ${zname[$idx]}) - donearby=0 + donearby=0 - if [[ ! -z $fv && ${zstate[$idx]} == $(getoppositestate ${fv}) ]]; then - problem="force_${fv}" - priority=99 - elif [[ $airconmode != "off" && ${zstate[$idx]} != "close" && $pingok -eq 0 ]]; then - problem="owner_not_home" - priority=99 - elif [[ $pingok -eq 1 && $(echo "${ztemp[$idx]} > (${zwantmax[$idx]} + $tolerance_h)" | bc) -eq 1 ]]; then - problem="too_hot" - priority=$(echo "${ztemp[$idx]} - ${zwantmax[$idx]}" | bc) - if [[ $(echo "${ztemp[$idx]} > (${zwantmax[$idx]} + ($tolerance_h * 2))" | bc) -eq 1 ]]; then - donearby=1 - fi - elif [[ $pingok -eq 1 && $(echo "${ztemp[$idx]} < (${zwantmin[$idx]} - $tolerance_l)" | bc) -eq 1 ]]; then - problem="too_cold" - priority=$(echo "${zwantmin[$idx]} - ${ztemp[$idx]}" | bc) - if [[ $(echo "${ztemp[$idx]} < (${zwantmin[$idx]} - ($tolerance_l * 2))" | bc) -eq 1 ]]; then - donearby=1 - fi - else - problem="n/a" - priority=0 - fi - #info "${zname[$idx]} priority is $priority" - zproblem[$idx]="$problem" - zpri[$idx]="$priority" + if [[ ! -z $fv && ${zstate[$idx]} == $(getoppositestate ${fv}) ]]; then + problem="force_${fv}" + priority=99 + elif [[ $airconmode != "off" && ${zstate[$idx]} != "close" && $pingok -eq 0 ]]; then + problem="owner_not_home" + priority=99 + elif [[ $pingok -eq 1 && $(echo "${ztemp[$idx]} > (${zwantmax[$idx]} + $tolerance_h)" | bc) -eq 1 ]]; then + problem="too_hot" + priority=$(echo "${ztemp[$idx]} - ${zwantmax[$idx]}" | bc) + if [[ $(echo "${ztemp[$idx]} > (${zwantmax[$idx]} + ($tolerance_h * 2))" | bc) -eq 1 ]]; then + donearby=1 + fi + elif [[ $pingok -eq 1 && $(echo "${ztemp[$idx]} < (${zwantmin[$idx]} - $tolerance_l)" | bc) -eq 1 ]]; then + problem="too_cold" + priority=$(echo "${zwantmin[$idx]} - ${ztemp[$idx]}" | bc) + if [[ $(echo "${ztemp[$idx]} < (${zwantmin[$idx]} - ($tolerance_l * 2))" | bc) -eq 1 ]]; then + donearby=1 + fi + else + problem="n/a" + priority=0 + fi + #info "${zname[$idx]} priority is $priority" + zproblem[$idx]="$problem" + zpri[$idx]="$priority" - if [[ $problem == "owner_not_home" ]]; then - # turn the zone off - if [[ ${zstate[$idx]} != "close" ]]; then - thisaction="$thisaction close_vent" - fi - elif [[ $problem =~ force_ ]]; then - if [[ ${zstate[$idx]} != $fv ]]; then - thisaction="$thisaction ${fv}_vent" - fi - elif [[ $problem == "too_cold" ]]; then - if [[ $airconmode == "heat" || $airconmode == "off" ]]; then - # turn the system on, if required - if [[ $airconmode == "off" ]]; then - if [[ $modelock == "n/a" || $modelock == "heat" ]]; then - thisaction="$thisaction power_on set_mode:heat" - fi - fi + if [[ $problem == "owner_not_home" ]]; then + # turn the zone off + if [[ ${zstate[$idx]} != "close" ]]; then + thisaction="$thisaction close_vent" + fi + elif [[ $problem =~ force_ ]]; then + if [[ ${zstate[$idx]} != $fv ]]; then + thisaction="$thisaction ${fv}_vent" + fi + elif [[ $problem == "too_cold" ]]; then + if [[ $airconmode == "heat" || $airconmode == "off" ]]; then + # turn the system on, if required + if [[ $airconmode == "off" ]]; then + if [[ $modelock == "n/a" || $modelock == "heat" ]]; then + thisaction="$thisaction power_on set_mode:heat" + fi + fi - # if we couldnt turn the system on, there's nothing else to do - if [[ $airconmode == "heat" ]]; then - # adjust set temperature, if required - if [[ $(echo "${zsettemp[$idx]} > ${zwantmax[$idx]}" | bc) -eq 1 || $(echo "${zsettemp[$idx]} < ${zwantmin[$idx]}" | bc) -eq 1 ]]; then - # set temperature to midpoint of acceptable range - num=$(get_midrange $idx) - if [[ $zsettemp != $num ]]; then - thisaction="$thisaction set_temp:$num" - fi - fi - # open the vent, if required - if [[ ${zstate[$idx]} != "open" ]]; then - thisaction="$thisaction open_vent" - fi - # set myzone, even if not required (will fix later) - thisaction="$thisaction set_myzone" - fi - elif [[ $airconmode == "cool" ]]; then - # set temperature to midpoint of acceptable range - num=$(get_midrange $idx) - if [[ $zsettemp != $num ]]; then - thisaction="$thisaction set_temp:$num" - fi - # close the vent, if required - if [[ ${zstate[$idx]} != "close" ]]; then - thisaction="$thisaction close_vent" - elif [[ $donearby -eq 1 ]]; then - thisaction="close_nearby_zone" - fi - fi - elif [[ $problem == "too_hot" ]]; then - if [[ $airconmode == "cool" || $airconmode == "off" ]]; then - # turn the system on, if required - if [[ $airconmode == "off" ]]; then - if [[ $modelock == "n/a" || $modelock == "cool" ]]; then - thisaction="$thisaction power_on set_mode:cool" - fi - fi + # if we couldnt turn the system on, there's nothing else to do + if [[ $airconmode == "heat" ]]; then + # adjust set temperature, if required + if [[ $(echo "${zsettemp[$idx]} > ${zwantmax[$idx]}" | bc) -eq 1 || $(echo "${zsettemp[$idx]} < ${zwantmin[$idx]}" | bc) -eq 1 ]]; then + # set temperature to midpoint of acceptable range + num=$(get_midrange $idx) + if [[ $zsettemp != $num ]]; then + thisaction="$thisaction set_temp:$num" + fi + fi + # open the vent, if required + if [[ ${zstate[$idx]} != "open" ]]; then + thisaction="$thisaction open_vent" + fi + # set myzone, even if not required (will fix later) + thisaction="$thisaction set_myzone" + fi + elif [[ $airconmode == "cool" ]]; then + # set temperature to midpoint of acceptable range + num=$(get_midrange $idx) + if [[ $zsettemp != $num ]]; then + thisaction="$thisaction set_temp:$num" + fi + # close the vent, if required + if [[ ${zstate[$idx]} != "close" ]]; then + thisaction="$thisaction close_vent" + elif [[ $donearby -eq 1 ]]; then + thisaction="close_nearby_zone" + fi + fi + elif [[ $problem == "too_hot" ]]; then + if [[ $airconmode == "cool" || $airconmode == "off" ]]; then + # turn the system on, if required + if [[ $airconmode == "off" ]]; then + if [[ $modelock == "n/a" || $modelock == "cool" ]]; then + thisaction="$thisaction power_on set_mode:cool" + fi + fi - # if we couldnt turn the system on, there's nothing else to do - if [[ $airconmode == "cool" ]]; then - # adjust set temperature, if required - if [[ $(echo "${zsettemp[$idx]} > ${zwantmax[$idx]}" | bc) -eq 1 || $(echo "${zsettemp[$idx]} < ${zwantmin[$idx]}" | bc) -eq 1 ]]; then - # set temperature to midpoint of acceptable range - num=$(get_midrange $idx) - if [[ $zsettemp != $num ]]; then - thisaction="$thisaction set_temp:$num" - fi - fi - # open the vent, if required - if [[ ${zstate[$idx]} != "open" ]]; then - thisaction="$thisaction open_vent" - fi - # set myzone, even if not required (will fix later) - thisaction="$thisaction set_myzone" - fi - elif [[ $airconmode == "heat" ]]; then - # set temperature to midpoint of acceptable range - num=$(get_midrange $idx) - if [[ $zsettemp != $num ]]; then - thisaction="$thisaction set_temp:$num" - fi - # close the vent, if required - if [[ ${zstate[$idx]} != "close" ]]; then - thisaction="$thisaction close_vent" - elif [[ $donearby -eq 1 ]]; then - thisaction="close_nearby_zone" - fi - fi - fi - fi - zaction[$idx]="$thisaction" - profile "getzoneaction for idx ${zname[$idx]}" + # if we couldnt turn the system on, there's nothing else to do + if [[ $airconmode == "cool" ]]; then + # adjust set temperature, if required + if [[ $(echo "${zsettemp[$idx]} > ${zwantmax[$idx]}" | bc) -eq 1 || $(echo "${zsettemp[$idx]} < ${zwantmin[$idx]}" | bc) -eq 1 ]]; then + # set temperature to midpoint of acceptable range + num=$(get_midrange $idx) + if [[ $zsettemp != $num ]]; then + thisaction="$thisaction set_temp:$num" + fi + fi + # open the vent, if required + if [[ ${zstate[$idx]} != "open" ]]; then + thisaction="$thisaction open_vent" + fi + # set myzone, even if not required (will fix later) + thisaction="$thisaction set_myzone" + fi + elif [[ $airconmode == "heat" ]]; then + # set temperature to midpoint of acceptable range + num=$(get_midrange $idx) + if [[ $zsettemp != $num ]]; then + thisaction="$thisaction set_temp:$num" + fi + # close the vent, if required + if [[ ${zstate[$idx]} != "close" ]]; then + thisaction="$thisaction close_vent" + elif [[ $donearby -eq 1 ]]; then + thisaction="close_nearby_zone" + fi + fi + fi + fi + zaction[$idx]="$thisaction" + profile "getzoneaction for idx ${zname[$idx]}" } function getidxfromname() { # name - local x - for x in ${!zname[@]}; do - if [[ ${zname[$x]} == $1 ]]; then - echo "${x}" - fi - done + local x + for x in ${!zname[@]}; do + if [[ ${zname[$x]} == $1 ]]; then + echo "${x}" + fi + done } function getnamefromid() { # id - local x - for x in ${!zname[@]}; do - if [[ ${zid[$x]} == $1 ]]; then - echo "${zname[$x]}" - fi - done + local x + for x in ${!zname[@]}; do + if [[ ${zid[$x]} == $1 ]]; then + echo "${zname[$x]}" + fi + done } # getforcevent zone_name function getforcevent() { - local x retval - retval="" - for x in ${!fv_zonename[@]}; do - if [[ ${fv_zonename[$x]} == "$1" ]]; then - retval="${fv_state[$x]}" - break - fi - done - echo "$retval" + local x retval + retval="" + for x in ${!fv_zonename[@]}; do + if [[ ${fv_zonename[$x]} == "$1" ]]; then + retval="${fv_state[$x]}" + break + fi + done + echo "$retval" } # getalladj zone_name function getalladj() { - local x retval - retval="" - for x in ${!adj_zonename[@]}; do - if [[ ${adj_zonename[$x]} == "$1" ]]; then - retval="${adj_nearby[$x]}" - break - fi - done - echo "$retval" + local x retval + retval="" + for x in ${!adj_zonename[@]}; do + if [[ ${adj_zonename[$x]} == "$1" ]]; then + retval="${adj_nearby[$x]}" + break + fi + done + echo "$retval" } function find_nearby_zones() { # zone_idx filter1 filter2 ... filter is: open|closed|noaction - local idx thiszone nearbyzones allnearbyzones thisone zi ok db conditions - idx=$1 - shift - conditions="$*" - db=0 - if [[ $db -eq 1 ]]; then - echo "find_nearby_zones(): idx = $idx" >/dev/stderr - echo "find_nearby_zones(): conditions = [$conditions]" >/dev/stderr - fi - thiszone=${zname[$idx]} - allnearbyzones=$(getalladj ${thiszone}) - nearbyzones="" - if [[ $db -eq 1 ]]; then - echo "find_nearby_zones(): allnearbyzones = [$allnearbyzones]" >/dev/stderr - fi - for thisone in $allnearbyzones; do - ok=1 - zi=$(getidxfromname $thisone) - if [[ $conditions == *open* && ${zstate[$zi]} != "open" ]]; then - ok=0 - fi - if [[ $conditions == *closed* && ${zstate[$zi]} != "close" ]]; then - ok=0 - fi - if [[ $conditions == *noaction* && ${zaction[$zi]} != "n/a" ]]; then - ok=0 - fi - if [[ $ok -eq 1 ]]; then - nearbyzones="$nearbyzones $thisone" - fi - done - echo "$nearbyzones" + local idx thiszone nearbyzones allnearbyzones thisone zi ok db conditions + idx=$1 + shift + conditions="$*" + db=0 + if [[ $db -eq 1 ]]; then + echo "find_nearby_zones(): idx = $idx" >/dev/stderr + echo "find_nearby_zones(): conditions = [$conditions]" >/dev/stderr + fi + thiszone=${zname[$idx]} + allnearbyzones=$(getalladj ${thiszone}) + nearbyzones="" + if [[ $db -eq 1 ]]; then + echo "find_nearby_zones(): allnearbyzones = [$allnearbyzones]" >/dev/stderr + fi + for thisone in $allnearbyzones; do + ok=1 + zi=$(getidxfromname $thisone) + if [[ $conditions == *open* && ${zstate[$zi]} != "open" ]]; then + ok=0 + fi + if [[ $conditions == *closed* && ${zstate[$zi]} != "close" ]]; then + ok=0 + fi + if [[ $conditions == *noaction* && ${zaction[$zi]} != "n/a" ]]; then + ok=0 + fi + if [[ $ok -eq 1 ]]; then + nearbyzones="$nearbyzones $thisone" + fi + done + echo "$nearbyzones" } function generate_actions() { # populates global: nairconcommands & airconcmd[] - local x y z adj tempstr nhot ncold - local powerchange nmyzones maxpri bestidx - local globaction mzmustmove poss nomyzone - local db - db=0 + local x y z adj tempstr nhot ncold + local powerchange nmyzones maxpri bestidx + local globaction mzmustmove poss nomyzone + local db + db=0 - nairconcommands=0 - powerchange="" + nairconcommands=0 + powerchange="" - for x in ${!zname[@]}; do - getzoneaction $x - done + for x in ${!zname[@]}; do + getzoneaction $x + done - # pass 1 - profile "pass 1 start" - for x in ${!zname[@]}; do - thisaction="${zaction[$x]}" - IFS=' ' read -ra tok <<< "${zaction[$x]}" - for y in ${!tok[@]}; do - if [[ ${tok[$y]} == "close_nearby_zone" ]]; then - # is there a nearby zone that's open? - adj=$(find_nearby_zones $x open noaction) - if [[ -z $adj ]]; then - zaction[$x]="power_off" - if [[ -z $powerchange ]]; then - powerchange="power_off" - elif [[ ${zaction[$x]} != $powerchange ]]; then - zactionfail[$x]=1 - fi - else - tempstr="" - for z in $adj; do - tempstr="$tempstr close:$z" - done - zaction[$x]="${zaction[$x]/close_nearby_zone/$tempstr}" - fi - fi - done - done + # pass 1 + profile "pass 1 start" + for x in ${!zname[@]}; do + thisaction="${zaction[$x]}" + IFS=' ' read -ra tok <<< "${zaction[$x]}" + for y in ${!tok[@]}; do + if [[ ${tok[$y]} == "close_nearby_zone" ]]; then + # is there a nearby zone that's open? + adj=$(find_nearby_zones $x open noaction) + if [[ -z $adj ]]; then + zaction[$x]="power_off" + if [[ -z $powerchange ]]; then + powerchange="power_off" + elif [[ ${zaction[$x]} != $powerchange ]]; then + zactionfail[$x]=1 + fi + else + tempstr="" + for z in $adj; do + tempstr="$tempstr close:$z" + done + zaction[$x]="${zaction[$x]/close_nearby_zone/$tempstr}" + fi + fi + done + done - # pass 2 - If multiple zones are too hot/cold, turn the whole system off/on (if off, replace all actions) - nhot=0 - ncold=0 - for x in ${!zname[@]}; do - if [[ -z $powerchange ]]; then - if [[ ${zproblem[$x]} == "too_hot" ]]; then - nhot=$((nhot + 1)) - elif [[ ${zproblem[$x]} == "too_cold" ]]; then - ncold=$((ncold + 1)) - fi - fi - done + # pass 2 - If multiple zones are too hot/cold, turn the whole system off/on (if off, replace all actions) + nhot=0 + ncold=0 + for x in ${!zname[@]}; do + if [[ -z $powerchange ]]; then + if [[ ${zproblem[$x]} == "too_hot" ]]; then + nhot=$((nhot + 1)) + elif [[ ${zproblem[$x]} == "too_cold" ]]; then + ncold=$((ncold + 1)) + fi + fi + done - globsetmode="" - globprob="" - if [[ $airconmode == "off" ]]; then - # aircon is off - if [[ $ncold -ge $limit ]]; then - globprob="too_cold" - if [[ $modelock == "n/a" || $modelock == "heat" ]]; then - globsetmode=" set_mode:heat" - fi - elif [[ $nhot -ge $limit ]]; then - globprob="too_hot" - if [[ $modelock == "n/a" || $modelock == "cool" ]]; then - globsetmode=" set_mode:cool" - fi - fi - [[ ! -z $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" - fi - [[ ! -z $globprob ]] && globaction="power_off" - fi - if [[ ! -z $globprob ]]; then - for x in ${!zname[@]}; do - if [[ ${zproblem[$x]} == $globprob && ${zaction[$x]} != *${globaction}* ]]; then - zaction[$x]="$globaction$globsetmode ${zaction[$x]}" - zactionfail[$x]=0 - elif [[ ${globaction} == "power_off" && ${zaction[$x]} != *$globaction* ]]; then - zactionfail[$x]=1 - fi - done - fi + globsetmode="" + globprob="" + if [[ $airconmode == "off" ]]; then + # aircon is off + if [[ $ncold -ge $limit ]]; then + globprob="too_cold" + if [[ $modelock == "n/a" || $modelock == "heat" ]]; then + globsetmode=" set_mode:heat" + fi + elif [[ $nhot -ge $limit ]]; then + globprob="too_hot" + if [[ $modelock == "n/a" || $modelock == "cool" ]]; then + globsetmode=" set_mode:cool" + fi + fi + [[ ! -z $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" + fi + [[ ! -z $globprob ]] && globaction="power_off" + fi + if [[ ! -z $globprob ]]; then + for x in ${!zname[@]}; do + if [[ ${zproblem[$x]} == $globprob && ${zaction[$x]} != *${globaction}* ]]; then + zaction[$x]="$globaction$globsetmode ${zaction[$x]}" + zactionfail[$x]=0 + elif [[ ${globaction} == "power_off" && ${zaction[$x]} != *$globaction* ]]; then + zactionfail[$x]=1 + fi + done + fi - # pass xx - if we're closing the constant zone, and it's NOT the myzone, - # just turn the whole system off (since it will probably be opened. - # again anyway). - if [[ -z $powerchange && $airconmode != "off" ]]; then - for x in ${!zname[@]}; do - if [[ ${zaction[$x]} == *close_vent* && $constant == ${zname[$x]} ]]; then - if [[ $airconmyzoneid != ${zid[$x]} ]]; then - zaction[$x]="power_off" - [[ -z $powerchange ]] && powerchange="power_off" - fi - fi - done - fi + # pass xx - if we're closing the constant zone, and it's NOT the myzone, + # just turn the whole system off (since it will probably be opened. + # again anyway). + if [[ -z $powerchange && $airconmode != "off" ]]; then + for x in ${!zname[@]}; do + if [[ ${zaction[$x]} == *close_vent* && $constant == ${zname[$x]} ]]; then + if [[ $airconmyzoneid != ${zid[$x]} ]]; then + zaction[$x]="power_off" + [[ -z $powerchange ]] && powerchange="power_off" + fi + fi + done + fi - # pass 3 - If we're powering the whole system on/off, don't do anything else - if [[ ! -z $powerchange ]]; then - for x in ${!zname[@]}; do - if [[ ${powerchange} == "power_off" && ${zaction[$x]} != $powerchange ]]; then - zactionfail[$x]=1 - fi - done - fi + # pass 3 - If we're powering the whole system on/off, don't do anything else + if [[ ! -z $powerchange ]]; then + for x in ${!zname[@]}; do + if [[ ${powerchange} == "power_off" && ${zaction[$x]} != $powerchange ]]; then + zactionfail[$x]=1 + fi + done + fi - # pass xx - if we're closing the myzone, pick a new one + # pass xx - if we're closing the myzone, pick a new one [[ $db -eq 1 ]] && info "pass 3 - powerchange is '$powerchange'" - if [[ -z $powerchange ]]; then - if [[ $airconmode != "off" ]]; then - mzmustmove=0 + if [[ -z $powerchange ]]; then + if [[ $airconmode != "off" ]]; then + mzmustmove=0 # get list of all zones which can't be myzone - nomyzone="" - for x in ${!zname[@]}; do + nomyzone="" + for x in ${!zname[@]}; do 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 - mzmustmove=1 - elif [[ ${zaction[@]} == *close:${zname[$x]}* ]]; then - mzmustmove=1 - elif [[ ${znomyzone[$x]} -eq 1 ]]; then - mzmustmove=1 - fi - if [[ $mzmustmove -eq 1 ]]; then + for x in ${!zname[@]}; do + if [[ $airconmyzoneid == ${zid[$x]} || ${zaction[$x]} == *set_myzone* ]]; then + if [[ ${zstate[$x]} == "close" || ${zaction[$x]} == *close_vent* ]]; then + mzmustmove=1 + elif [[ ${zaction[@]} == *close:${zname[$x]}* ]]; then + mzmustmove=1 + elif [[ ${znomyzone[$x]} -eq 1 ]]; then + mzmustmove=1 + fi + if [[ $mzmustmove -eq 1 ]]; then [[ $db -eq 1 ]] && info "myzone must move away from ${zname[$x]}" - #info "myzone must move away from ${zname[$x]}" - zaction[$x]="${zaction[$x]/set_myzone/}" - nomyzone="$nomyzone ${zname[$x]} " + #info "myzone must move away from ${zname[$x]}" + zaction[$x]="${zaction[$x]/set_myzone/}" + nomyzone="$nomyzone ${zname[$x]} " [[ $db -eq 1 ]] && info "zaction[${zname[$z]} is '${zaction[$x]}'" [[ $db -eq 1 ]] && info "nomyzone is '$nomyzone}'" - fi - fi - done - if [[ $mzmustmove -eq 1 ]]; then + fi + fi + done + if [[ $mzmustmove -eq 1 ]]; then [[ $db -eq 1 ]] && info "got mzmustmove == 1" [[ $db -eq 1 ]] && info "FINAL nomyzone is '$nomyzone}'" - # find an alternative - for x in ${!zname[@]}; do - # open or opening? set myzone. we'll resolve - # duplicates in the next step. + # find an alternative + for x in ${!zname[@]}; do + # open or opening? set myzone. we'll resolve + # duplicates in the next step. [[ $db -eq 1 ]] && info " checking if we can move mz to ${zname[$x]}" - poss=0 - if [[ ${zaction[$x]} != *set_myzone* && $nomyzone != *\ ${zname[$x]}\ * ]]; then + poss=0 + if [[ ${zaction[$x]} != *set_myzone* && $nomyzone != *\ ${zname[$x]}\ * ]]; then [[ $db -eq 1 ]] && info " not already moving mz here + not in nomyzone list" - if [[ ${zstate[$x]} == "open" || ${zaction[$x]} == *open_vent* ]]; then + if [[ ${zstate[$x]} == "open" || ${zaction[$x]} == *open_vent* ]]; then [[ $db -eq 1 ]] && info " is open or opening -> OK" - poss=1 - elif [[ ${zaction[@]} == *open:${zname[$x]}* ]]; then + poss=1 + elif [[ ${zaction[@]} == *open:${zname[$x]}* ]]; then [[ $db -eq 1 ]] && info " is opening via adjacency-> OK" - poss=1 - fi - if [[ $poss -eq 1 ]]; then + poss=1 + fi + if [[ $poss -eq 1 ]]; then [[ $db -eq 1 ]] && info " myzone could move to ${zname[$x]}" - #info " myzone could move to ${zname[$x]}" - zaction[$x]="${zaction[$x]} set_myzone" + #info " myzone could move to ${zname[$x]}" + zaction[$x]="${zaction[$x]} set_myzone" [[ $db -eq 1 ]] && info " new zaction[${zname[$x]}] is ${zaction[x]}" - fi - fi - done - fi - fi - fi + fi + fi + done + fi + fi + fi - # pass 4 - multiple myzones? - if [[ -z $powerchange ]]; then - nmyzones=0 - maxpri=-999 - bestidx=-1 - for x in ${!zname[@]}; do - # Multiple myzones? - if [[ ${zaction[$x]} == *set_myzone* ]]; then - #info " ${zname[$x]} wants myzone (pri=${zpri[$x]} maxpri=$maxpri)" - nmyzones=$((nmyzones + 1)) - if [[ $(echo "scale=1; ${zpri[$x]} > $maxpri" | bc) == "1" ]]; then - bestidx=$x - maxpri=$(echo "scale=1; ${zpri[$x]}" | bc) - #info " new best priority: ${zname[$x]} = $maxpri" - fi - fi - done - if [[ $nmyzones -gt 1 ]]; then - for x in ${!zname[@]}; do - if [[ $x -ne $bestidx && ${zaction[$x]} == *set_myzone* ]]; then - zaction[$x]="${zaction[$x]/set_myzone/}" - fi - done - fi - fi + # pass 4 - multiple myzones? + if [[ -z $powerchange ]]; then + nmyzones=0 + maxpri=-999 + bestidx=-1 + for x in ${!zname[@]}; do + # Multiple myzones? + if [[ ${zaction[$x]} == *set_myzone* ]]; then + #info " ${zname[$x]} wants myzone (pri=${zpri[$x]} maxpri=$maxpri)" + nmyzones=$((nmyzones + 1)) + if [[ $(echo "scale=1; ${zpri[$x]} > $maxpri" | bc) == "1" ]]; then + bestidx=$x + maxpri=$(echo "scale=1; ${zpri[$x]}" | bc) + #info " new best priority: ${zname[$x]} = $maxpri" + fi + fi + done + if [[ $nmyzones -gt 1 ]]; then + for x in ${!zname[@]}; do + if [[ $x -ne $bestidx && ${zaction[$x]} == *set_myzone* ]]; then + zaction[$x]="${zaction[$x]/set_myzone/}" + fi + done + fi + fi - # final pass - for x in ${!zname[@]}; do - if [[ ${zactionfail[$x]} -eq 0 ]]; then - # Remove myzone if already set - if [[ ${zaction[$x]} == *set_myzone* && $airconmyzoneid == ${zid[x]} ]]; then - zaction[$x]="${zaction[$x]/set_myzone/}" - fi + # final pass + for x in ${!zname[@]}; do + if [[ ${zactionfail[$x]} -eq 0 ]]; then + # Remove myzone if already set + if [[ ${zaction[$x]} == *set_myzone* && $airconmyzoneid == ${zid[x]} ]]; then + zaction[$x]="${zaction[$x]/set_myzone/}" + fi - # Remove leading spaces - zaction[$x]=$(echo ${zaction[$x]} | awk '{$1=$1; sub("n/a ",""); sub(" n/a","") };1') - # Generate actual aircon commands from zone commands - gen_aircon_command ${x} ${zaction[$x]} - fi - done + # Remove leading spaces + zaction[$x]=$(echo ${zaction[$x]} | awk '{$1=$1; sub("n/a ",""); sub(" n/a","") };1') + # Generate actual aircon commands from zone commands + gen_aircon_command ${x} ${zaction[$x]} + fi + done } # 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 - idx=$1 - shift - allactions="$*" - doneset=0 - donemode=0 + local idx allactions this toadd num doneset othername otherid otheridx db donemode str + idx=$1 + shift + allactions="$*" + doneset=0 + donemode=0 - db=0 - [[ $db -eq 1 ]] && info "gen_aircon_command() for idx=${idx}: $allactions" + db=0 + [[ $db -eq 1 ]] && info "gen_aircon_command() for idx=${idx}: $allactions" - IFS=' ' read -ra tok <<< "${allactions}" - for this in ${tok[@]}; do - if [[ $this == *power_on* ]]; then - add_aircon_command $idx -1 "Power on system" "on" - elif [[ $this == *power_off* ]]; then - add_aircon_command $idx -1 "Power off system" "off" - elif [[ $this == *set_myzone* && $airconmyzoneid != ${zid[$idx]} ]]; then - add_aircon_command $idx -1 "Set MyZone to ${zname[$idx]}" "myzone --zone ${zid[$idx]}" - elif [[ $this == *open:* ]]; then - 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 - othername=$(echo "$this" | sed -e 's/^.*close://;s/ .*//') - otheridx=$(getidxfromname $othername) - otherid=${zid[$otheridx]} - add_aircon_command $idx $otheridx "Close vent in ${zname[$otheridx]}" "set --zone ${otherid} --state off --temp ${zsettemp[$otheridx]}" - elif [[ $this == *set_mode:* ]]; then - 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 - if [[ $doneset -eq 0 ]]; then - toadd="" - comm="" - if [[ $allactions == *open_vent* ]]; then - toadd="$toadd --state on" - comm="open vent" - elif [[ $allactions == *close_vent* ]]; then - toadd="$toadd --state off" - comm="close vent" - fi - if [[ $allactions == *set_temp* ]]; then - num=$(echo "$this" | sed -e 's/^.*set_temp://;s/ .*//') - toadd="$toadd --temp $num" - [[ ! -z $comm ]] && comm="${comm} and " - comm="${comm}set temperature to $num degrees" - else - toadd="$toadd --temp ${zsettemp[$idx]}" - fi - if [[ ! -z $toadd ]]; then - add_aircon_command $idx -1 "In zone ${zname[$idx]}, $comm" "set --zone ${zid[$idx]}$toadd" - doneset=1 - fi - fi - fi - done + IFS=' ' read -ra tok <<< "${allactions}" + for this in ${tok[@]}; do + if [[ $this == *power_on* ]]; then + add_aircon_command $idx -1 "Power on system" "on" + elif [[ $this == *power_off* ]]; then + add_aircon_command $idx -1 "Power off system" "off" + elif [[ $this == *set_myzone* && $airconmyzoneid != ${zid[$idx]} ]]; then + add_aircon_command $idx -1 "Set MyZone to ${zname[$idx]}" "myzone --zone ${zid[$idx]}" + elif [[ $this == *open:* ]]; then + 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 + othername=$(echo "$this" | sed -e 's/^.*close://;s/ .*//') + otheridx=$(getidxfromname $othername) + otherid=${zid[$otheridx]} + add_aircon_command $idx $otheridx "Close vent in ${zname[$otheridx]}" "set --zone ${otherid} --state off --temp ${zsettemp[$otheridx]}" + elif [[ $this == *set_mode:* ]]; then + 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 + if [[ $doneset -eq 0 ]]; then + toadd="" + comm="" + if [[ $allactions == *open_vent* ]]; then + toadd="$toadd --state on" + comm="open vent" + elif [[ $allactions == *close_vent* ]]; then + toadd="$toadd --state off" + comm="close vent" + fi + if [[ $allactions == *set_temp* ]]; then + num=$(echo "$this" | sed -e 's/^.*set_temp://;s/ .*//') + toadd="$toadd --temp $num" + [[ ! -z $comm ]] && comm="${comm} and " + comm="${comm}set temperature to $num degrees" + else + toadd="$toadd --temp ${zsettemp[$idx]}" + fi + if [[ ! -z $toadd ]]; then + add_aircon_command $idx -1 "In zone ${zname[$idx]}, $comm" "set --zone ${zid[$idx]}$toadd" + doneset=1 + fi + fi + fi + done } # add_aircon_command zone_idx "comment goes here" "actual pymyair command to run" function add_aircon_command() { - local x idx otheridx comment db + local x idx otheridx comment db - [[ $# -le 1 ]] && return 1 + [[ $# -le 1 ]] && return 1 - idx=$1 - shift - otheridx=$1 - shift - comment=$1 - shift + idx=$1 + shift + otheridx=$1 + shift + comment=$1 + shift - if [[ $otheridx -ne -1 ]]; then - if [[ ! -z $comment ]]; then - comment="${comment} (to fix ${zname[$idx]})" - fi - fi + if [[ $otheridx -ne -1 ]]; then + if [[ ! -z $comment ]]; then + comment="${comment} (to fix ${zname[$idx]})" + fi + fi - db=0 - [[ $db -eq 1 ]] && info " add_aircon_command() for idx=${idx} otheridx=${otheridx} comment=[$comment]: $*" >/dev/stderr + db=0 + [[ $db -eq 1 ]] && info " add_aircon_command() for idx=${idx} otheridx=${otheridx} comment=[$comment]: $*" >/dev/stderr - [[ -z $* ]] && return 1 + [[ -z $* ]] && return 1 - for x in ${airconcmd[@]}; do - if [[ $x == "$*" ]]; then - return 1 - fi - done - airconcmd[$nairconcommands]="$*" - airconcomment[$nairconcommands]="$comment" - airconcmdzone[$nairconcommands]="${zname[$idx]}" - airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}" - airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }" - #if [[ $otheridx -ne -1 ]]; then - # airconcomment[$nairconcommands]="${airconcomment[$nairconcommands]}, update nearby zone ${zname[$otheridx]}" - #fi - nairconcommands=$((nairconcommands + 1)) - return 0 + for x in ${airconcmd[@]}; do + if [[ $x == "$*" ]]; then + return 1 + fi + done + airconcmd[$nairconcommands]="$*" + airconcomment[$nairconcommands]="$comment" + airconcmdzone[$nairconcommands]="${zname[$idx]}" + airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}" + airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }" + #if [[ $otheridx -ne -1 ]]; then + # airconcomment[$nairconcommands]="${airconcomment[$nairconcommands]}, update nearby zone ${zname[$otheridx]}" + #fi + nairconcommands=$((nairconcommands + 1)) + return 0 } function addnoop() { - local idx - idx=$(getidxfromname "$1") - zignore[$idx]=1 + local idx + idx=$(getidxfromname "$1") + zignore[$idx]=1 } function addnomyzone() { - local idx - idx=$(getidxfromname "$1") - znomyzone[$idx]=1 + local idx + idx=$(getidxfromname "$1") + znomyzone[$idx]=1 } function addforcevent() { - local x idx - idx=$nforcevents - for x in ${!fv_zonename[@]}; do - if [[ ${fv_zonename[$x]} == "$1" ]]; then - idx=$x - break; - fi - done - fv_zonename[$idx]="$1" - fv_state[$idx]="$2" - [[ $idx == $nforcevents ]] && nforcevents=$((nforcevents + 1)) + local x idx + idx=$nforcevents + for x in ${!fv_zonename[@]}; do + if [[ ${fv_zonename[$x]} == "$1" ]]; then + idx=$x + break; + fi + done + fv_zonename[$idx]="$1" + fv_state[$idx]="$2" + [[ $idx == $nforcevents ]] && nforcevents=$((nforcevents + 1)) } function addtemprange() { - local x idx - idx=$ntempranges - for x in ${!tr_zonename[@]}; do - if [[ ${tr_zonename[$x]} == "$1" ]]; then - idx=$x - break; - fi - done - tr_zonename[$idx]="$1" - tr_range[$idx]="$2" - [[ $idx == $ntempranges ]] && ntempranges=$((ntempranges + 1)) + local x idx + idx=$ntempranges + for x in ${!tr_zonename[@]}; do + if [[ ${tr_zonename[$x]} == "$1" ]]; then + idx=$x + break; + fi + done + tr_zonename[$idx]="$1" + tr_range[$idx]="$2" + [[ $idx == $ntempranges ]] && ntempranges=$((ntempranges + 1)) } function addadj() { - local name - name="$1" - shift - adj_zonename[$nadj]="$name" - adj_nearby[$nadj]="$*" - nadj=$((nadj + 1)) + local name + name="$1" + shift + adj_zonename[$nadj]="$name" + adj_nearby[$nadj]="$*" + nadj=$((nadj + 1)) } function addperson() { - local h p x idx db - db=0 + local h p x idx db + db=0 - p="$1" - shift - h="$*" + p="$1" + shift + h="$*" - [[ $db -eq 1 ]] && info "addperson() person $p host(s) [$h]" + [[ $db -eq 1 ]] && info "addperson() person $p host(s) [$h]" - idx=$npeople - for x in ${!pname[@]}; do - if [[ ${pname[$x]} == "$p" ]]; then - [[ $db -eq 1 ]] && info " owner already exists, appending." - idx=$x - break; - fi - done - pname[$idx]="$p" - if [[ ${pdev[$idx]} != *\ $h\ * ]]; then - pdev[$idx]="${pdev[$idx]} $h " - fi - [[ $db -eq 1 ]] && info " dev val is: ${pdev[$idx]}" - [[ $idx == $npeople ]] && npeople=$((npeople + 1)) + idx=$npeople + for x in ${!pname[@]}; do + if [[ ${pname[$x]} == "$p" ]]; then + [[ $db -eq 1 ]] && info " owner already exists, appending." + idx=$x + break; + fi + done + pname[$idx]="$p" + if [[ ${pdev[$idx]} != *\ $h\ * ]]; then + pdev[$idx]="${pdev[$idx]} $h " + fi + [[ $db -eq 1 ]] && info " dev val is: ${pdev[$idx]}" + [[ $idx == $npeople ]] && npeople=$((npeople + 1)) } function addowner() { - local z h local x idx db - db=0 + local z h local x idx db + db=0 - z="$1" - shift - h="$*" + z="$1" + shift + h="$*" - [[ $db -eq 1 ]] && info "addowner() zone $z host(s) [$h]" + [[ $db -eq 1 ]] && info "addowner() zone $z host(s) [$h]" - idx=$nowners - for x in ${!ownerzone[@]}; do - if [[ ${ownerzone[$x]} == "$z" ]]; then - [[ $db -eq 1 ]] && info " owner already exists, appending." - idx=$x - break; - fi - done - ownerzone[$idx]="$z" - if [[ ${ownerhost[$idx]} != *\ $h\ * ]]; then - ownerhost[$idx]="${ownerhost[$idx]} $h " - fi - [[ $db -eq 1 ]] && info " hosts val is: ${ownerhost[$idx]}" - [[ $idx == $nowners ]] && nowners=$((nowners + 1)) + idx=$nowners + for x in ${!ownerzone[@]}; do + if [[ ${ownerzone[$x]} == "$z" ]]; then + [[ $db -eq 1 ]] && info " owner already exists, appending." + idx=$x + break; + fi + done + ownerzone[$idx]="$z" + if [[ ${ownerhost[$idx]} != *\ $h\ * ]]; then + ownerhost[$idx]="${ownerhost[$idx]} $h " + fi + [[ $db -eq 1 ]] && info " hosts val is: ${ownerhost[$idx]}" + [[ $idx == $nowners ]] && nowners=$((nowners + 1)) } # getownerperson zone_name # returns name of person who owns zone function getownerperson() { - local x retval - retval="" - for x in ${!ownerzone[@]}; do - if [[ ${ownerzone[$x]} == "$1" ]]; then - retval="${ownerperson[$x]}" - break - fi - done - echo "$retval" + local x retval + retval="" + for x in ${!ownerzone[@]}; do + if [[ ${ownerzone[$x]} == "$1" ]]; then + retval="${ownerperson[$x]}" + break + fi + done + echo "$retval" } # getowner zone_name # returns devices associated woth zone function getowner() { - local x retval - retval="" - for x in ${!ownerzone[@]}; do - if [[ ${ownerzone[$x]} == "$1" ]]; then - retval="${ownerhost[$x]}" - break - fi - done - echo "$retval" + local x retval + retval="" + for x in ${!ownerzone[@]}; do + if [[ ${ownerzone[$x]} == "$1" ]]; then + retval="${ownerhost[$x]}" + break + fi + done + echo "$retval" } # gettemprange zone_name function gettemprange() { - local x retval - retval="n/a" - for x in ${!tr_zonename[@]}; do - if [[ ${tr_zonename[$x]} == "$1" ]]; then - retval="${tr_range[$x]}" - break - fi - done - echo "$retval" + local x retval + retval="n/a" + for x in ${!tr_zonename[@]}; do + if [[ ${tr_zonename[$x]} == "$1" ]]; then + retval="${tr_range[$x]}" + break + fi + done + echo "$retval" } function getstrtype() { - local strtype - shopt -s nocasematch - strtype=unknown - if [[ "$*" =~ ^[0-9]{4}$ ]]; then - strtype="24h" - elif [[ "$*" =~ ^(mon|tue|wed|thu|fri|sat|sun)$ ]]; then - strtype="weekday" - fi - shopt -u nocasematch - echo "$strtype" + local strtype + shopt -s nocasematch + strtype=unknown + if [[ "$*" =~ ^[0-9]{4}$ ]]; then + strtype="24h" + elif [[ "$*" =~ ^(mon|tue|wed|thu|fri|sat|sun)$ ]]; then + strtype="weekday" + fi + shopt -u nocasematch + echo "$strtype" } -function numtoweekday() { - local num - shopt -s nocasematch - num=-1 - case "$1" in - "mon") num=1;; - "tue") num=2;; - "wed") num=3;; - "thu") num=4;; - "fri") num=5;; - "sat") num=6;; - "sun") num=7;; - esac - shopt -u nocasematch - echo "$num" +function weekdaytonum() { + local num + shopt -s nocasematch + num=-1 + case "$1" in + "mon") num=1;; + "tue") num=2;; + "wed") num=3;; + "thu") num=4;; + "fri") num=5;; + "sat") num=6;; + "sun") num=7;; + esac + shopt -u nocasematch + echo "$num" } function conderror() { - error "Invalid condition: $1" - echo -e "${RED} Start: $2" - echo -e "${RED} End: $3" + error "Invalid condition: $1" + echo -e "${RED} Start: $2" + echo -e "${RED} End: $3" } function load_config() { - local line rv timestr ttok stype ok starth endh nowh - local cond allconds x - local db - db=0 - rv=0 - while read line; do - line=${line%%#*} # remove comments - if [[ ! -z ${line// } ]]; then - # time based options - if [[ ${line:0:1} == "@" ]]; then - timestr=${line%% *} - timestr=${timestr:1} - IFS=';' read -ra allconds <<< "$timestr" - for cond in ${allconds[@]} ; do - [[ $db -eq 1 ]] && info "Processing condition: '$cond'" - IFS='-' read -ra ttok <<< "$cond" - if [[ ${#ttok[@]} == 1 ]]; then - stype[0]=$(getstrtype ${ttok[0]}) - if [[ ${stype[0]} != "weekday" ]]; then - error "Invalid condition: '${cond}'" - return 1 - fi - starth=$(numtoweekday ${ttok[0]}) - if [[ $starth -eq -1 ]]; then - error "'${ttok[0]}' is not a valid type here (type is ${stype[0]})" + local line rv timestr ttok stype ok starth endh nowh + local cond allconds x + local db + parse_config || return 1 + db=0 + rv=0 + while read line; do + line=${line%%#*} # remove comments + if [[ -n ${line// } ]]; then + # time based options + if [[ ${line:0:1} == "@" ]]; then + processtimeconditions "$line" || ok=0 + if [[ $ok -eq 1 ]]; then + # strip condition off the front + line=${line#* } + fi + else + ok=1 + fi + if [[ $ok -eq 1 ]]; then + IFS=' ' read -ra tok <<< "$line" + if [[ ${tok[0]} == "temp" ]]; then + addtemprange ${tok[1]} ${tok[2]} + elif [[ ${tok[0]} == "constant" ]]; then + constant=${tok[1]} + elif [[ ${tok[0]} == "adj" ]]; then + addadj ${tok[1]} ${tok[@]:2} + elif [[ ${tok[0]} == "nomyzone" || ${tok[0]} == "nomy" ]]; then + addnomyzone ${tok[1]} + elif [[ ${tok[0]} == "noop" || ${tok[0]} == "ignore" ]]; then + addnoop ${tok[1]} + elif [[ ${tok[0]} == "force" ]]; then + addforcevent ${tok[1]} ${tok[2]} + elif [[ ${tok[0]} == "owner" ]]; then + addowner ${tok[1]} ${tok[@]:2} + elif [[ ${tok[0]} == "person" ]]; then + addperson ${tok[1]} ${tok[@]:2} + elif [[ ${tok[0]} == "modelock" ]]; then + modelock="${tok[1]}" + elif [[ ${tok[0]} == "test" ]]; then + info "Got test option: '${tok[@]}'" + rv=1 + fi + fi + fi + done < "$CONFIGFILE" + return $rv +} - return 1 - fi - endh="$starth" - nowh=$(date +%u) - else - stype[0]=$(getstrtype ${ttok[0]}) - stype[1]=$(getstrtype ${ttok[1]}) - starth="" - endh="" - nowh="" - if [[ ${stype[0]} != ${stype[1]} ]]; then - error "start and end condition types don't match:" - echo -e "${RED} Start: ${ttok[0]} (${stype[0]})${PLAIN}" - echo -e "${RED} End: ${ttok[1]} (${stype[1]})${PLAIN}" - return 1 - elif [[ ${stype[0]} == "24h" ]]; then - starth=${ttok[0]} - endh=${ttok[1]} - nowh=$(date +%H%M) - elif [[ ${stype[0]} == "weekday" ]]; then - starth=$(numtoweekday ${ttok[0]}) - endh=$(numtoweekday ${ttok[1]}) - if [[ $starth -eq -1 || $endh -eq -1 ]]; then - conderror "${cond}" "'${ttok[0]}' (${stype[0]})" "'${ttok[1]}' (${stype[1]})" +# pooulates global timestr_human, -c means keep going if we dont match +function processtimeconditions() { + local timestr line allconds cond + local ttok stype nowh starth endh + local this_human + local keepgoing=0 + local ok=0 + if [[ $1 == "-c" ]]; then + keepgoing=1 + shift 1 + fi + line="$*" + timestr_human="" - return 1 - fi - nowh=$(date +%u) - else - conderror "${cond}" "'${ttok[0]}' (${stype[0]})" "'${ttok[1]}' (${stype[1]})" - return 1 - fi - fi - if [[ ! -z $starth ]]; then - [[ $db -eq 1 ]] && info " check if $nowh is between $starth and $endh" - ok=0 - if [[ $(echo "$starth < $endh" | bc) == "1" ]]; then - if [[ $(echo "$nowh >= $starth" | bc) == "1" && $(echo "$nowh <= $endh" | bc) == "1" ]]; then - ok=1 - fi - elif [[ $(echo "$starth > $endh" | bc) == "1" ]]; then - if [[ $(echo "$nowh <= $endh" | bc) == "1" || $(echo "$nowh >= $starth" | bc) == "1" ]]; then - ok=1 - fi - else - if [[ $nowh == $endh || $nowh == $starth ]]; then - ok=1 - fi - fi - [[ $db -eq 1 && $ok -eq 0 ]] && info " $nowh isn't in range $cond" - [[ $db -eq 1 && $ok -eq 1 ]] && info " MATCH: $nowh within range $cond" - fi - if [[ $ok -eq 0 ]]; then - break - fi - done - if [[ $ok -eq 1 ]]; then - # strip condition off the front - line=${line#* } - fi - else - ok=1 - fi - if [[ $ok -eq 1 ]]; then - IFS=' ' read -ra tok <<< "$line" - if [[ ${tok[0]} == "temp" ]]; then - addtemprange ${tok[1]} ${tok[2]} - elif [[ ${tok[0]} == "constant" ]]; then - if [[ -z ${tok[1]} ]]; then - error "Missing zone name in constant command." - exit 1 - elif [[ -z $constant ]]; then - constant=${tok[1]} - else - error "Constant zone defined more than once." - exit 1 - fi - elif [[ ${tok[0]} == "adj" ]]; then - addadj ${tok[1]} ${tok[@]:2} - elif [[ ${tok[0]} == "nomyzone" || ${tok[0]} == "nomy" ]]; then - addnomyzone ${tok[1]} - elif [[ ${tok[0]} == "noop" || ${tok[0]} == "ignore" ]]; then - addnoop ${tok[1]} - elif [[ ${tok[0]} == "force" ]]; then - if [[ $VALID_ZONE_STATES == *\ ${tok[2]}\ * ]]; then - addforcevent ${tok[1]} ${tok[2]} - else - error "Invalid zone state '${tok[2]}'. Valid options are: $VALID_ZONE_STATES" - exit 1 - fi - elif [[ ${tok[0]} == "owner" ]]; then - addowner ${tok[1]} ${tok[@]:2} - elif [[ ${tok[0]} == "person" ]]; then - addperson ${tok[1]} ${tok[@]:2} - elif [[ ${tok[0]} == "modelock" ]]; then - if [[ $VALID_MODES == *\ ${tok[1]}\ * ]]; then - modelock="${tok[1]}" - else - error "Invalid modelock '${tok[1]}'. Valid options are: $VALID_MODES" - exit 1 - fi - elif [[ ${tok[0]} == "test" ]]; then - info "Got test option: '${tok[@]}'" - rv=1 - fi - fi + timestr=${line%% *} + timestr=${timestr:1} + IFS=';' read -ra allconds <<< "$timestr" + for cond in ${allconds[@]} ; do + [[ $db -eq 1 ]] && info "Processing condition: '$cond'" + IFS='-' read -ra ttok <<< "$cond" + if [[ ${#ttok[@]} == 1 ]]; then + stype[0]=$(getstrtype ${ttok[0]}) + if [[ ${stype[0]} != "weekday" ]]; then + error "Invalid condition: '${cond}'" + return 1 + fi + starth=$(weekdaytonum ${ttok[0]}) + if [[ $starth -eq -1 ]]; then + error "'${ttok[0]}' is not a valid type here (type is ${stype[0]})" - fi - done < "$CONFIGFILE" - return $rv + return 1 + fi + endh="$starth" + nowh=$(date +%u) + else + stype[0]=$(getstrtype ${ttok[0]}) + stype[1]=$(getstrtype ${ttok[1]}) + starth="" + endh="" + nowh="" + if [[ ${stype[0]} != ${stype[1]} ]]; then + error "start and end condition types don't match:" + echo -e "${RED} Start: ${ttok[0]} (${stype[0]})${PLAIN}" + echo -e "${RED} End: ${ttok[1]} (${stype[1]})${PLAIN}" + return 1 + elif [[ ${stype[0]} == "24h" ]]; then + starth=${ttok[0]} + endh=${ttok[1]} + nowh=$(date +%H%M) + + [[ -n $timestr_human ]] && this_human=" b" || this_human=B + this_human=$(printf "${this_human}etween _H_%02s:%02s_EH_ and _H_%02s:%02s_EH_" ${starth:0:2} ${starth:2:2} ${endh:0:2} ${endh:2:2}) + elif [[ ${stype[0]} == "weekday" ]]; then + starth=$(weekdaytonum ${ttok[0]}) + endh=$(weekdaytonum ${ttok[1]}) + if [[ $starth -eq -1 || $endh -eq -1 ]]; then + conderror "${cond}" "'${ttok[0]}' (${stype[0]})" "'${ttok[1]}' (${stype[1]})" + + return 1 + fi + nowh=$(date +%u) + if [[ ${ttok[1]} == ${ttok[2]} ]]; then + [[ -n $timestr_human ]] && this_human="o " || this_human=O + this_human=$(printf "${this_human}n _H_%ss_EH_" ${ttok[0]}) + else + [[ -n $timestr_human ]] && this_human=" f" || this_human=F + this_human=$(printf "${this_human}rom _H_%s_EH_ to _H_%s_EH_" ${ttok[0]} ${ttok[1]}) + fi + else + conderror "${cond}" "'${ttok[0]}' (${stype[0]})" "'${ttok[1]}' (${stype[1]})" + return 1 + fi + fi + if [[ ! -z $starth ]]; then + [[ $db -eq 1 ]] && info " check if $nowh is between $starth and $endh" + ok=0 + if [[ $(echo "$starth < $endh" | bc) == "1" ]]; then + if [[ $(echo "$nowh >= $starth" | bc) == "1" && $(echo "$nowh <= $endh" | bc) == "1" ]]; then + ok=1 + fi + elif [[ $(echo "$starth > $endh" | bc) == "1" ]]; then + if [[ $(echo "$nowh <= $endh" | bc) == "1" || $(echo "$nowh >= $starth" | bc) == "1" ]]; then + ok=1 + fi + else + if [[ $nowh == $endh || $nowh == $starth ]]; then + ok=1 + fi + fi + [[ $db -eq 1 && $ok -eq 0 ]] && info " $nowh isn't in range $cond" + [[ $db -eq 1 && $ok -eq 1 ]] && info " MATCH: $nowh within range $cond" + fi + timestr_human="${timestr_human}${this_human}" + if [[ $ok -eq 0 && $keepgoing -eq 0 ]]; then + break + fi + done + return $((1 - $ok)) +} + +function active_cols() { + inactc="$RED" + linec=${PLAIN} + devc="$GREEN" + devbc="$BOLD$devc" + statec="$BOLD$YELLOW" + roomc="$ORANGE" + timec="$PINK" + timebc="$BOLD$timec" + minc="$BOLD$BLUE" + maxc="$BOLD$RED" +} + +function inactive_cols() { + inactc="$DARKGREY" + linec="${inactc}" + devc="$inactc" + devbc="$inactc" + statec="$inactc" + roomc="$inactc" + timec="$inactc" + timebc="$inactc" + minc="$inactc" + maxc="$inactc" +} + +function parse_config() { + local line rv timestr ttok stype ok starth endh nowh + local cond allconds x + local db fileok=1 linenum show=0 + local config_human line_human errstr + + if [[ -n $1 ]]; then + show=$1 + fi + db=0 + rv=0 + config_human="" + errstr="" + linenum=1 + while read line; do + ok=1 + active_cols + line=${line%%#*} # remove comments + line_human="" + if [[ ! -z ${line// } ]]; then + # time based options + if [[ ${line:0:1} == "@" ]]; then + # strip condition off the front + processtimeconditions -c "$line" || ok=0 + [[ $ok -eq 0 ]] && inactive_cols + line=${line#* } + if [[ -n $timestr_human ]]; then + local modts + modts=${timestr_human//_H_/$timebc} + modts=${modts//_EH_/$linec$timec} + line_human="${timec}$modts${linec}, " + fi + fi + + IFS=' ' read -ra tok <<< "$line" + if [[ ${tok[0]} == "temp" ]]; then + local min max + min=${tok[2]%-*} + max=${tok[2]#*-} + line_human="${line_human}Keep temperature of ${roomc}${tok[1]}${linec} between ${minc}${min}${linec}-${maxc}${max}${linec} degrees" + elif [[ ${tok[0]} == "constant" ]]; then + true + elif [[ ${tok[0]} == "person" ]]; then + true + elif [[ ${tok[0]} == "adj" ]]; then + true + elif [[ ${tok[0]} == "nomyzone" || ${tok[0]} == "nomy" ]]; then + line_human="${line_human}Prevent ${roomc}${tok[1]}${linec} from being the MyZone" + elif [[ ${tok[0]} == "noop" || ${tok[0]} == "ignore" ]]; then + line_human="${line_human}Ignore ${roomc}${tok[1]}${linec} temperature when deciding what to do" + elif [[ ${tok[0]} == "force" ]]; then + if [[ $VALID_ZONE_STATES == *\ ${tok[2]}\ * ]]; then + local adj + adj="${tok[2]}" + [[ $adj != "open" ]] && adj="${adj}d" + line_human="${line_human}Force the vent in ${roomc}${tok[1]}${linec} to be ${statec}${adj}${linec}" + else + errstr="${errstr}${linenum}:Invalid zone state '${tok[2]}'. Valid options are: $VALID_ZONE_STATES\n" + fileok=0 + fi + elif [[ ${tok[0]} == "owner" ]]; then + local devices verb + devices="${devc}${tok[@]:2}${linec}" + devices="${devbc}[${linec}${devices}${devbc}]${linec}" + if [[ ${#tok[@]} -eq 3 ]]; then + verb="isn't" + else + verb="aren't" + fi + line_human="${line_human}${statec}Close${linec} vent in ${roomc}${tok[1]}${linec} if $devices $verb online" + elif [[ ${tok[0]} == "modelock" ]]; then + if [[ $VALID_MODES == *\ ${tok[1]}\ * ]]; then + local col + modelock="${tok[1]}" + [[ $modelock == "cool" ]] && col="$BOLD$CYAN" || col="$RED" + line_human="${line_human}Only operate the aircon in ${col}${tok[1]}${linec} mode" + else + errstr="${errstr}${linenum}:Invalid modelock '${tok[1]}'. Valid options are: $VALID_MODES\n" + fileok=0 + fi + elif [[ ${tok[0]} == "test" ]]; then + line_human="${line_human}Got test option '${roomc}${tok[1]}${linec}'" + elif [[ -n $line ]]; then + errstr="${errstr}${linenum}:Syntax error: ${line}\n" + fileok=0 + fi + fi + if [[ -n $line_human ]]; then + if [[ $ok -eq 0 ]]; then + line_human="${PLAIN}${inactc} ${linec}${line_human}" + fi + config_human="${config_human}- ${linec}${line_human}${PLAIN}\n" + fi + linenum=$((linenum + 1)) + done < "$CONFIGFILE" + + if [[ $fileok -eq 1 ]]; then + if [[ $show -eq 2 ]]; then + echo -e "${config_human}" + elif [[ $show -eq 1 ]]; then + info "Configuration file is ${BOLD}OK" + fi + rv=0 + else + error "Configuration file is invalid:" + echo -e "${RED}$errstr${PLAIN}" | sed -e 's/^/ /' + rv=1 + fi + return $rv } # if we can ping any of the args, return ok function canping() { - local ip db host thisrv mac - db=0 - for host in $*; do - ip=$(getent hosts $host | grep -v :) - ip=${ip%% *} - if [[ -z $ip ]]; then - thisrv=1 - else - #arp -d $ip >/dev/null 2>&1 - #ping -c1 -w1 -n -q $ip >/dev/null 2>&1 & - #sleep 0.3 - mac=$(arp -n $ip) - mac=$(echo "$mac" | egrep -v "Host|xpired" | awk '{print $2}') - [[ $mac == *:* ]] && thisrv=0 || thisrv=1 - fi - [[ $db -eq 1 ]] && info "canping() $host ($ip) is $thisrv - mac=$mac" - if [[ $thisrv -eq 0 ]]; then - return 0 - fi - done - return 1 + local ip db host thisrv mac + local os + os=$(uname -s) + db=0 + for host in $*; do + if [[ $os == "Darwin" ]]; then + ip=$(dscacheutil -q host -a name $host | grep ^ip_address: | awk '{ print $NF}') + else + ip=$(getent hosts $host | grep -v :) + fi + ip=${ip%% *} + if [[ -z $ip ]]; then + thisrv=1 + else + #arp -d $ip >/dev/null 2>&1 + #ping -c1 -w1 -n -q $ip >/dev/null 2>&1 & + #sleep 0.3 + mac=$(arp -n $ip) + mac=$(echo "$mac" | egrep -v "Host|xpired" | awk '{print $2}') + [[ $mac == *:* ]] && thisrv=0 || thisrv=1 + fi + [[ $db -eq 1 ]] && info "canping() $host ($ip) is $thisrv - mac=$mac" + if [[ $thisrv -eq 0 ]]; then + return 0 + fi + done + return 1 } function addzone() { - local name state settemp temp wanttemp wanttempmin wanttempmax id - name="$1" - state="$2" - settemp="$3" - temp="$4" - id="$5" - zname[$nzones]="$name" - zstate[$nzones]="$state" - zsettemp[$nzones]="$settemp" - ztemp[$nzones]="$temp" - zid[$nzones]="$id" - zwanttemp[$nzones]="n/a" - zproblem[$nzones]="n/a" - zaction[$nzones]="n/a" - zactionfail[$nzones]=0 - zowner[$nzones]=$(getowner "$name") - zownerperson[$nzones]=$(getownerperson "$name") - #info "zone $name owner is [${zowner[$nzones]}]" - zignore[$nzones]=0 - znomyzone[$nzones]=0 - zpri[$nzones]=0 - wanttemp=$(gettemprange "$name") - if [[ $wanttemp == "n/a" ]]; then - zwanttemp[$nzones]="n/a" - zwantmin[$nzones]="-99" - zwantmax[$nzones]="99" - else - zwanttemp[$nzones]="$wanttemp" - zwantmin[$nzones]="${wanttemp%-*}" - zwantmax[$nzones]="${wanttemp#*-}" - fi + local name state settemp temp wanttemp wanttempmin wanttempmax id + name="$1" + state="$2" + settemp="$3" + temp="$4" + id="$5" + zname[$nzones]="$name" + zstate[$nzones]="$state" + zsettemp[$nzones]="$settemp" + ztemp[$nzones]="$temp" + zid[$nzones]="$id" + zwanttemp[$nzones]="n/a" + zproblem[$nzones]="n/a" + zaction[$nzones]="n/a" + zactionfail[$nzones]=0 + zowner[$nzones]=$(getowner "$name") + zownerperson[$nzones]=$(getownerperson "$name") + #info "zone $name owner is [${zowner[$nzones]}]" + zignore[$nzones]=0 + znomyzone[$nzones]=0 + zpri[$nzones]=0 + wanttemp=$(gettemprange "$name") + if [[ $wanttemp == "n/a" ]]; then + zwanttemp[$nzones]="n/a" + zwantmin[$nzones]="-99" + zwantmax[$nzones]="99" + else + zwanttemp[$nzones]="$wanttemp" + zwantmin[$nzones]="${wanttemp%-*}" + zwantmax[$nzones]="${wanttemp#*-}" + fi - nzones=$((nzones + 1)) + nzones=$((nzones + 1)) } function getcol() { - local col - case $1 in - "off") col="$GREY";; - "cool") col="$CYAN";; - "heat") col="$RED";; - *) col="$PLAIN";; - esac - echo $col + local col + case $1 in + "off") col="$GREY";; + "cool") col="$CYAN";; + "heat") col="$RED";; + *) col="$PLAIN";; + esac + echo $col } function gen_config() { - local x - if [[ -e $CONFIGFILE ]]; then - error "$CONFIGFILE already exists" - return 1 - fi - get_aircon_info - cp /dev/null $CONFIGFILE - echo "# Specify commandline args here" >> $CONFIGFILE - echo "# options -p -t 0.3 ... " >> $CONFIGFILE - echo >> $CONFIGFILE - echo "# Don't switch to modes other than this" >> $CONFIGFILE - echo "#modelock heat|cool" >> $CONFIGFILE - echo >> $CONFIGFILE - echo "# Set temperature range to enforce" >> $CONFIGFILE - for x in ${!zname[@]}; do - echo "#temp ${zname[$x]} min_temp-max_temp" >> $CONFIGFILE - done - echo >> $CONFIGFILE - echo "# Turn off zone if we can't ARP for given hostname's IP" >> $CONFIGFILE - for x in ${!zname[@]}; do - echo "#owner ${zname[$x]} hostname.domain" >> $CONFIGFILE - done - echo >> $CONFIGFILE - echo "# Define which zones are adjacent to each other (used to close nearby" >> $CONFIGFILE - echo "# zones to help control temperature)" >> $CONFIGFILE - for x in ${!zname[@]}; do - echo "#adj ${zname[$x]} adjacent_zone1 [adjacent_zone2] ... [adjacent_zoneX]" >> $CONFIGFILE - done - echo >> $CONFIGFILE - echo "# Force a zone into a certain state" >> $CONFIGFILE - echo "#force ${zname[0]} open" >> $CONFIGFILE - echo "#force ${zname[1]} close" >> $CONFIGFILE - echo >> $CONFIGFILE - echo "# All commands except options can be restricted to certain times with:" >> $CONFIGFILE - echo "# @hhmm-hhmm Restrict between certain 24 hour times" >> $CONFIGFILE - echo "# @Mon-Wed Restrict between certain weekdays" >> $CONFIGFILE - echo "# @Mon Restrict to one weekdays only" >> $CONFIGFILE + local x + if [[ -e $CONFIGFILE ]]; then + error "$CONFIGFILE already exists" + return 1 + fi + get_aircon_info + cp /dev/null $CONFIGFILE + echo "# Specify commandline args here" >> $CONFIGFILE + echo "# options -p -t 0.3 ... " >> $CONFIGFILE + echo >> $CONFIGFILE + echo "# Don't switch to modes other than this" >> $CONFIGFILE + echo "#modelock heat|cool" >> $CONFIGFILE + echo >> $CONFIGFILE + echo "# Set temperature range to enforce" >> $CONFIGFILE + for x in ${!zname[@]}; do + echo "#temp ${zname[$x]} min_temp-max_temp" >> $CONFIGFILE + done + echo >> $CONFIGFILE + echo "# Turn off zone if we can't ARP for given hostname's IP" >> $CONFIGFILE + for x in ${!zname[@]}; do + echo "#owner ${zname[$x]} hostname.domain" >> $CONFIGFILE + done + echo >> $CONFIGFILE + echo "# Define which zones are adjacent to each other (used to close nearby" >> $CONFIGFILE + echo "# zones to help control temperature)" >> $CONFIGFILE + for x in ${!zname[@]}; do + echo "#adj ${zname[$x]} adjacent_zone1 [adjacent_zone2] ... [adjacent_zoneX]" >> $CONFIGFILE + done + echo >> $CONFIGFILE + echo "# Force a zone into a certain state" >> $CONFIGFILE + echo "#force ${zname[0]} open" >> $CONFIGFILE + echo "#force ${zname[1]} close" >> $CONFIGFILE + echo >> $CONFIGFILE + echo "# All commands except options can be restricted to certain times with:" >> $CONFIGFILE + echo "# @hhmm-hhmm Restrict between certain 24 hour times" >> $CONFIGFILE + echo "# @Mon-Wed Restrict between certain weekdays" >> $CONFIGFILE + echo "# @Mon Restrict to one weekdays only" >> $CONFIGFILE - echo "# @Mon;hhmm-hhmm Restrict both day and time" >> $CONFIGFILE - echo "# For example:" >> $CONFIGFILE - echo "# Keep zone closed on Tuesdays and Wednesdays" >> $CONFIGFILE - echo "#@Tue-Wed force ${zname[0]} close" >> $CONFIGFILE - echo "# Override temperature range between 11pm and 5am" >> $CONFIGFILE - echo "#@2300-0500 temp ${zname[0]} 20-21" >> $CONFIGFILE - echo "# Keep zone open between 10am and 11am on Mondays" >> $CONFIGFILE - echo "#@Mon;1000-1100 force ${zname[0]} open" >> $CONFIGFILE + echo "# @Mon;hhmm-hhmm Restrict both day and time" >> $CONFIGFILE + echo "# For example:" >> $CONFIGFILE + echo "# Keep zone closed on Tuesdays and Wednesdays" >> $CONFIGFILE + echo "#@Tue-Wed force ${zname[0]} close" >> $CONFIGFILE + echo "# Override temperature range between 11pm and 5am" >> $CONFIGFILE + echo "#@2300-0500 temp ${zname[0]} 20-21" >> $CONFIGFILE + echo "# Keep zone open between 10am and 11am on Mondays" >> $CONFIGFILE + echo "#@Mon;1000-1100 force ${zname[0]} open" >> $CONFIGFILE } function get_aircon_info() { - profile "query aircon" - [[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Querying aircon... ${PLAIN}" - zones=$(myair $AIRCON_IP zones | jq -r '.[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ') - airconmode=$(myair $AIRCON_IP mode) - nzones=0 - for line in $zones; do - IFS=',' read -ra tok <<< "$line" - addzone "${tok[0]}" "${tok[1]}" "${tok[2]}" "${tok[3]}" "${tok[4]}" - done - airconmyzoneid=$(myair $AIRCON_IP myzone) - airconmyzone=$(getnamefromid $airconmyzoneid) - [[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}" - profile "query aircon" + profile "query aircon" + [[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Querying aircon... ${PLAIN}" + zones=$(myair $AIRCON_IP zones | jq -r '.[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ') + airconmode=$(myair $AIRCON_IP mode) + nzones=0 + for line in $zones; do + IFS=',' read -ra tok <<< "$line" + addzone "${tok[0]}" "${tok[1]}" "${tok[2]}" "${tok[3]}" "${tok[4]}" + done + airconmyzoneid=$(myair $AIRCON_IP myzone) + airconmyzone=$(getnamefromid $airconmyzoneid) + [[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}" + profile "query aircon" } function show_aircon_status() { - local zonestr zonecol settempcol actioncol thiswantcol thisstate thisstateform - local thisformat x powercol lockcol - local FORMAT1 FORMAT2 FORMATHOT FORMATCOLD FORMATOK CLOSEDFORM OPENFORM + local zonestr zonecol settempcol actioncol thiswantcol thisstate thisstateform + local thisformat x powercol lockcol + local FORMAT1 FORMAT2 FORMATHOT FORMATCOLD FORMATOK CLOSEDFORM OPENFORM - FORMAT1="${BOLD}%-16s%-7s%-8s%-7s%-7s%s${PLAIN}" - FORMAT2="${UNDERLINE}${FORMAT1}${PLAIN}" - FORMATHOT="${RED}%-7s${PLAIN}" - FORMATCOLD="${CYAN}%-7s${PLAIN}" - FORMATOK="${WHITE}%-7s${PLAIN}" - CLOSEDFORM="$GREY%-8s$PLAIN" - OPENFORM="$PLAIN%-8s$PLAIN" + FORMAT1="${BOLD}%-16s%-7s%-8s%-7s%-7s%s${PLAIN}" + FORMAT2="${UNDERLINE}${FORMAT1}${PLAIN}" + FORMATHOT="${RED}%-7s${PLAIN}" + FORMATCOLD="${CYAN}%-7s${PLAIN}" + FORMATOK="${WHITE}%-7s${PLAIN}" + CLOSEDFORM="$GREY%-8s$PLAIN" + OPENFORM="$PLAIN%-8s$PLAIN" - powercol=$(getcol $airconmode) - lockcol=$(getcol $modelock) - printf "${BOLD}Aircon mode:${PLAIN} $powercol%s$PLAIN" $airconmode - if [[ $modelock != "n/a" ]]; then - echo -e " (locked to $lockcol$modelock$PLAIN)" - else - echo - fi - printf "${BOLD}Current myzone:${PLAIN} %s (zone %s)\n" $airconmyzone $airconmyzoneid - printf "${BOLD}Tolerance:${PLAIN} %s degrees low, %s degrees high" $tolerance_l $tolerance_h + powercol=$(getcol $airconmode) + lockcol=$(getcol $modelock) + printf "${BOLD}Aircon mode:${PLAIN} $powercol%s$PLAIN" $airconmode + if [[ $modelock != "n/a" ]]; then + echo -e " (locked to $lockcol$modelock$PLAIN)" + else + echo + fi + printf "${BOLD}Current myzone:${PLAIN} %s (zone %s)\n" $airconmyzone $airconmyzoneid + printf "${BOLD}Tolerance:${PLAIN} %s degrees low, %s degrees high" $tolerance_l $tolerance_h - echo + echo - printf "$FORMAT1\n" "" "Valid" "" "Set" "Actual" "Proposed " - printf "$FORMAT2\n" "Zone" "Temp" "State" "Temp" "Temp" "Action " - for x in ${!zname[@]}; do - if [[ ${zproblem[$x]} == "too_hot" ]]; then - thisformat="${FORMATHOT}" - elif [[ ${zproblem[$x]} == "too_cold" ]]; then - thisformat="${FORMATCOLD}" - else - thisformat="${FORMATOK}" - fi - if [[ ${airconmode} == "off" ]]; then - thisstateform="${CLOSEDFORM}" - thisstate="" - elif [[ ${zstate[$x]} == "close" ]]; then - thisstateform="${CLOSEDFORM}" - thisstate=${zstate[$x]} - else - thisstateform="${OPENFORM}" - thisstate=${zstate[$x]} - fi - thiswant="${zwanttemp[$x]}" - if [[ $thiswant == "n/a" ]]; then - thiswantcol="$GREY" - else - thiswantcol="$PLAIN" - fi - if [[ ${zactionfail[$x]} -eq 1 || ${zaction[$x]} == "n/a" ]]; then - actioncol="$GREY" - else - actioncol="$PLAIN" - fi + printf "$FORMAT1\n" "" "Valid" "" "Set" "Actual" "Proposed " + printf "$FORMAT2\n" "Zone" "Temp" "State" "Temp" "Temp" "Action " + for x in ${!zname[@]}; do + if [[ ${zproblem[$x]} == "too_hot" ]]; then + thisformat="${FORMATHOT}" + elif [[ ${zproblem[$x]} == "too_cold" ]]; then + thisformat="${FORMATCOLD}" + else + thisformat="${FORMATOK}" + fi + if [[ ${airconmode} == "off" ]]; then + thisstateform="${CLOSEDFORM}" + thisstate="" + elif [[ ${zstate[$x]} == "close" ]]; then + thisstateform="${CLOSEDFORM}" + thisstate=${zstate[$x]} + else + thisstateform="${OPENFORM}" + thisstate=${zstate[$x]} + fi + thiswant="${zwanttemp[$x]}" + if [[ $thiswant == "n/a" ]]; then + thiswantcol="$GREY" + else + thiswantcol="$PLAIN" + fi + if [[ ${zactionfail[$x]} -eq 1 || ${zaction[$x]} == "n/a" ]]; then + actioncol="$GREY" + else + actioncol="$PLAIN" + fi - if [[ ${airconmode} == "off" ]]; then - settempcol="$GREY" - else - settempcol="$PLAIN" - fi + if [[ ${airconmode} == "off" ]]; then + settempcol="$GREY" + else + settempcol="$PLAIN" + fi - if [[ $airconmyzoneid == ${zid[$x]} ]]; then - zonecol="$WHITE$BOLD" - zonestr="${zname[$x]} (M)" - else - zonecol="$PLAIN" - zonestr="${zname[$x]}" - fi - if [[ $constant == ${zname[$x]} ]]; then - zonestr="${zname[$x]} (C)" - fi + if [[ $airconmyzoneid == ${zid[$x]} ]]; then + zonecol="$WHITE$BOLD" + zonestr="${zname[$x]} (M)" + else + zonecol="$PLAIN" + zonestr="${zname[$x]}" + fi + if [[ $constant == ${zname[$x]} ]]; then + zonestr="${zname[$x]} (C)" + fi - printf "$zonecol%-16s$PLAIN$thiswantcol%-7s$PLAIN$thisstateform$settempcol%-7s$PLAIN$thisformat$actioncol%s$PLAIN\n" "${zonestr}" "${thiswant}" "${thisstate}" "${zsettemp[$x]}" "${ztemp[$x]}" "${zaction[$x]}" - done + printf "$zonecol%-16s$PLAIN$thiswantcol%-7s$PLAIN$thisstateform$settempcol%-7s$PLAIN$thisformat$actioncol%s$PLAIN\n" "${zonestr}" "${thiswant}" "${thisstate}" "${zsettemp[$x]}" "${ztemp[$x]}" "${zaction[$x]}" + done } function show_analysis() { - local count x ostr - echo -e "${UNDERLINE}Analysis:${PLAIN}" - count=0 - for x in ${!zproblem[@]}; do - if [[ ${zproblem[$x]} != "n/a" ]]; then - if [[ ${zproblem[$x]} == "owner_not_home" ]]; then - if [[ ${zowner[$x]} == *\ * ]]; then - ostr="owners are" - else - ostr="owner is" - fi - echo "- ${zname[$x]} open but $ostr not detected (${zowner[$x]})." - elif [[ ${zproblem[$x]} =~ force_ ]]; then - what=${zproblem[$x]##*_} - [[ $what == "close" ]] && what="${what}d" - echo "- ${zname[$x]} is forced $what" - else - if [[ $constant == ${zname[$x]} ]]; then - append=" (constant zone)" - else - append="" - fi - echo "- ${zname[$x]} is ${zproblem[$x]/_/ }${append}" - fi - count=$((count + 1)) - fi - done - if [[ $globprob == too_* ]]; then - echo "- $limit or more zones are ${globprob/_/ }" - fi - [[ $count -eq 0 ]] && echo -e "${GREEN}All is good!${PLAIN}" + local count x ostr + echo -e "${UNDERLINE}Analysis:${PLAIN}" + count=0 + for x in ${!zproblem[@]}; do + if [[ ${zproblem[$x]} != "n/a" ]]; then + if [[ ${zproblem[$x]} == "owner_not_home" ]]; then + if [[ ${zowner[$x]} == *\ * ]]; then + ostr="owners are" + else + ostr="owner is" + fi + echo "- ${zname[$x]} open but $ostr not detected (${zowner[$x]})." + elif [[ ${zproblem[$x]} =~ force_ ]]; then + what=${zproblem[$x]##*_} + [[ $what == "close" ]] && what="${what}d" + echo "- ${zname[$x]} is forced $what" + else + if [[ $constant == ${zname[$x]} ]]; then + append=" (constant zone)" + else + append="" + fi + echo "- ${zname[$x]} is ${zproblem[$x]/_/ }${append}" + fi + count=$((count + 1)) + fi + done + if [[ $globprob == too_* ]]; then + echo "- $limit or more zones are ${globprob/_/ }" + fi + [[ $count -eq 0 ]] && echo -e "${GREEN}All is good!${PLAIN}" } function show_proposed_commands() { - local str x maxlen count cmdformat fullcmd - str="Proposed commands" - echo -e "${UNDERLINE}${str}:${PLAIN}" + local str x maxlen count cmdformat fullcmd + str="Proposed commands" + echo -e "${UNDERLINE}${str}:${PLAIN}" - if [[ $nairconcommands -gt 0 ]]; then - if [[ -f ${KILLFILE} ]]; then - echo -e "${RED}Not running commands because killfile exists ($KILLFILE)${PLAIN}" - elif [[ $DOIT -ne 1 ]]; then - echo -e "${RED}Not running commands because -y not specified${PLAIN}" - fi - fi + if [[ $nairconcommands -gt 0 ]]; then + if [[ -f ${KILLFILE} ]]; then + echo -e "${RED}Not running commands because killfile exists ($KILLFILE)${PLAIN}" + elif [[ $DOIT -ne 1 ]]; then + echo -e "${RED}Not running commands because -y not specified${PLAIN}" + fi + fi - maxlen=-99 - for x in ${!airconcmd[@]}; do - fullcmd="myair $AIRCON_IP ${airconcmd[$x]}" - thislen=${#fullcmd} - [[ $thislen -gt $maxlen ]] && maxlen=$thislen - done + maxlen=-99 + for x in ${!airconcmd[@]}; do + fullcmd="myair $AIRCON_IP ${airconcmd[$x]}" + thislen=${#fullcmd} + [[ $thislen -gt $maxlen ]] && maxlen=$thislen + done - cmdformat="%-$((maxlen + 3))s" - count=0 - 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 - count=$((count + 1)) - done - [[ $count -eq 0 ]] && echo -e "${GREY}n/a${PLAIN}" + cmdformat="%-$((maxlen + 3))s" + count=0 + 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 + count=$((count + 1)) + done + [[ $count -eq 0 ]] && echo -e "${GREY}n/a${PLAIN}" } function run_commands() { - local x - for x in ${!airconcmd[@]}; do - [[ ! -z ${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]}\"" - done + local x + for x in ${!airconcmd[@]}; do + [[ ! -z ${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]}\"" + done } function profile() { - local diff - [[ $profiler != 1 ]] && return - p_last=$p_now - p_now=$(date +%s) - diff=$(( p_now - $p_last)) - if [[ -z $p_str ]]; then - p_str="$*" - else - info "+${diff} secs [$*]" >/dev/stderr - p_str="" - fi + local diff + [[ $profiler != 1 ]] && return + p_last=$p_now + p_now=$(date +%s) + diff=$(( p_now - $p_last)) + if [[ -z $p_str ]]; then + p_str="$*" + else + info "+${diff} secs [$*]" >/dev/stderr + p_str="" + fi } @@ -1264,50 +1425,50 @@ function profile() { # failedcmds # influxrv function influx_clear() { - failedcmds="" - influxrv=0 + failedcmds="" + influxrv=0 } # poplulates glpbals: # failedcmds # influxrv function influx_insert() { # $1 == cmd - local cmd thisrv - if [[ -z ${influx} ]]; then - return 1 - fi - cmd="$1" - if [[ $DOIT -eq 1 ]]; then - ${influx} -database "$influxdb" -execute "$cmd" - else - echo "${influx} -database $influxdb -execute $cmd" - thisrv=0 - fi - thisrv=$? - influxrv=$((influxrv + $thisrv)) - if [[ $thisrv -ne 0 ]]; then - failedcmds="$failedcmds$cmd\n" - fi + local cmd thisrv + if [[ -z ${influx} ]]; then + return 1 + fi + cmd="$1" + if [[ $DOIT -eq 1 ]]; then + ${influx} -database "$influxdb" -execute "$cmd" + else + echo "${influx} -database $influxdb -execute $cmd" + thisrv=0 + fi + thisrv=$? + influxrv=$((influxrv + $thisrv)) + if [[ $thisrv -ne 0 ]]; then + failedcmds="$failedcmds$cmd\n" + fi } # poplulates glpbals: # influx # influxdb function influx_init() { # $1 == dbname - local dbfound - influx=$(which influx 2>/dev/null) - influxdb="$1" - if [[ $? -ne 0 ]]; then - error "influx executable not found in path." - return 1 - fi - dbfound=$(${influx} -database "$influxdb" -execute "SHOW DATABASES" | grep -w ^${influxdb}) - if [[ -z $dbfound ]]; then - error "Couldn't find influx database '$influxdb'" - return 1 - fi - influx_clear - return 0 + local dbfound + influx=$(which influx 2>/dev/null) + influxdb="$1" + if [[ $? -ne 0 ]]; then + error "influx executable not found in path." + return 1 + fi + dbfound=$(${influx} -database "$influxdb" -execute "SHOW DATABASES" | grep -w ^${influxdb}) + if [[ -z $dbfound ]]; then + error "Couldn't find influx database '$influxdb'" + return 1 + fi + influx_clear + return 0 } @@ -1343,154 +1504,165 @@ showwho=0 limit=$DEFAULTLIMIT profiler=0 csvfile="$DEFAULT_CSVFILE" +sanitycheck=0 # check for config file option first if [[ $* == *-f\ * ]]; then - cf=$(echo "$*" | sed -e 's/.*-f //;s/ .*//') - if [[ ! -z $cf ]]; then - CONFIGFILE="$cf" - fi + cf=$(echo "$*" | sed -e 's/.*-f //;s/ .*//') + if [[ ! -z $cf ]]; then + CONFIGFILE="$cf" + fi fi ALLARGS="" if [[ -e $CONFIGFILE ]]; then - # load options from file... - ALLARGS=$(egrep "^options " $CONFIGFILE | sed -e 's/^options //' | tr '\n' ' ') + # load options from file... + ALLARGS=$(egrep "^options " $CONFIGFILE | sed -e 's/^options //' | tr '\n' ' ') fi ALLARGS="$ALLARGS $*" -optstring="A:cf:hi:I:k:l:Lo:pymwt:T:x:" +optstring="A:cf:hi:I:k:l:Lo:pmsSt:T:wx:y" while getopts "$optstring" i $ALLARGS; do - case "$i" in - h) - usage; - exit 1; - ;; - f) - CONFIGFILE=${OPTARG} - ;; - i) - AIRCON_IP=${OPTARG} - ;; - I) - logmode=2 - influx_init "$OPTARG" || exit 1 - ;; - A) - influx_init "$OPTARG" || exit 1 - ;; - k) - KILLFILE=${OPTARG} - ;; - l) - limit=${OPTARG} - ;; - o) - csvfile="$OPTARG" - ;; - L) - logmode=1 - ;; - t) - tolerance_l=${OPTARG} - ;; - T) - tolerance_h=${OPTARG} - ;; - c) - enable_cronmode - ;; - p) + case "$i" in + h) + usage; + exit 1; + ;; + f) + CONFIGFILE=${OPTARG} + ;; + i) + AIRCON_IP=${OPTARG} + ;; + I) + logmode=2 + influx_init "$OPTARG" || exit 1 + ;; + A) + influx_init "$OPTARG" || exit 1 + ;; + k) + KILLFILE=${OPTARG} + ;; + l) + limit=${OPTARG} + ;; + o) + csvfile="$OPTARG" + ;; + L) + logmode=1 + ;; + t) + tolerance_l=${OPTARG} + ;; + T) + tolerance_h=${OPTARG} + ;; + c) + enable_cronmode + ;; + p) profiler=1 - info "Profiler mode enabled" - ;; - m) - makeconfig=1 - ;; - y) - DOIT=1 - ;; - w) - showwho=1 - ;; - x) - MYAIR="${OPTARG}" - ;; - *) - usage; + info "Profiler mode enabled" + ;; + m) + makeconfig=1 + ;; + s) + sanitycheck=1 + ;; + S) + sanitycheck=2 + ;; + y) + DOIT=1 + ;; + w) + showwho=1 + ;; + x) + MYAIR="${OPTARG}" + ;; + *) + usage; exit 1; - ;; - esac + ;; + esac done shift $((OPTIND - 1)) - -if [[ -z $MYAIR ]]; then - MYAIR=$(which myair) - if [[ $? -ne 0 ]]; then - error "Can't find pymyair executable 'myair' in path. Install it from here: https://github.com/smallsam/pymyair" - exit 1 - fi -else - if [[ ! -x "$MYAIR" ]]; then - error "Specified pymyair executable '$MYAIR' not found." - exit 1 - fi -fi - if [[ $makeconfig -eq 1 ]]; then - gen_config - rv=$? - if [[ $rv -eq 0 ]]; then - info "A config file for your current aircon setup has been generated here:" - info " $CONFIGFILE" - info "Please review this and update as required." - fi - exit $rv + gen_config + rv=$? + if [[ $rv -eq 0 ]]; then + info "A config file for your current aircon setup has been generated here:" + info " $CONFIGFILE" + info "Please review this and update as required." + fi + exit $rv fi if [[ -e $CONFIGFILE ]]; then - if ! load_config; then - error "Config load failed" - exit 1 - fi + if [[ $sanitycheck -ge 1 ]]; then + parse_config $sanitycheck + exit $? + elif ! load_config; then + error "Config load failed" + exit 1 + fi else - error "Config file $CONFIGFILE doesn't exist." - exit 1 + error "Config file $CONFIGFILE doesn't exist." + exit 1 +fi + +if [[ $showwho -ne 1 ]]; then + if [[ -z $MYAIR ]]; then + MYAIR=$(which myair) + if [[ $? -ne 0 ]]; then + error "Can't find pymyair executable 'myair' in path. Install it from here: https://github.com/smallsam/pymyair" + exit 1 + fi + else + if [[ ! -x "$MYAIR" ]]; then + error "Specified pymyair executable '$MYAIR' not found." + exit 1 + fi + fi fi # ping all hosts in background to populate arp table for x in ${devices}; do - ping -c1 -w1 -n -q $ip >/dev/null 2>&1 & + ping -c1 -w1 -n -q $ip >/dev/null 2>&1 & done wait if [[ $showwho -eq 1 ]]; then - # get max phone name length - maxlen=1 - for x in ${pname[@]}; do - [[ ${#x} -gt $maxlen ]] && maxlen=$((${#x} + 3)) - done - # get a list of all phones - TFORMAT="${BOLD}${UNDERLINE}%-${maxlen}s%-16s${PLAIN}\n" - HFORMAT="%-${maxlen}s${GREEN}%-16s${PLAIN}\n" - AFORMAT="%-${maxlen}s${RED}%-16s${PLAIN}\n" - echo - printf "$TFORMAT" "Person" "Availability" - for x in ${!pname[@]}; do - if canping "${pdev[$x]}"; then - thisform="$HFORMAT" - str="At home" - else - thisform="$AFORMAT" - str="Out of the house" - fi - printf "$thisform" "${pname[$x]}" "$str" - done - echo - exit 0 + # get max phone name length + maxlen=1 + for x in ${pname[@]}; do + [[ ${#x} -gt $maxlen ]] && maxlen=$((${#x} + 3)) + done + # get a list of all phones + TFORMAT="${BOLD}${UNDERLINE}%-${maxlen}s%-16s${PLAIN}\n" + HFORMAT="%-${maxlen}s${GREEN}%-16s${PLAIN}\n" + AFORMAT="%-${maxlen}s${RED}%-16s${PLAIN}\n" + echo + printf "$TFORMAT" "Person" "Availability" + for x in ${!pname[@]}; do + if canping "${pdev[$x]}"; then + thisform="$HFORMAT" + str="At home" + else + thisform="$AFORMAT" + str="Out of the house" + fi + printf "$thisform" "${pname[$x]}" "$str" + done + echo + exit 0 fi @@ -1498,81 +1670,81 @@ fi get_aircon_info if [[ $logmode -eq 1 ]]; then - now=$(date +'%d/%m/%Y %H:%M:%S') - if [[ ! -e $csvfile ]]; then - cp /dev/null $csvfile - echo -n "Date" >>$csvfile - for x in ${!zname[@]}; do - echo -n ",${zname[$x]}" >> $csvfile - done - echo >> $csvfile - fi - echo -n "${now}" >>$csvfile - for x in ${!zname[@]}; do - echo -n ",${ztemp[$x]}" >> $csvfile - done - echo >> $csvfile - exit 0 + now=$(date +'%d/%m/%Y %H:%M:%S') + if [[ ! -e $csvfile ]]; then + cp /dev/null $csvfile + echo -n "Date" >>$csvfile + for x in ${!zname[@]}; do + echo -n ",${zname[$x]}" >> $csvfile + done + echo >> $csvfile + fi + echo -n "${now}" >>$csvfile + for x in ${!zname[@]}; do + echo -n ",${ztemp[$x]}" >> $csvfile + done + echo >> $csvfile + exit 0 elif [[ $logmode -eq 2 ]]; then - now=$(date +'%d/%m/%Y %H:%M:%S') + now=$(date +'%d/%m/%Y %H:%M:%S') - rv=0 - failedcmds="" - influx_clear - for x in ${!zname[@]}; do - influx_insert "INSERT temperature,room=${zname[$x]} value=${ztemp[$x]}" - done + rv=0 + failedcmds="" + influx_clear + for x in ${!zname[@]}; do + influx_insert "INSERT temperature,room=${zname[$x]} value=${ztemp[$x]}" + done - for x in ${!pname[@]}; do - canping "${pdev[$x]}" && ishome=1 || ishome=0 - influx_insert "INSERT attendance,person=${pname[$x]} value=$ishome" - done - [[ $airconmode == "off" ]] && pw=0 || pw=1 - influx_insert "INSERT aircon running=$pw" - # 0= off - # 1=cool - # 2=heat - # 3=dry - # 4=fan/other - case "$airconmode" in - "off") modenum=0;; - "cool") modenum=1;; - "heat") modenum=2;; - "dry") modenum=3;; - *) modenum=4;; - esac - influx_insert "INSERT aircon mode=$modenum" + for x in ${!pname[@]}; do + canping "${pdev[$x]}" && ishome=1 || ishome=0 + influx_insert "INSERT attendance,person=${pname[$x]} value=$ishome" + done + [[ $airconmode == "off" ]] && pw=0 || pw=1 + influx_insert "INSERT aircon running=$pw" + # 0= off + # 1=cool + # 2=heat + # 3=dry + # 4=fan/other + case "$airconmode" in + "off") modenum=0;; + "cool") modenum=1;; + "heat") modenum=2;; + "dry") modenum=3;; + *) modenum=4;; + esac + influx_insert "INSERT aircon mode=$modenum" - if [[ $influxrv -gt 0 ]]; then - echo -e "${RED}$failedcmds${PLAIN}" | sed -e 's/^/ /' - fi - exit ${rv} + if [[ $influxrv -gt 0 ]]; then + echo -e "${RED}$failedcmds${PLAIN}" | sed -e 's/^/ /' + fi + exit ${rv} fi generate_actions if [[ $cronmode -eq 1 ]]; then - # only show output if we are doing something - [[ $nairconcommands -ge 1 ]] && showoutput=1 || showoutput=0 + # only show output if we are doing something + [[ $nairconcommands -ge 1 ]] && showoutput=1 || showoutput=0 else - showoutput=1 + showoutput=1 fi if [[ $showoutput -eq 1 ]]; then - echo - show_aircon_status - echo - show_analysis - echo - show_proposed_commands - echo + echo + show_aircon_status + echo + show_analysis + echo + show_proposed_commands + echo fi # Actually run the commands if [[ $DOIT -eq 1 ]]; then - if [[ ! -f ${KILLFILE} ]]; then - run_commands - [[ $cronmode -ne 1 ]] && echo - fi + if [[ ! -f ${KILLFILE} ]]; then + run_commands + [[ $cronmode -ne 1 ]] && echo + fi fi