2021-07-01 16:24:15 +10:00
|
|
|
#!/bin/bash
|
2021-06-03 09:01:36 +10:00
|
|
|
|
2021-07-01 16:24:15 +10:00
|
|
|
# TODO: comparison to previous reading
|
2021-06-03 09:01:36 +10:00
|
|
|
# TODO: gnuplot of given time range
|
|
|
|
# TODO: manual controls
|
|
|
|
|
|
|
|
DEFAULT_KILLFILE="${HOME}/.aircon_noaction"
|
|
|
|
DEFAULT_CONFIGFILE=${HOME}/.airconrc
|
|
|
|
DEFAULT_CSVFILE=${HOME}/acstats.csv
|
|
|
|
DEFAULT_AIRCON_IP=10.99.99.1
|
|
|
|
DEFAULTLIMIT=3
|
|
|
|
DEFAULT_TOLERANCE=0
|
|
|
|
VALID_MODES=" cool heat "
|
|
|
|
VALID_ZONE_STATES=" open close "
|
|
|
|
|
2022-06-28 10:06:06 +10:00
|
|
|
ARPING_DEF=/usr/local/sbin/arping
|
|
|
|
ARPING=${ARPING_DEF}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
BOLD="\033[1m"
|
|
|
|
PLAIN="\033[0m"
|
2021-12-04 20:24:25 +11:00
|
|
|
STRIKE="\033[9m"
|
2021-06-03 09:01:36 +10:00
|
|
|
UNDERLINE="\033[4m"
|
2021-12-04 20:24:25 +11:00
|
|
|
DARKGREY="\033[38;2;90;90;90m"
|
2021-06-03 09:01:36 +10:00
|
|
|
RED="\033[31m"
|
2021-12-04 20:24:25 +11:00
|
|
|
ORANGE="\033[38;2;255;165;0m"
|
|
|
|
PINK="\033[38;2;255;151;198m"
|
|
|
|
MAGENTA="\033[35m"
|
2021-06-03 09:01:36 +10:00
|
|
|
GREEN="\033[32m"
|
|
|
|
YELLOW="\033[33m"
|
|
|
|
BLUE="\033[34m"
|
|
|
|
CYAN="\033[36m"
|
2021-12-04 20:24:25 +11:00
|
|
|
GREY="\033[2;37m"
|
2021-06-03 09:01:36 +10:00
|
|
|
WHITE="\033[37m"
|
|
|
|
LINK="$BLUE$UNDERLINE"
|
|
|
|
|
2023-04-10 21:18:10 +10:00
|
|
|
RULEDB=0
|
2021-06-03 09:01:36 +10:00
|
|
|
|
2023-09-03 12:32:37 +10:00
|
|
|
export PYTHONWARNINGS="ignore" # for urllib NotOpenSSLWarning
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function enable_cronmode() {
|
2021-12-04 20:24:25 +11:00
|
|
|
cronmode=1
|
|
|
|
BOLD=""
|
|
|
|
PLAIN=""
|
|
|
|
UNDERLINE=""
|
|
|
|
GREY=""
|
|
|
|
RED=""
|
|
|
|
GREEN=""
|
|
|
|
YELLOW=""
|
|
|
|
BLUE=""
|
|
|
|
CYAN=""
|
|
|
|
WHITE=""
|
|
|
|
LINK="$BLUE$UNDERLINE"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function usage() {
|
2021-12-04 20:24:25 +11:00
|
|
|
echo "usage: $0 [options]"
|
|
|
|
echo
|
|
|
|
echo " Modifies aircon based on configured parameters in $DEFAULT_CONFIGFILE."
|
|
|
|
echo
|
2023-12-11 23:02:15 +11:00
|
|
|
echo " -a file Specify location of arping binary (default: $ARPING_DEF)."
|
|
|
|
echo " -b Rule debug mode. Show processing of time rules."
|
|
|
|
echo " -A db Log actions to given influxdb database."
|
|
|
|
echo " -c Cron mode. Only show output if actions were taken."
|
|
|
|
echo " -D dbhost Specify influxdb hostname for -I and -A options (default: localhost)"
|
|
|
|
echo " -e file After removing expired killfile, write exptext (see -E) to this file."
|
|
|
|
echo " -E exptext Define 'exptext' for -e option."
|
2023-12-02 09:51:56 +11:00
|
|
|
echo " -g file Send Tele(g)ram notifications via api.telegran.org. File format is:"
|
|
|
|
echo " bottoken"
|
|
|
|
echo " chatid"
|
2021-12-04 20:24:25 +11:00
|
|
|
echo " -f file Specify an alternate config file."
|
2024-10-16 14:44:21 +11:00
|
|
|
echo " -F zonename:temp Forcibly provide current zone temperature (for testing)"
|
2022-06-28 10:06:06 +10:00
|
|
|
echo " -h Show this text."
|
|
|
|
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)."
|
2023-11-25 13:12:56 +11:00
|
|
|
echo " -k file If file exists and is empty, never change aircon settings (default: $DEFAULT_KILLFILE)."
|
|
|
|
echo " If file is non-empty, never change aircon settings if current unixtime < file contents."
|
|
|
|
echo " File will be removed if current unixtime >= file contents."
|
2021-12-04 20:24:25 +11:00
|
|
|
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 " -m Generate a config file based on current aircon setup."
|
2022-06-28 10:06:06 +10:00
|
|
|
echo " -o file Specify CSV output file. Default: $DEFAULT_CSVFILE"
|
2021-12-04 20:24:25 +11:00
|
|
|
echo " -p Profiler mode."
|
|
|
|
echo " -s Validate config file then exit."
|
2021-12-05 16:52:47 +11:00
|
|
|
echo " -S[H] Show configured rules in human-readable format"
|
|
|
|
echo " (HTML if -H given, otherwise ANSI)."
|
2021-12-04 20:24:25 +11:00
|
|
|
echo " -t num Specify degrees below min temperature before taking action."
|
|
|
|
echo " -T num Specify degrees above max temperature before taking action."
|
2022-06-28 10:06:06 +10:00
|
|
|
echo " -w List which people are available then exit."
|
|
|
|
echo " -W List zone-owning devices are available then exit."
|
2021-12-04 20:24:25 +11:00
|
|
|
echo " -y Actually run commands/db inserts. By default, commands are just displayed."
|
|
|
|
echo
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function action() {
|
|
|
|
echo -e "$BOLD$GREEN>> Running action: $PLAIN$GREEN$*$PLAIN"
|
|
|
|
}
|
|
|
|
|
2023-09-03 20:59:35 +10:00
|
|
|
function warn() {
|
|
|
|
echo -e "$BOLD${YELLOW}Warning: $PLAIN$YELLOW$*$PLAIN" >/dev/stderr
|
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function error() {
|
|
|
|
echo -e "$BOLD${RED}ERROR: $PLAIN$RED$*$PLAIN" >/dev/stderr
|
|
|
|
}
|
|
|
|
|
|
|
|
function info() {
|
|
|
|
echo -e "$BOLD${CYAN}>> $PLAIN$CYAN$*$PLAIN"
|
|
|
|
}
|
|
|
|
|
|
|
|
# get_midrange zone_idx
|
|
|
|
function get_midrange() { # outputs midpoint of temperature range for given zone
|
2021-12-04 20:24:25 +11:00
|
|
|
local min max
|
|
|
|
min=${zwantmin[$idx]}
|
|
|
|
max=${zwantmax[$idx]}
|
|
|
|
echo "($min + $max) / 2" | bc
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
# get_perfect_tolerance zone_idx
|
2022-06-14 21:09:56 +10:00
|
|
|
function get_perfect_tolerance() { # outputs the difference from midpoint after which temperature is considered "perfect"
|
2022-05-29 10:27:40 +10:00
|
|
|
local min max
|
|
|
|
min=${zwantmin[$idx]}
|
|
|
|
max=${zwantmax[$idx]}
|
|
|
|
echo "scale=2; ($max - $min) / 4" | bc
|
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function getoppositestate() {
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $1 == "open" ]]; then
|
|
|
|
echo "close"
|
|
|
|
elif [[ $1 == "close" ]]; then
|
|
|
|
echo "open"
|
|
|
|
fi
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function getzoneaction() { # populates zproblem[] and zaction[]
|
2021-12-04 20:24:25 +11:00
|
|
|
local idx problem num thisaction priority pingok fv
|
2022-05-29 10:27:40 +10:00
|
|
|
local donearby thisperfect=0
|
2021-12-04 20:24:25 +11:00
|
|
|
idx=$1
|
|
|
|
|
|
|
|
profile "getzoneaction for idx ${zname[$idx]}"
|
2022-06-28 17:16:21 +10:00
|
|
|
[[ $robtest -eq 1 ]] && echo "getzoneaction zone ${zname[$idx]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
thisaction="n/a"
|
|
|
|
if [[ ${zignore[$idx]} -eq 1 ]]; then
|
|
|
|
problem="n/a"
|
2022-05-29 10:27:40 +10:00
|
|
|
thisperfect=1
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2023-09-03 16:27:53 +10:00
|
|
|
[[ $robtest -eq 1 ]] && echo " owner of ${zname[$idx]} is [${zowner[$idx]}]" >&2
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ -z ${zowner[$idx]} ]]; then
|
|
|
|
pingok=1
|
2022-06-28 17:16:21 +10:00
|
|
|
#[[ $robtest -eq 1 ]] && echo " empty owner so no ping "
|
2022-05-28 15:09:29 +10:00
|
|
|
elif canping ${zowner[$idx]}; then
|
2022-06-28 17:16:21 +10:00
|
|
|
#[[ $robtest -eq 1 ]] && echo " canping returned ok"
|
2021-12-04 20:24:25 +11:00
|
|
|
pingok=1
|
|
|
|
else
|
2022-06-28 17:16:21 +10:00
|
|
|
#[[ $robtest -eq 1 ]] && echo " canping returned fail"
|
2021-12-04 20:24:25 +11:00
|
|
|
pingok=0
|
2022-06-28 17:16:21 +10:00
|
|
|
thisperfect=0
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
fv=$(getforcevent ${zname[$idx]})
|
2022-06-28 17:16:21 +10:00
|
|
|
[[ $robtest -eq 1 ]] && echo " canping zone ${zname[$idx]} is: $pingok"
|
2022-05-29 21:36:08 +10:00
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
donearby=0
|
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $fv && ${zstate[$idx]} == $(getoppositestate ${fv}) ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ $pingok -eq 1 ]]; then
|
|
|
|
# check for 'perfect' zones
|
|
|
|
if [[ ${zwanttemp[$idx]} != *-* ]]; then
|
|
|
|
thisperfect=1
|
|
|
|
else
|
2022-05-29 21:36:08 +10:00
|
|
|
local mid midtol
|
2022-05-29 10:27:40 +10:00
|
|
|
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
|
2022-06-14 21:09:56 +10:00
|
|
|
thisperfect=$(echo "${ztemp[$idx]} >= (${mid} + ${midtol})" | bc)
|
2022-05-29 10:27:40 +10:00
|
|
|
elif [[ $airconmode == "cool" ]]; then
|
2022-06-14 21:09:56 +10:00
|
|
|
thisperfect=$(echo "${ztemp[$idx]} <= (${mid} - ${midtol})" | bc)
|
2022-05-29 10:27:40 +10:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
zproblem[$idx]="$problem"
|
|
|
|
zpri[$idx]="$priority"
|
2022-05-28 15:09:29 +10:00
|
|
|
zownerhome[$idx]="$pingok"
|
2021-12-04 20:24:25 +11:00
|
|
|
|
2023-09-03 16:27:53 +10:00
|
|
|
[[ $robtest -eq 1 ]] && echo " zproblem is: ${zproblem[$idx]}"
|
|
|
|
[[ $robtest -eq 1 ]] && echo " zpri is: ${zpri[$idx]}"
|
|
|
|
[[ $robtest -eq 1 ]] && echo " zownerhome is: ${zownerhome[$idx]}"
|
|
|
|
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2024-10-16 14:44:21 +11:00
|
|
|
if [[ $airconmode == "heat" || $thisaction == *set_mode:heat* ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# 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
|
2024-10-16 14:44:21 +11:00
|
|
|
if [[ $airconmode == "cool" || $thisaction == *set_mode:cool* ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# 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"
|
2022-05-29 10:27:40 +10:00
|
|
|
zperfect[$idx]=$thisperfect
|
2023-09-03 16:27:53 +10:00
|
|
|
[[ $robtest -eq 1 ]] && echo " zaction is: ${zaction[$idx]}"
|
|
|
|
[[ $robtest -eq 1 ]] && echo " zperfect is: ${zperfect[$idx]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
profile "getzoneaction for idx ${zname[$idx]}"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function getidxfromname() { # name
|
2021-12-04 20:24:25 +11:00
|
|
|
local x
|
2022-05-29 21:36:08 +10:00
|
|
|
#echo "==== getidxfromname($1)" >/dev/stderr
|
2021-12-04 20:24:25 +11:00
|
|
|
for x in ${!zname[@]}; do
|
2022-05-29 21:36:08 +10:00
|
|
|
#echo "==== idx $x comparing zname ('${zname[$x]}') to \$1 ('$1')" >/dev/stderr
|
|
|
|
if [[ ${zname[$x]} == "$1" ]]; then
|
|
|
|
#echo " ==== matched. returning ${x}" >/dev/stderr
|
2021-12-04 20:24:25 +11:00
|
|
|
echo "${x}"
|
2022-05-29 21:36:08 +10:00
|
|
|
return
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
done
|
2022-05-29 21:36:08 +10:00
|
|
|
echo "-1"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function getnamefromid() { # id
|
2021-12-04 20:24:25 +11:00
|
|
|
local x
|
|
|
|
for x in ${!zname[@]}; do
|
|
|
|
if [[ ${zid[$x]} == $1 ]]; then
|
|
|
|
echo "${zname[$x]}"
|
|
|
|
fi
|
|
|
|
done
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# getforcevent zone_name
|
|
|
|
function getforcevent() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# getalladj zone_name
|
|
|
|
function getalladj() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function find_nearby_zones() { # zone_idx filter1 filter2 ... filter is: open|closed|noaction
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2024-06-29 08:56:57 +10:00
|
|
|
if [[ $conditions == *open* && $constant == ${zname[$zi]} ]]; then
|
|
|
|
# the constant zone never counts as an adjacent 'open' zone, because
|
|
|
|
# if we were to close it, it would just get opened again.
|
|
|
|
ok=0
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $ok -eq 1 ]]; then
|
|
|
|
nearbyzones="$nearbyzones $thisone"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
echo "$nearbyzones"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
function all_zones_perfect() {
|
|
|
|
local x
|
|
|
|
for x in ${zperfect[@]}; do
|
|
|
|
if [[ $x -ne 1 ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 0
|
|
|
|
}
|
2021-06-03 09:01:36 +10:00
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
function generate_actions() { # populates global: nairconcommands & airconcmd[] & globprob
|
2021-12-04 20:24:25 +11:00
|
|
|
local x y z adj tempstr nhot ncold
|
|
|
|
local powerchange nmyzones maxpri bestidx
|
|
|
|
local globaction mzmustmove poss nomyzone
|
|
|
|
local db
|
|
|
|
db=0
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Determining actions... ${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
|
|
|
|
nairconcommands=0
|
|
|
|
powerchange=""
|
|
|
|
|
|
|
|
for x in ${!zname[@]}; do
|
|
|
|
getzoneaction $x
|
2022-05-28 15:09:29 +10:00
|
|
|
#echo "zoneignore for ${zname[$x]} is ${zignore[$x]}" >/dev/stderr
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
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
|
2022-05-29 10:27:40 +10:00
|
|
|
[[ -n $globsetmode ]] && globaction="power_on"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
|
|
|
if [[ $airconmode == "heat" && $nhot -ge $limit ]]; then
|
|
|
|
globprob="too_hot"
|
|
|
|
elif [[ $airconmode == "cool" && $ncold -ge $limit ]]; then
|
|
|
|
globprob="too_cold"
|
2022-05-29 10:27:40 +10:00
|
|
|
elif [[ $ncold -eq 0 && $nhot -eq 0 ]]; then
|
|
|
|
if all_zones_perfect; then
|
|
|
|
globprob="not_needed"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-05-29 10:27:40 +10:00
|
|
|
fi
|
|
|
|
if [[ -n $globprob ]]; then
|
|
|
|
globaction="power_off"
|
|
|
|
[[ -z $powerchange ]] && powerchange="power_off"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $globprob ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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).
|
2024-05-16 18:47:25 +10:00
|
|
|
#
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ -z $powerchange && $airconmode != "off" ]]; then
|
|
|
|
for x in ${!zname[@]}; do
|
2024-05-16 18:47:25 +10:00
|
|
|
if [[ ${zaction[$x]} == *close_vent* ]]; then
|
|
|
|
if [[ $constant == ${zname[$x]} ]]; then
|
|
|
|
if [[ $airconmyzoneid != ${zid[$x]} ]]; then
|
|
|
|
zaction[$x]="power_off"
|
|
|
|
[[ -z $powerchange ]] && powerchange="power_off"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
|
|
|
|
# pass 3 - If we're powering the whole system on/off, don't do anything else
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $powerchange ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-06-03 09:01:36 +10:00
|
|
|
[[ $db -eq 1 ]] && info "pass 3 - powerchange is '$powerchange'"
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ -z $powerchange ]]; then
|
|
|
|
if [[ $airconmode != "off" ]]; then
|
|
|
|
mzmustmove=0
|
2021-07-01 16:24:15 +10:00
|
|
|
# get list of all zones which can't be myzone
|
2021-12-04 20:24:25 +11:00
|
|
|
nomyzone=""
|
|
|
|
for x in ${!zname[@]}; do
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ ${znomyzone[$x]} -eq 1 ]]; then
|
|
|
|
nomyzone="$nomyzone ${zname[$x]} "
|
|
|
|
fi
|
|
|
|
done
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info "myzone must move away from ${zname[$x]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
#info "myzone must move away from ${zname[$x]}"
|
|
|
|
zaction[$x]="${zaction[$x]/set_myzone/}"
|
|
|
|
nomyzone="$nomyzone ${zname[$x]} "
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info "zaction[${zname[$z]} is '${zaction[$x]}'"
|
2023-12-09 08:47:07 +11:00
|
|
|
[[ $db -eq 1 ]] && info "nomyzone is '$nomyzone'"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [[ $mzmustmove -eq 1 ]]; then
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info "got mzmustmove == 1"
|
|
|
|
[[ $db -eq 1 ]] && info "FINAL nomyzone is '$nomyzone}'"
|
2021-12-04 20:24:25 +11:00
|
|
|
# find an alternative
|
|
|
|
for x in ${!zname[@]}; do
|
|
|
|
# open or opening? set myzone. we'll resolve
|
|
|
|
# duplicates in the next step.
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info " checking if we can move mz to ${zname[$x]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
poss=0
|
|
|
|
if [[ ${zaction[$x]} != *set_myzone* && $nomyzone != *\ ${zname[$x]}\ * ]]; then
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info " not already moving mz here + not in nomyzone list"
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ ${zstate[$x]} == "open" || ${zaction[$x]} == *open_vent* ]]; then
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info " is open or opening -> OK"
|
2021-12-04 20:24:25 +11:00
|
|
|
poss=1
|
|
|
|
elif [[ ${zaction[@]} == *open:${zname[$x]}* ]]; then
|
2021-07-01 16:24:15 +10:00
|
|
|
[[ $db -eq 1 ]] && info " is opening via adjacency-> OK"
|
2021-12-04 20:24:25 +11:00
|
|
|
poss=1
|
|
|
|
fi
|
|
|
|
if [[ $poss -eq 1 ]]; then
|
2021-06-03 09:01:36 +10:00
|
|
|
[[ $db -eq 1 ]] && info " myzone could move to ${zname[$x]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
#info " myzone could move to ${zname[$x]}"
|
|
|
|
zaction[$x]="${zaction[$x]} set_myzone"
|
2021-06-03 09:01:36 +10:00
|
|
|
[[ $db -eq 1 ]] && info " new zaction[${zname[$x]}] is ${zaction[x]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
# 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
|
2024-05-16 18:47:25 +10:00
|
|
|
|
|
|
|
# if we are closing the constant zone and taking no other action,
|
|
|
|
# just turn the system off.
|
|
|
|
if [[ $nairconcommands -eq 1 ]]; then
|
|
|
|
if [[ ${airconjcmd[0]} == *lose* ]]; then
|
|
|
|
if [[ ${airconcmdzone[0]} == $constant ]]; then
|
|
|
|
globprob="constant_close"
|
|
|
|
globaction="power_off"
|
|
|
|
[[ -z $powerchange ]] && powerchange="power_off"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $globaction ]]; then
|
2024-05-16 18:47:25 +10:00
|
|
|
gen_aircon_command -1 ${globaction}
|
2022-05-29 10:27:40 +10:00
|
|
|
fi
|
2024-05-16 18:47:25 +10:00
|
|
|
|
2023-12-02 09:51:56 +11:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# gen_aircon_command zone_idx "command1 command2 etc"
|
2021-07-01 16:24:15 +10:00
|
|
|
function gen_aircon_command() {
|
2023-09-03 16:27:53 +10:00
|
|
|
local idx allactions this toadd num doneset othername otherid otherid2 otheridx db donemode str jtoadd="" id2
|
2021-12-04 20:24:25 +11:00
|
|
|
idx=$1
|
|
|
|
shift
|
|
|
|
allactions="$*"
|
|
|
|
doneset=0
|
|
|
|
donemode=0
|
|
|
|
|
|
|
|
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
|
2023-09-03 16:27:53 +10:00
|
|
|
add_aircon_command $idx -1 "Power on system" "on" '"info":{"state":"on"}'
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *power_off* ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
add_aircon_command $idx -1 "Power off system" "off" '"info":{"state":"off"}'
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *set_myzone* && $airconmyzoneid != ${zid[$idx]} ]]; then
|
2022-05-29 10:27:40 +10:00
|
|
|
[[ $idx -eq -1 ]] && continue
|
2023-09-03 16:27:53 +10:00
|
|
|
add_aircon_command $idx -1 "Set MyZone to ${zname[$idx]}" "myzone --zone ${zid[$idx]}" "\"info\":{\"myZone\":${zid[$idx]}}"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *open:* ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
# open vent in another zone
|
|
|
|
[[ $idx -eq -1 ]] && continue
|
2021-12-04 20:24:25 +11:00
|
|
|
othername=$(echo "$this" | sed -e 's/^.*open://;s/ .*//')
|
|
|
|
otheridx=$(getidxfromname $othername)
|
|
|
|
otherid=${zid[$otheridx]}
|
2023-09-03 16:27:53 +10:00
|
|
|
otherid2=$(printf "z%02d" "$otherid")
|
|
|
|
add_aircon_command $idx $otheridx "Open vent in ${zname[$otheridx]}" "set --zone ${otherid} --state on --temp ${zsettemp[$otheridx]}" "\"zones\":{\"${otherid2}\":{\"state\":\"open\",\"setTemp\",${zsettemp[$otheridx]}}"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *close:* ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
# close vent in another zone
|
|
|
|
[[ $idx -eq -1 ]] && continue
|
2021-12-04 20:24:25 +11:00
|
|
|
othername=$(echo "$this" | sed -e 's/^.*close://;s/ .*//')
|
|
|
|
otheridx=$(getidxfromname $othername)
|
|
|
|
otherid=${zid[$otheridx]}
|
2023-09-03 16:27:53 +10:00
|
|
|
otherid2=$(printf "z%02d" "$otherid")
|
|
|
|
add_aircon_command $idx $otheridx "Close vent in ${zname[$otheridx]}" "set --zone ${otherid} --state off --temp ${zsettemp[$otheridx]}" "\"zones\":{\"${otherid2}\":{\"state\":\"close\",\"setTemp\",${zsettemp[$otheridx]}}"
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *set_mode:* ]]; then
|
|
|
|
str=$(echo "$this" | sed -e 's/^.*set_mode://;s/ .*//')
|
2023-09-03 16:27:53 +10:00
|
|
|
add_aircon_command $idx -1 "Set system mode to '$str'" "$str" "\"info\":{\"mode\":\"${str}\"}"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ $this == *set_temp* || $this == *open_vent* || $this == *close_vent* ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
[[ $idx -eq -1 ]] && continue
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $doneset -eq 0 ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
id2=$(printf "z%02d" "${zid[$idx]}")
|
|
|
|
jtoadd="\"zones\":{\"${id2}\":{"
|
2021-12-04 20:24:25 +11:00
|
|
|
toadd=""
|
|
|
|
comm=""
|
|
|
|
if [[ $allactions == *open_vent* ]]; then
|
|
|
|
toadd="$toadd --state on"
|
2023-09-03 16:27:53 +10:00
|
|
|
jtoadd="${jtoadd}\"state\":\"open\","
|
2021-12-04 20:24:25 +11:00
|
|
|
comm="open vent"
|
|
|
|
elif [[ $allactions == *close_vent* ]]; then
|
|
|
|
toadd="$toadd --state off"
|
2023-09-03 16:27:53 +10:00
|
|
|
jtoadd="${jtoadd}\"state\":\"close\","
|
2021-12-04 20:24:25 +11:00
|
|
|
comm="close vent"
|
|
|
|
fi
|
|
|
|
if [[ $allactions == *set_temp* ]]; then
|
|
|
|
num=$(echo "$this" | sed -e 's/^.*set_temp://;s/ .*//')
|
|
|
|
toadd="$toadd --temp $num"
|
2023-09-03 16:27:53 +10:00
|
|
|
jtoadd="${jtoadd}\"setTemp\":\"$num\","
|
2022-05-29 10:27:40 +10:00
|
|
|
[[ -n $comm ]] && comm="${comm} and "
|
2021-12-04 20:24:25 +11:00
|
|
|
comm="${comm}set temperature to $num degrees"
|
|
|
|
else
|
|
|
|
toadd="$toadd --temp ${zsettemp[$idx]}"
|
2023-09-03 16:27:53 +10:00
|
|
|
jtoadd="${jtoadd}\"setTemp\":\"${zsettemp[$idx]}\","
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $toadd ]]; then
|
2023-09-03 16:27:53 +10:00
|
|
|
|
|
|
|
jtoadd="${jtoadd/%,/}}}" # remove trailing comma, add closing braces
|
|
|
|
add_aircon_command $idx -1 "In zone ${zname[$idx]}, $comm" "set --zone ${zid[$idx]}$toadd" "$jtoadd"
|
2021-12-04 20:24:25 +11:00
|
|
|
doneset=1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2023-10-22 12:19:33 +11:00
|
|
|
# add_aircon_command zone_idx zone_idx2 "comment goes here" "textual version of command to run" "json command"
|
2021-06-03 09:01:36 +10:00
|
|
|
function add_aircon_command() {
|
2023-09-03 16:27:53 +10:00
|
|
|
local x idx otheridx comment db cmd jcmd
|
2021-12-04 20:24:25 +11:00
|
|
|
|
|
|
|
[[ $# -le 1 ]] && return 1
|
|
|
|
|
|
|
|
idx=$1
|
|
|
|
shift
|
|
|
|
otheridx=$1
|
|
|
|
shift
|
|
|
|
comment=$1
|
|
|
|
shift
|
2023-09-03 16:27:53 +10:00
|
|
|
cmd="$1"
|
|
|
|
shift
|
|
|
|
jcmd="{ \"ac1\":{"
|
|
|
|
jcmd="${jcmd}$1"
|
|
|
|
jcmd="${jcmd} } }"
|
2021-12-04 20:24:25 +11:00
|
|
|
|
|
|
|
if [[ $otheridx -ne -1 ]]; then
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $comment ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
[[ -z $* ]] && return 1
|
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
# already got this command queued?
|
2021-12-04 20:24:25 +11:00
|
|
|
for x in ${airconcmd[@]}; do
|
|
|
|
if [[ $x == "$*" ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
done
|
2023-09-03 16:27:53 +10:00
|
|
|
airconcmd[$nairconcommands]="$cmd"
|
|
|
|
airconjcmd[$nairconcommands]="$jcmd"
|
2021-12-04 20:24:25 +11:00
|
|
|
airconcomment[$nairconcommands]="$comment"
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ $idx -eq -1 ]]; then
|
|
|
|
airconcmdzone[$nairconcommands]="Aircon"
|
|
|
|
airconproblem[$nairconcommands]="Aircon is not needed at this time."
|
|
|
|
else
|
|
|
|
airconcmdzone[$nairconcommands]="${zname[$idx]}"
|
2023-12-09 08:47:07 +11:00
|
|
|
if [[ ${zproblem[$idx]} == "n/a" ]]; then
|
|
|
|
# global problem
|
|
|
|
if [[ -n $globprob ]]; then
|
|
|
|
airconproblem[$nairconcommands]="$(describe_globprob)"
|
|
|
|
else
|
|
|
|
airconproblem[$nairconcommands]="Unknown"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
# zone-specific problem
|
|
|
|
airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }"
|
|
|
|
fi
|
2022-05-29 10:27:40 +10:00
|
|
|
fi
|
2023-12-09 08:47:07 +11:00
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ $otheridx -eq -1 ]]; then
|
|
|
|
airconcmdotherzone[$nairconcommands]=""
|
|
|
|
else
|
|
|
|
airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
#if [[ $otheridx -ne -1 ]]; then
|
|
|
|
# airconcomment[$nairconcommands]="${airconcomment[$nairconcommands]}, update nearby zone ${zname[$otheridx]}"
|
|
|
|
#fi
|
|
|
|
nairconcommands=$((nairconcommands + 1))
|
|
|
|
return 0
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
}
|
2023-09-03 16:27:53 +10:00
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function addnoop() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local idx
|
|
|
|
idx=$(getidxfromname "$1")
|
|
|
|
zignore[$idx]=1
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2021-07-01 16:24:15 +10:00
|
|
|
function addnomyzone() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local idx
|
|
|
|
idx=$(getidxfromname "$1")
|
|
|
|
znomyzone[$idx]=1
|
2021-07-01 16:24:15 +10:00
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function addforcevent() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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))
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
function addtemprange() { # [-s] idx min-max -s means 'set zwanttemp+zwantmin+zwantmax too'
|
|
|
|
local x idx doset=0
|
|
|
|
if [[ $1 == "-s" ]]; then
|
|
|
|
doset=1
|
|
|
|
shift
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
idx=$ntempranges
|
|
|
|
for x in ${!tr_zonename[@]}; do
|
|
|
|
if [[ ${tr_zonename[$x]} == "$1" ]]; then
|
|
|
|
idx=$x
|
|
|
|
break;
|
|
|
|
fi
|
|
|
|
done
|
2022-05-28 15:09:29 +10:00
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
tr_zonename[$idx]="$1"
|
|
|
|
tr_range[$idx]="$2"
|
2022-05-28 15:09:29 +10:00
|
|
|
|
|
|
|
if [[ $doset -eq 1 ]]; then
|
|
|
|
local wanttemp zidx
|
|
|
|
wanttemp=$(gettemprange "$1")
|
|
|
|
zidx=$(getidxfromname "$1")
|
|
|
|
if [[ $wanttemp == "n/a" ]]; then
|
|
|
|
zwanttemp[$zidx]="n/a"
|
|
|
|
zwantmin[$zidx]="-99"
|
|
|
|
zwantmax[$zidx]="99"
|
|
|
|
else
|
|
|
|
zwanttemp[$zidx]="$wanttemp"
|
|
|
|
zwantmin[$zidx]="${wanttemp%-*}"
|
|
|
|
zwantmax[$zidx]="${wanttemp#*-}"
|
|
|
|
fi
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
[[ $idx == $ntempranges ]] && ntempranges=$((ntempranges + 1))
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function addadj() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local name
|
|
|
|
name="$1"
|
|
|
|
shift
|
|
|
|
adj_zonename[$nadj]="$name"
|
|
|
|
adj_nearby[$nadj]="$*"
|
|
|
|
nadj=$((nadj + 1))
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function addperson() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local h p x idx db
|
|
|
|
db=0
|
|
|
|
|
|
|
|
p="$1"
|
|
|
|
shift
|
|
|
|
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))
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
function addowner() { # zone "host1 host2 ..."
|
|
|
|
local z h local x idx db doset=0
|
2022-05-29 21:36:08 +10:00
|
|
|
local zidx
|
2021-12-04 20:24:25 +11:00
|
|
|
db=0
|
2022-05-28 15:09:29 +10:00
|
|
|
if [[ $1 == "-s" ]]; then
|
|
|
|
doset=1
|
|
|
|
shift
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
|
|
|
|
z="$1"
|
|
|
|
shift
|
|
|
|
h="$*"
|
|
|
|
|
2022-05-29 21:36:08 +10:00
|
|
|
|
|
|
|
zidx=$(getidxfromname "$z") # get the index into the zname[] etc arrays
|
|
|
|
if [[ $zidx -eq -1 ]]; then
|
|
|
|
error "Failed to set owner of zone '$z' to '$h' - zone doesn't exist. "
|
|
|
|
exit 1;
|
|
|
|
fi
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
[[ $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))
|
2022-05-28 15:09:29 +10:00
|
|
|
|
|
|
|
if [[ $doset -eq 1 ]]; then
|
|
|
|
zowner[$zidx]="${ownerhost[$idx]}";
|
2022-05-29 21:36:08 +10:00
|
|
|
|
|
|
|
[[ $db -eq 1 ]] && info " doing set of zowner[$zidx] (${zname[$zidx]}} to [${ownerhost[$idx]}]"
|
2022-05-28 15:09:29 +10:00
|
|
|
#zownerperson[$zidx]=$(getownerperson "$z"); # may be overwritten later
|
|
|
|
fi
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# getownerperson zone_name
|
|
|
|
# returns name of person who owns zone
|
2022-05-28 15:09:29 +10:00
|
|
|
#function getownerperson() {
|
|
|
|
# local x retval
|
|
|
|
# retval=""
|
|
|
|
# for x in ${!ownerzone[@]}; do
|
|
|
|
# if [[ ${ownerzone[$x]} == "$1" ]]; then
|
|
|
|
# retval="${ownerperson[$x]}"
|
|
|
|
# break
|
|
|
|
# fi
|
|
|
|
# done
|
|
|
|
# echo "$retval"
|
|
|
|
#}
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
# getowner zone_name
|
2022-05-29 21:36:08 +10:00
|
|
|
# returns devices associated with zone
|
2021-06-03 09:01:36 +10:00
|
|
|
function getowner() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local x retval
|
|
|
|
retval=""
|
|
|
|
for x in ${!ownerzone[@]}; do
|
|
|
|
if [[ ${ownerzone[$x]} == "$1" ]]; then
|
|
|
|
retval="${ownerhost[$x]}"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
echo "$retval"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# gettemprange zone_name
|
|
|
|
function gettemprange() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function getstrtype() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
function weekdaytonum() {
|
|
|
|
local num
|
|
|
|
shopt -s nocasematch
|
|
|
|
num=-1
|
|
|
|
case "$1" in
|
|
|
|
"mon") num=1;;
|
|
|
|
"tue") num=2;;
|
|
|
|
"wed") num=3;;
|
2022-05-29 21:36:08 +10:00
|
|
|
"thu") num=4;;
|
2021-12-04 20:24:25 +11:00
|
|
|
"fri") num=5;;
|
|
|
|
"sat") num=6;;
|
|
|
|
"sun") num=7;;
|
|
|
|
esac
|
|
|
|
shopt -u nocasematch
|
|
|
|
echo "$num"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-06-16 19:21:32 +10:00
|
|
|
function weekdaytofull() {
|
|
|
|
local full
|
|
|
|
shopt -s nocasematch
|
|
|
|
num=-1
|
|
|
|
case "$1" in
|
|
|
|
"mon") full="Monday";;
|
|
|
|
"tue") full="Tuesday";;
|
|
|
|
"wed") full="Wednesday";;
|
|
|
|
"thu") full="Thursday";;
|
|
|
|
"fri") full="Friday";;
|
|
|
|
"sat") full="Saturday";;
|
|
|
|
"sun") full="Sunday";;
|
|
|
|
esac
|
|
|
|
shopt -u nocasematch
|
|
|
|
echo "$full"
|
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function conderror() {
|
2021-12-04 20:24:25 +11:00
|
|
|
error "Invalid condition: $1"
|
|
|
|
echo -e "${RED} Start: $2"
|
|
|
|
echo -e "${RED} End: $3"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
2021-07-01 16:24:15 +10:00
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function load_config() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local line rv timestr ttok stype ok starth endh nowh
|
|
|
|
local cond allconds x
|
|
|
|
local db
|
|
|
|
parse_config || return 1
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Loading config file... ${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
db=0
|
|
|
|
rv=0
|
|
|
|
while read line; do
|
2022-05-28 15:09:29 +10:00
|
|
|
ok=1 # default to okay
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2022-05-28 15:09:29 +10:00
|
|
|
addtemprange -s ${tok[1]} ${tok[2]}
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2022-05-28 15:09:29 +10:00
|
|
|
addowner -s ${tok[1]} ${tok[@]:2}
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2022-06-14 21:09:56 +10:00
|
|
|
if [[ $cronmode -eq 0 && $logmode -eq 0 ]]; then
|
|
|
|
if [[ $rv -eq 0 ]]; then
|
|
|
|
echo -e "${GREEN}${BOLD}ok${PLAIN}"
|
|
|
|
else
|
|
|
|
echo -e "${RED}${BOLD}fail${PLAIN}"
|
|
|
|
fi
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
return $rv
|
|
|
|
}
|
|
|
|
|
|
|
|
# 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
|
2021-12-05 16:51:14 +11:00
|
|
|
local nonmatches=0
|
|
|
|
local rv
|
2023-04-10 19:52:05 +10:00
|
|
|
local db=0
|
|
|
|
if [[ $RULEDB -eq 1 ]]; then
|
|
|
|
db=1
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $1 == "-c" ]]; then
|
|
|
|
keepgoing=1
|
|
|
|
shift 1
|
|
|
|
fi
|
|
|
|
line="$*"
|
|
|
|
timestr_human=""
|
|
|
|
|
2023-04-10 19:52:05 +10:00
|
|
|
timestr=${line%% *} # only process first word
|
|
|
|
timestr=${timestr:1} # strip leading @
|
|
|
|
[[ $db -eq 1 ]] && info "${BOLD}Processing line: '$line'"
|
2021-12-04 20:24:25 +11:00
|
|
|
IFS=';' read -ra allconds <<< "$timestr"
|
|
|
|
for cond in ${allconds[@]} ; do
|
2023-04-10 19:52:05 +10:00
|
|
|
[[ $db -eq 1 ]] && info " processing condition: '$cond'"
|
2021-12-04 20:24:25 +11:00
|
|
|
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]})"
|
|
|
|
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
endh="$starth"
|
|
|
|
nowh=$(date +%u)
|
2022-06-16 19:21:32 +10:00
|
|
|
|
|
|
|
[[ -n $timestr_human ]] && this_human="o " || this_human=O
|
|
|
|
this_human=$(printf "${this_human}n _H_%ss_EH_" $(weekdaytofull ${ttok[0]}))
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
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)
|
2022-06-16 19:21:32 +10:00
|
|
|
if [[ ${ttok[0]} == ${ttok[1]} ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
[[ -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
|
2022-06-16 19:21:32 +10:00
|
|
|
fi # end if ttokcount
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $starth ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
[[ $db -eq 1 ]] && info " check if $nowh is between $starth and $endh"
|
|
|
|
ok=0
|
|
|
|
if [[ $(echo "$starth < $endh" | bc) == "1" ]]; then
|
2023-04-10 19:52:05 +10:00
|
|
|
[[ $db -eq 1 ]] && info " time period does NOT span midnight"
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $(echo "$nowh >= $starth" | bc) == "1" && $(echo "$nowh <= $endh" | bc) == "1" ]]; then
|
|
|
|
ok=1
|
|
|
|
fi
|
|
|
|
elif [[ $(echo "$starth > $endh" | bc) == "1" ]]; then
|
2023-04-10 19:52:05 +10:00
|
|
|
[[ $db -eq 1 ]] && info " time period spans midnight"
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-12-05 16:51:14 +11:00
|
|
|
[[ $ok -eq 0 ]] && nonmatches=$((nonmatches + 1))
|
2021-12-04 20:24:25 +11:00
|
|
|
[[ $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"
|
2022-06-16 19:21:32 +10:00
|
|
|
fi # end if condition matches
|
2021-12-04 20:24:25 +11:00
|
|
|
timestr_human="${timestr_human}${this_human}"
|
|
|
|
if [[ $ok -eq 0 && $keepgoing -eq 0 ]]; then
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
2021-12-05 16:51:14 +11:00
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
[[ $db -eq 1 ]] && info " ok=$ok nonmatches=$nonmatches"
|
|
|
|
|
2021-12-05 16:51:14 +11:00
|
|
|
if [[ $ok -eq 0 || $nonmatches -gt 0 ]]; then
|
|
|
|
rv=1
|
|
|
|
else
|
|
|
|
rv=0
|
|
|
|
fi
|
2022-05-28 15:09:29 +10:00
|
|
|
[[ $db -eq 1 ]] && info " returning $rv"
|
2021-12-05 16:51:14 +11:00
|
|
|
return $rv
|
2021-12-04 20:24:25 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
function active_cols() {
|
2021-12-05 16:51:14 +11:00
|
|
|
if [[ $RULEFORMAT == "html" ]]; then
|
|
|
|
plainc="<font color=#000000></strong></s>" # black
|
|
|
|
inactc="<font color=#ff0000>" # red
|
|
|
|
linec="<font color=#000000></strong></s>" # black
|
|
|
|
devc="<font color=#00aa00>" # green+bold
|
|
|
|
devbc="<strong><font color=#00aa00>" # green
|
|
|
|
statec="<strong><font color=#bbbb00>" # yellow+bold
|
|
|
|
roomc="<font color=#ffa500>" # orange
|
|
|
|
timec="<font color=#ff97c6>" # pink
|
|
|
|
timebc="<strong><font color=#ff97c6>" # pink+bold
|
|
|
|
minc="<strong><font color=#0000dd>" # blue+bold
|
|
|
|
maxc="<strong><font color=#dd0000>" # red+bold
|
|
|
|
coolc="<strong><font color=#00dddd>" # cyan+bold
|
|
|
|
heatc="<strong><font color=#dd0000>" # red+bold
|
|
|
|
nl="<br></s></strong><font color=#000000>\n"
|
|
|
|
else
|
|
|
|
plainc=${PLAIN}
|
|
|
|
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"
|
|
|
|
coolc="$BOLD$CYAN"
|
|
|
|
heatc="$RED"
|
|
|
|
nl="\n"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
function inactive_cols() {
|
2021-12-05 16:51:14 +11:00
|
|
|
if [[ $RULEFORMAT == "html" ]]; then
|
|
|
|
plainc="<font color=#000000></strong></s>" # black
|
|
|
|
inactc="<s><font color=#aaaaaa>" # lightgrey
|
|
|
|
linec=""
|
|
|
|
devc=""
|
|
|
|
devbc=""
|
|
|
|
statec=""
|
|
|
|
roomc=""
|
|
|
|
timec=""
|
|
|
|
timebc=""
|
|
|
|
minc=""
|
|
|
|
maxc=""
|
|
|
|
nl="</s><br>\n"
|
|
|
|
else
|
|
|
|
plainc=${PLAIN}
|
|
|
|
inactc="$DARKGREY"
|
|
|
|
linec="${inactc}"
|
|
|
|
devc="$inactc"
|
|
|
|
devbc="$inactc"
|
|
|
|
statec="$inactc"
|
|
|
|
roomc="$inactc"
|
|
|
|
timec="$inactc"
|
|
|
|
timebc="$inactc"
|
|
|
|
minc="$inactc"
|
|
|
|
maxc="$inactc"
|
|
|
|
nl="\n"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2022-05-28 15:09:29 +10:00
|
|
|
local ign="" thisignored=0 oneof
|
2021-12-04 20:24:25 +11:00
|
|
|
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Parsing config file... ${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2022-05-28 15:09:29 +10:00
|
|
|
thisignored=0
|
2021-12-04 20:24:25 +11:00
|
|
|
line_human=""
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n ${line// } ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# 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]#*-}
|
2022-05-28 15:09:29 +10:00
|
|
|
[[ $ign == *\ ${tok[1]}* ]] && thisignored=1 # zone is being ignored
|
|
|
|
[[ $thisignored -eq 1 ]] && inactive_cols
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2024-11-25 15:47:10 +11:00
|
|
|
[[ $ok -eq 1 ]] && ign="${ign} ${tok[1]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-12-05 16:51:14 +11:00
|
|
|
errstr="${errstr}${linenum}:Invalid zone state '${tok[2]}'. Valid options are: $VALID_ZONE_STATES$nl"
|
2021-12-04 20:24:25 +11:00
|
|
|
fileok=0
|
|
|
|
fi
|
|
|
|
elif [[ ${tok[0]} == "owner" ]]; then
|
|
|
|
local devices verb
|
|
|
|
devices="${devc}${tok[@]:2}${linec}"
|
|
|
|
if [[ ${#tok[@]} -eq 3 ]]; then
|
|
|
|
verb="isn't"
|
2022-05-28 15:09:29 +10:00
|
|
|
oneof=""
|
|
|
|
devices="${devbc}${linec}${devices}${devbc}${linec}"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
|
|
|
verb="aren't"
|
2022-05-28 15:09:29 +10:00
|
|
|
oneof=" one of"
|
|
|
|
devices="${devbc}(${linec}${devices}${devbc})${linec}"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-05-28 15:09:29 +10:00
|
|
|
line_human="${line_human}${statec}Close${linec} vent in ${roomc}${tok[1]}${linec} if${oneof} $devices $verb online"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ ${tok[0]} == "modelock" ]]; then
|
|
|
|
if [[ $VALID_MODES == *\ ${tok[1]}\ * ]]; then
|
|
|
|
local col
|
|
|
|
modelock="${tok[1]}"
|
2021-12-05 16:51:14 +11:00
|
|
|
[[ $modelock == "cool" ]] && col="$coolc" || col="$heatc"
|
2021-12-04 20:24:25 +11:00
|
|
|
line_human="${line_human}Only operate the aircon in ${col}${tok[1]}${linec} mode"
|
|
|
|
else
|
2021-12-05 16:51:14 +11:00
|
|
|
errstr="${errstr}${linenum}:Invalid modelock '${tok[1]}'. Valid options are: $VALID_MODES$nl"
|
2021-12-04 20:24:25 +11:00
|
|
|
fileok=0
|
|
|
|
fi
|
|
|
|
elif [[ ${tok[0]} == "test" ]]; then
|
|
|
|
line_human="${line_human}Got test option '${roomc}${tok[1]}${linec}'"
|
|
|
|
elif [[ -n $line ]]; then
|
2021-12-05 16:51:14 +11:00
|
|
|
errstr="${errstr}${linenum}:Syntax error: ${line}$nl"
|
2021-12-04 20:24:25 +11:00
|
|
|
fileok=0
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
if [[ -n $line_human ]]; then
|
|
|
|
if [[ $ok -eq 0 ]]; then
|
2022-05-28 15:09:29 +10:00
|
|
|
line_human="${plainc}${inactc}[out-of-hours] ${linec}${line_human}"
|
|
|
|
elif [[ $thisignored -eq 1 ]]; then
|
|
|
|
line_human="${plainc}${inactc}[ignored] ${linec}${line_human}"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2021-12-05 16:51:14 +11:00
|
|
|
config_human="${config_human}- ${linec}${line_human}${plainc}$nl"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
linenum=$((linenum + 1))
|
|
|
|
done < "$CONFIGFILE"
|
|
|
|
|
|
|
|
if [[ $fileok -eq 1 ]]; then
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $show -eq 2 ]]; then
|
|
|
|
echo -e "${config_human}"
|
|
|
|
elif [[ $show -eq 1 ]]; then
|
|
|
|
info "Configuration file is ${BOLD}OK"
|
|
|
|
fi
|
|
|
|
rv=0
|
|
|
|
else
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${RED}${BOLD}fail${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
error "Configuration file is invalid:"
|
2021-12-05 16:51:14 +11:00
|
|
|
echo -e "${RED}$errstr${plainc}" | sed -e 's/^/ /'
|
2021-12-04 20:24:25 +11:00
|
|
|
rv=1
|
|
|
|
fi
|
|
|
|
return $rv
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2022-06-14 21:09:56 +10:00
|
|
|
# if we can ping ANY of the args, return ok
|
2021-06-03 09:01:36 +10:00
|
|
|
function canping() {
|
2022-06-14 21:09:56 +10:00
|
|
|
local n hname ip db host success=0 mac
|
2022-06-28 10:06:06 +10:00
|
|
|
local os arprv arpres
|
2021-12-04 20:24:25 +11:00
|
|
|
os=$(uname -s)
|
2023-04-10 19:52:05 +10:00
|
|
|
db=0
|
2022-06-28 17:16:21 +10:00
|
|
|
if [[ $db -eq 1 ]]; then
|
|
|
|
info "canping() for:"
|
|
|
|
for host in $*; do
|
|
|
|
info " - '${host}'"
|
|
|
|
done
|
|
|
|
fi
|
2022-06-14 21:09:56 +10:00
|
|
|
# get ip and clear arp
|
|
|
|
n=0
|
2021-12-04 20:24:25 +11:00
|
|
|
for host in $*; do
|
2022-06-14 21:09:56 +10:00
|
|
|
hname[$n]="$host"
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $os == "Darwin" ]]; then
|
2022-06-14 21:09:56 +10:00
|
|
|
ip[$n]=$(dscacheutil -q host -a name $host | grep ^ip_address: | awk '{ print $NF}')
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2022-06-14 21:09:56 +10:00
|
|
|
ip[$n]=$(getent hosts $host | grep -v : | awk '{ print $1 }')
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-06-14 21:09:56 +10:00
|
|
|
if [[ -n ${ip[$n]} ]]; then
|
|
|
|
arp -d ${ip[$n]} >/dev/null 2>&1
|
|
|
|
fi
|
2022-06-28 17:16:21 +10:00
|
|
|
n=$((n + 1))
|
2022-06-14 21:09:56 +10:00
|
|
|
done
|
|
|
|
|
|
|
|
# send new arp req
|
|
|
|
for n in ${!ip[@]}; do
|
|
|
|
if [[ -n ${ip[$n]} ]]; then
|
2022-06-28 17:16:21 +10:00
|
|
|
if [[ -e $ARPING ]]; then
|
|
|
|
${ARPING} -c10 -W0.2 -w4 -C1 -q ${ip[$n]} 2>/dev/null &
|
|
|
|
else
|
|
|
|
ping -c 1 -w 1 -q ${ip[$n]} 2>/dev/null &
|
|
|
|
fi
|
2022-06-14 21:09:56 +10:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
|
|
|
|
# wait for arp replies or timeout
|
|
|
|
wait
|
|
|
|
sleep 0.4
|
|
|
|
|
|
|
|
# now check entries
|
|
|
|
for n in ${!ip[@]}; do
|
2022-06-28 17:16:21 +10:00
|
|
|
[[ $db -eq 1 ]] && info " recheck ${hname[$n]} (${ip[$n]})"
|
2022-06-14 21:09:56 +10:00
|
|
|
if [[ -n ${ip[$n]} ]]; then
|
2022-06-28 10:06:06 +10:00
|
|
|
arpres=$(arp -n ${ip[$n]} 2>/dev/null)
|
2022-06-28 17:16:21 +10:00
|
|
|
arprv=$?
|
2022-06-28 10:06:06 +10:00
|
|
|
mac=$(echo "$arpres" | egrep -v "Host|xpired" | awk '{print $2}')
|
|
|
|
[[ $mac == *:* ]] && success=1
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2022-06-28 17:16:21 +10:00
|
|
|
[[ $db -eq 1 ]] && info " ${hname[$n]} (${ip[$n]}) mac is mac=$mac"
|
|
|
|
[[ $db -eq 1 ]] && info "canping() ${hname[$n]} (${ip[$n]}) is $success"
|
|
|
|
|
2022-06-14 21:09:56 +10:00
|
|
|
if [[ $success -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
return 1
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function addzone() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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"
|
2022-05-29 10:27:40 +10:00
|
|
|
zperfect[$nzones]=0
|
2021-12-04 20:24:25 +11:00
|
|
|
zproblem[$nzones]="n/a"
|
|
|
|
zaction[$nzones]="n/a"
|
|
|
|
zactionfail[$nzones]=0
|
2022-05-28 15:09:29 +10:00
|
|
|
zowner[$nzones]=$(getowner "$name") # devices which 'own' the zone - may be overwritten later
|
|
|
|
#zownerperson[$nzones]=$(getownerperson "$name") # may be overwritten later
|
|
|
|
zownerhome[$nzones]=1
|
2021-12-04 20:24:25 +11:00
|
|
|
#info "zone $name owner is [${zowner[$nzones]}]"
|
|
|
|
zignore[$nzones]=0
|
|
|
|
znomyzone[$nzones]=0
|
|
|
|
zpri[$nzones]=0
|
|
|
|
wanttemp=$(gettemprange "$name")
|
|
|
|
if [[ $wanttemp == "n/a" ]]; then
|
2022-05-28 15:09:29 +10:00
|
|
|
zwanttemp[$nzones]="n/a" # default - this will be overridden in load_config
|
|
|
|
zwantmin[$nzones]="-99" # default - this will be overridden in load_config
|
|
|
|
zwantmax[$nzones]="99" # default - this will be overridden in load_config
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
|
|
|
zwanttemp[$nzones]="$wanttemp"
|
|
|
|
zwantmin[$nzones]="${wanttemp%-*}"
|
|
|
|
zwantmax[$nzones]="${wanttemp#*-}"
|
|
|
|
fi
|
|
|
|
|
|
|
|
nzones=$((nzones + 1))
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function getcol() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local col
|
|
|
|
case $1 in
|
|
|
|
"off") col="$GREY";;
|
|
|
|
"cool") col="$CYAN";;
|
|
|
|
"heat") col="$RED";;
|
|
|
|
*) col="$PLAIN";;
|
|
|
|
esac
|
|
|
|
echo $col
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function gen_config() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function get_aircon_info() {
|
2023-09-03 16:27:53 +10:00
|
|
|
local jsoninfo url state
|
2021-12-04 20:24:25 +11:00
|
|
|
profile "query aircon"
|
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Querying aircon... ${PLAIN}"
|
2023-10-22 12:19:33 +11:00
|
|
|
url="${AIRCON_URL}/getSystemData"
|
|
|
|
jsoninfo=$(curl -s "$url" 2>/dev/null)
|
2024-05-16 18:47:25 +10:00
|
|
|
if [[ $? -ne 0 ]]; then
|
|
|
|
error "get_aircon_info() failed to reach ${AIRCON_URL}/getSystemData endpoint"
|
|
|
|
exit 1;
|
|
|
|
fi
|
|
|
|
echo "$jsoninfo" | jq . &>/dev/null
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
|
|
error "${AIRCON_URL}/getSystemData returned bad json: $jsoninfo"
|
|
|
|
exit 1;
|
|
|
|
fi
|
2023-10-22 12:19:33 +11:00
|
|
|
zones=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.zones[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ')
|
|
|
|
state=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.state' | tr -d '" ')
|
|
|
|
if [[ $state == "off" ]]; then
|
|
|
|
airconmode="off"
|
2023-09-03 16:27:53 +10:00
|
|
|
else
|
2023-10-22 12:19:33 +11:00
|
|
|
airconmode=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.mode' | tr -d '" ')
|
2023-09-03 16:27:53 +10:00
|
|
|
fi
|
2023-10-22 12:19:33 +11:00
|
|
|
airconmyzoneid=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.myZone ' | tr -d '" ')
|
2021-12-04 20:24:25 +11:00
|
|
|
nzones=0
|
|
|
|
for line in $zones; do
|
|
|
|
IFS=',' read -ra tok <<< "$line"
|
|
|
|
addzone "${tok[0]}" "${tok[1]}" "${tok[2]}" "${tok[3]}" "${tok[4]}"
|
|
|
|
done
|
2024-05-16 18:47:25 +10:00
|
|
|
if [[ $nzones -eq 0 ]]; then
|
|
|
|
error "get_aircon_info() found no zones"
|
|
|
|
exit 1;
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
airconmyzone=$(getnamefromid $airconmyzoneid)
|
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}"
|
|
|
|
profile "query aircon"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
function show_aircon_status() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local zonestr zonecol settempcol actioncol thiswantcol thisstate thisstateform
|
2022-05-28 15:09:29 +10:00
|
|
|
local actualtempformat x powercol lockcol actionstr
|
2021-12-04 20:24:25 +11:00
|
|
|
local FORMAT1 FORMAT2 FORMATHOT FORMATCOLD FORMATOK CLOSEDFORM OPENFORM
|
2022-05-28 15:09:29 +10:00
|
|
|
local ownercol ownerform
|
2021-12-04 20:24:25 +11:00
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
FORMAT1="${BOLD}%-16s%-9s%-8s%-7s%-7s%-7s%s${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
FORMAT2="${UNDERLINE}${FORMAT1}${PLAIN}"
|
|
|
|
FORMATHOT="${RED}%-7s${PLAIN}"
|
|
|
|
FORMATCOLD="${CYAN}%-7s${PLAIN}"
|
|
|
|
FORMATOK="${WHITE}%-7s${PLAIN}"
|
2022-05-29 10:27:40 +10:00
|
|
|
FORMATPERFECT="${GREEN}%-7s${PLAIN}"
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
printf "$FORMAT1\n" "" "Valid" "" "Set" "Actual" "Owner" "Proposed "
|
|
|
|
printf "$FORMAT2\n" "Zone" "Temp" "State" "Temp" "Temp" "Home" "Action "
|
2021-12-04 20:24:25 +11:00
|
|
|
for x in ${!zname[@]}; do
|
|
|
|
if [[ ${zproblem[$x]} == "too_hot" ]]; then
|
2022-05-28 15:09:29 +10:00
|
|
|
actualtempformat="${FORMATHOT}"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ ${zproblem[$x]} == "too_cold" ]]; then
|
2022-05-28 15:09:29 +10:00
|
|
|
actualtempformat="${FORMATCOLD}"
|
2022-05-29 10:27:40 +10:00
|
|
|
elif [[ ${zperfect[$x]} -eq 1 ]]; then
|
|
|
|
actualtempformat="${FORMATPERFECT}"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2022-05-28 15:09:29 +10:00
|
|
|
actualtempformat="${FORMATOK}"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
if [[ ${airconmode} == "off" ]]; then
|
|
|
|
thisstateform="${CLOSEDFORM}"
|
|
|
|
thisstate="<off>"
|
|
|
|
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
|
2022-05-28 15:09:29 +10:00
|
|
|
|
|
|
|
# override
|
|
|
|
if [[ ${zignore[$x]} -eq 1 ]]; then
|
|
|
|
thiswant="ignore"
|
|
|
|
thiswantcol="$GREY"
|
|
|
|
fi
|
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
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 [[ $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
|
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
if [[ -z ${zowner[$x]} ]]; then
|
|
|
|
ownercol="$GREY"
|
|
|
|
ownerstr="n/a"
|
|
|
|
elif [[ ${zownerhome[$x]} -eq 1 ]]; then
|
|
|
|
ownercol="$PLAIN"
|
|
|
|
ownerstr="yes"
|
|
|
|
else
|
|
|
|
ownercol="$GREY"
|
|
|
|
ownerstr="no"
|
|
|
|
fi
|
|
|
|
|
|
|
|
actionstr="${zaction[$x]}"
|
|
|
|
#if [[ ${zaction[$x]} == "n/a" && ${zignore[$x]} -eq 1 ]]; then
|
|
|
|
# actionstr="${actionstr} (zone ignored)"
|
|
|
|
#fi
|
|
|
|
|
|
|
|
printf "$zonecol%-16s$PLAIN$thiswantcol%-9s$PLAIN$thisstateform$settempcol%-7s$PLAIN${actualtempformat}${ownercol}%-7s${PLAIN}$actioncol%s$PLAIN\n" "${zonestr}" "${thiswant}" "${thisstate}" "${zsettemp[$x]}" "${ztemp[$x]}" "$ownerstr" "${actionstr}"
|
2021-12-04 20:24:25 +11:00
|
|
|
done
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-09 08:47:07 +11:00
|
|
|
# generate textual description of global problem
|
|
|
|
function describe_globprob() {
|
|
|
|
[[ -z $globprob ]] && return 1;
|
|
|
|
if [[ $globprob == too_* ]]; then
|
|
|
|
echo "$limit or more zones are ${globprob/_/ }"
|
|
|
|
elif [[ $globprob == "not_needed" ]]; then
|
|
|
|
echo "The system is on but all zones at optimal temperature"
|
2024-05-16 18:47:25 +10:00
|
|
|
elif [[ $globprob == "constant_close" ]]; then
|
|
|
|
echo "All other zones are already closed"
|
2023-12-09 08:47:07 +11:00
|
|
|
else
|
|
|
|
echo "_unknown_globprob_:$globprob"
|
|
|
|
fi
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
function show_analysis() { # returns 1 if all good and nothing to show
|
2021-12-04 20:24:25 +11:00
|
|
|
local count x ostr
|
2023-12-09 08:47:07 +11:00
|
|
|
local amode="normal"
|
|
|
|
|
|
|
|
if [[ $1 == "-t" ]]; then
|
|
|
|
mode="telegram"
|
|
|
|
shift
|
|
|
|
fi
|
|
|
|
if [[ $mode != "telegram" ]]; then
|
|
|
|
echo -e "${UNDERLINE}Analysis:${PLAIN}"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
count=0
|
|
|
|
for x in ${!zproblem[@]}; do
|
2023-12-09 08:47:07 +11:00
|
|
|
znowners=$(wc -w <<< "${zowner[$x]}" | bc)
|
|
|
|
zowners=$(sed -r 's/^ +//;s/ +$//;s/ +/, /g' <<< "${zowner[$x]}")
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ ${zproblem[$x]} != "n/a" ]]; then
|
|
|
|
if [[ ${zproblem[$x]} == "owner_not_home" ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
if [[ $znowners -gt 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
ostr="owners are"
|
|
|
|
else
|
|
|
|
ostr="owner is"
|
|
|
|
fi
|
2023-12-09 08:47:07 +11:00
|
|
|
echo "- The zone '${zname[$x]}' is open but its $ostr not home (${zowners})"
|
2021-12-04 20:24:25 +11:00
|
|
|
elif [[ ${zproblem[$x]} =~ force_ ]]; then
|
|
|
|
what=${zproblem[$x]##*_}
|
|
|
|
[[ $what == "close" ]] && what="${what}d"
|
2023-12-09 08:47:07 +11:00
|
|
|
echo "- The zone '${zname[$x]}' should be $what at this time"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2022-05-28 15:09:29 +10:00
|
|
|
if [[ ${zownerhome[$x]} -ne 1 ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
if [[ $znowners -gt 1 ]]; then
|
|
|
|
append1=", but none of its owners ($zowners) are online"
|
2022-05-28 15:09:29 +10:00
|
|
|
else
|
|
|
|
append1=", but ${zowner[$x]} isn't online"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
append1=""
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ $constant == ${zname[$x]} ]]; then
|
2022-05-28 15:09:29 +10:00
|
|
|
append2=" (constant zone)"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2022-05-28 15:09:29 +10:00
|
|
|
append2=""
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2023-12-09 08:47:07 +11:00
|
|
|
echo "- The zone '${zname[$x]}' is ${zproblem[$x]/_/ }${append1}${append2}"
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
|
|
|
count=$((count + 1))
|
|
|
|
fi
|
|
|
|
done
|
2023-12-09 08:47:07 +11:00
|
|
|
|
|
|
|
if [[ -n $globprob ]]; then
|
|
|
|
echo "- $(describe_globprob)"
|
|
|
|
fi
|
|
|
|
if [[ $count -eq 0 && -z $globprob ]]; then
|
|
|
|
if [[ $mode != "telegram" ]]; then
|
|
|
|
echo -e "${GREEN}All is good!${PLAIN}"
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2023-12-09 08:47:07 +11:00
|
|
|
[[ $count -eq 0 && -z $globprob ]] && return 1
|
|
|
|
return 0;
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2023-12-11 23:02:15 +11:00
|
|
|
function killfile_active() { # returns true if killfile will stop us
|
2023-11-25 13:12:56 +11:00
|
|
|
local val now
|
|
|
|
if [[ ! -f ${KILLFILE} ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
2023-12-15 06:29:12 +11:00
|
|
|
val=$(head -1 "${KILLFILE}")
|
2023-12-11 23:02:15 +11:00
|
|
|
[[ -z $val ]] && return 0
|
2023-11-25 13:12:56 +11:00
|
|
|
now=$(date +%s)
|
|
|
|
if [[ $val -le $now ]]; then
|
|
|
|
# killfile expired
|
|
|
|
rm -f "${KILLFILE}"
|
2023-12-11 23:02:15 +11:00
|
|
|
if [[ -n $expirenotifyfile ]]; then
|
|
|
|
echo "$expirenotifytext" > "$expirenotifyfile"
|
|
|
|
fi
|
2023-11-25 13:12:56 +11:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function show_proposed_commands() {
|
2021-12-04 20:24:25 +11:00
|
|
|
local str x maxlen count cmdformat fullcmd
|
|
|
|
str="Proposed commands"
|
|
|
|
echo -e "${UNDERLINE}${str}:${PLAIN}"
|
|
|
|
|
|
|
|
if [[ $nairconcommands -gt 0 ]]; then
|
2023-11-25 13:12:56 +11:00
|
|
|
if killfile_active; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
cmdformat="%-$((maxlen + 3))s"
|
|
|
|
count=0
|
|
|
|
for x in ${!airconcmd[@]}; do
|
|
|
|
fullcmd="myair $AIRCON_IP ${airconcmd[$x]}"
|
|
|
|
printf -- "$cmdformat" "$fullcmd"
|
2022-05-29 10:27:40 +10:00
|
|
|
[[ -n ${airconcomment[$x]} ]] && printf " $GREEN$BOLD# $PLAIN$GREEN%s$PLAIN\n" "${airconcomment[$x]}" || echo
|
2021-12-04 20:24:25 +11:00
|
|
|
count=$((count + 1))
|
|
|
|
done
|
|
|
|
[[ $count -eq 0 ]] && echo -e "${GREY}n/a${PLAIN}"
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2023-09-03 16:27:53 +10:00
|
|
|
function combine_commands() {
|
|
|
|
local x id2 basefile tfile combinejq jcmd jurl
|
|
|
|
combinejq=".[0]"
|
|
|
|
if [[ ${#airconjcmd} -eq 0 ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
basefile=$(mktemp /tmp/$$.json.base.XXXXXX)
|
|
|
|
[[ -z $basefile ]] && { error "couldnt create base json file" >&2; exit 1; }
|
|
|
|
|
|
|
|
echo -e "{\n\"aircons\": {\n\"ac1\": {\n\"info\": {\n},\n\"zones\": {\n" >${basefile}
|
|
|
|
|
|
|
|
for x in ${zid[@]}; do
|
|
|
|
id2=$(printf "%02d" $x)
|
|
|
|
echo " \"z${id2}\": { }," >>${basefile}
|
|
|
|
done
|
|
|
|
sed -i '$s/,$//' ${basefile}
|
|
|
|
echo -e "}\n}\n}\n}\n" >> ${basefile}
|
|
|
|
|
|
|
|
for x in ${!airconjcmd[@]}; do
|
|
|
|
tfile[$x]=$(mktemp /tmp/$$.json.$x.XXXXXX)
|
|
|
|
[[ -z ${tfile[$x]} ]] && { error "couldnt create temp file" >&2; exit 1; }
|
|
|
|
echo "${airconjcmd[$x]}" >${tfile[$x]}
|
|
|
|
combinejq="${combinejq} * .[$((x + 1))]"
|
|
|
|
done
|
|
|
|
|
2023-09-03 20:59:35 +10:00
|
|
|
jcmd=$($JQ -s "$combinejq" $basefile ${tfile[@]} )
|
2023-09-03 16:27:53 +10:00
|
|
|
[[ $? -ne 0 ]] && { error "couldnt merge json command files " >&2; exit 1; }
|
|
|
|
[[ -z $jcmd ]] && { error "got empty merged json command" >&2; exit 1; }
|
|
|
|
jurl="${AIRCON_URL}/setAircon?json=$jcmd"
|
|
|
|
|
|
|
|
for x in ${tfile[@]};
|
|
|
|
do rm -f "${x}"
|
|
|
|
done
|
|
|
|
rm -f "$basefile"
|
|
|
|
|
|
|
|
echo "$jurl" | tr -d '\n '
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
2023-12-09 08:47:07 +11:00
|
|
|
# note: this function is no longer used
|
2023-12-02 09:51:56 +11:00
|
|
|
function reword_problem() { #1="problem text"
|
|
|
|
local orig="$1" new=""
|
|
|
|
if [[ $orig == *" is too "* ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
new=$(sed -r 's/^([A-Za-z]+) is too ([A-Za-z]+)/the zone "\1" was too \2/' <<<"$orig")
|
2023-12-02 09:51:56 +11:00
|
|
|
elif [[ $orig == *" is owner not_home "* ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
new=$(sed -r 's/^([A-Za-z]+) is .*/the owner of the zone "\1" was not at home/' <<<"$orig")
|
2023-12-02 09:51:56 +11:00
|
|
|
elif [[ $orig == *" is force close"* ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
new=$(sed -r 's/^([A-Za-z]+) is .*/the zone "\1" should be closed at this time/' <<<"$orig")
|
2023-12-02 09:51:56 +11:00
|
|
|
elif [[ $orig == *" is n/a"* ]]; then
|
2023-12-09 08:47:07 +11:00
|
|
|
## wrong! n/a means there is a globprob
|
|
|
|
new=$(sed -r 's/^([A-Za-z]+) is .*/the zone "\1" should be the "myzone" at this time/' <<<"$orig")
|
2023-12-02 09:51:56 +11:00
|
|
|
else
|
|
|
|
new="$orig"
|
|
|
|
fi
|
|
|
|
new=$(sed 's/&/%26/g' <<<"$new")
|
|
|
|
echo "$new"
|
|
|
|
}
|
|
|
|
|
|
|
|
function telegram_send() { #1=msg
|
|
|
|
local res msg="$1"
|
|
|
|
#action "sending to telegram: curl -s --data \"text=$msg\" --data \"chat_id=$TELEGRAM_CHAT\" --data \"parse_mode=markdown\" 'https://api.telegram.org/bot'$TELEGRAM_TOKEN'/sendMessage' "
|
|
|
|
res=$(curl -s --data "text=$msg" --data "chat_id=$TELEGRAM_CHAT" --data "parse_mode=markdown" 'https://api.telegram.org/bot'$TELEGRAM_TOKEN'/sendMessage' 2>&1)
|
2023-12-09 08:47:07 +11:00
|
|
|
|
|
|
|
if [[ $cronmode -eq 1 ]]; then
|
|
|
|
echo "telegram_send: text=[$msg]"
|
|
|
|
echo "telegram_send: curl=curl -s --data \"text=$msg\" --data \"chat_id=$TELEGRAM_CHAT\" --data \"parse_mode=markdown\" \'https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage\'"
|
|
|
|
echo "telegram_send: res=[$res]"
|
|
|
|
fi
|
2023-12-02 09:51:56 +11:00
|
|
|
#action "telegram result: $res"
|
|
|
|
}
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function run_commands() {
|
2023-09-03 16:27:53 +10:00
|
|
|
local x tfile combinejq jcmd jurl res jqres
|
2023-12-02 09:51:56 +11:00
|
|
|
local thisprob thisfix prevprob
|
|
|
|
local botwords="" txt fixnum
|
2023-09-03 16:27:53 +10:00
|
|
|
|
2021-12-04 20:24:25 +11:00
|
|
|
for x in ${!airconcmd[@]}; do
|
2023-09-03 16:27:53 +10:00
|
|
|
#echo RUNNING myair $AIRCON_IP ${airconcmd[$x]}
|
|
|
|
|
2022-05-29 10:27:40 +10:00
|
|
|
[[ -n ${airconcomment[$x]} ]] && action "${airconcomment[$x]}"
|
2021-12-04 20:24:25 +11:00
|
|
|
influx_insert "INSERT aircon action=\"${airconcomment[$x]}\",comment=\"${airconproblem[$x]}\""
|
|
|
|
done
|
2023-09-03 16:27:53 +10:00
|
|
|
|
2023-10-22 12:19:33 +11:00
|
|
|
jurl=$(combine_commands)
|
2023-12-02 09:51:56 +11:00
|
|
|
if [[ $? -eq 0 ]]; then
|
|
|
|
res=$(curl -s -g "$jurl" 3>/dev/null)
|
|
|
|
jqres=$(echo "$res" | $JQ -r '.ack' 2>/dev/null)
|
|
|
|
if [[ $jqres != "true" ]]; then
|
|
|
|
error "Myair API call failed:"
|
|
|
|
echo -e "$RED curl -s -g $jurl$PLAIN"
|
|
|
|
echo -e "$RED Result:"
|
|
|
|
echo "$jqres" | sed 's/_^/ /'
|
|
|
|
return 1
|
|
|
|
fi
|
2023-09-03 16:27:53 +10:00
|
|
|
fi
|
2023-12-02 09:51:56 +11:00
|
|
|
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2023-12-02 09:51:56 +11:00
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
function profile() {
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
# poplulates glpbals:
|
|
|
|
# failedcmds
|
|
|
|
# influxrv
|
|
|
|
function influx_clear() {
|
2021-12-04 20:24:25 +11:00
|
|
|
failedcmds=""
|
|
|
|
influxrv=0
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# poplulates glpbals:
|
|
|
|
# failedcmds
|
|
|
|
# influxrv
|
|
|
|
function influx_insert() { # $1 == cmd
|
2021-12-04 20:24:25 +11:00
|
|
|
local cmd thisrv
|
|
|
|
if [[ -z ${influx} ]]; then
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
cmd="$1"
|
|
|
|
if [[ $DOIT -eq 1 ]]; then
|
2022-01-16 20:35:49 +11:00
|
|
|
${influx} -host "$influxhost" -database "$influxdb" -execute "$cmd"
|
2021-12-04 20:24:25 +11:00
|
|
|
else
|
2022-01-16 20:35:49 +11:00
|
|
|
echo "${influx} -host "$influxhost" -database $influxdb -execute $cmd"
|
2021-12-04 20:24:25 +11:00
|
|
|
thisrv=0
|
|
|
|
fi
|
|
|
|
thisrv=$?
|
|
|
|
influxrv=$((influxrv + $thisrv))
|
|
|
|
if [[ $thisrv -ne 0 ]]; then
|
|
|
|
failedcmds="$failedcmds$cmd\n"
|
|
|
|
fi
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
# poplulates glpbals:
|
|
|
|
# influx
|
|
|
|
# influxdb
|
|
|
|
function influx_init() { # $1 == dbname
|
2021-12-04 20:24:25 +11:00
|
|
|
local dbfound
|
|
|
|
influx=$(which influx 2>/dev/null)
|
|
|
|
influxdb="$1"
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
|
|
error "influx executable not found in path."
|
|
|
|
return 1
|
|
|
|
fi
|
2022-01-16 20:35:49 +11:00
|
|
|
dbfound=$(${influx} -host "$influxhost" -database "$influxdb" -execute "SHOW DATABASES" | grep -w ^${influxdb})
|
2021-12-04 20:24:25 +11:00
|
|
|
if [[ -z $dbfound ]]; then
|
2022-01-16 20:35:49 +11:00
|
|
|
error "Couldn't find influx database '$influxdb' on host $influxhost"
|
2021-12-04 20:24:25 +11:00
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
influx_clear
|
|
|
|
return 0
|
2021-06-03 09:01:36 +10:00
|
|
|
}
|
|
|
|
|
2023-12-09 08:47:07 +11:00
|
|
|
function show_telegram_output() {
|
|
|
|
local botwords="" atext fixnum=1 thisprob thisfix
|
|
|
|
|
|
|
|
# get analysis text in telegram mode
|
|
|
|
atext=$(show_analysis -t)
|
|
|
|
[[ $? -ne 0 ]] && return 1;
|
|
|
|
|
|
|
|
# replace newlines
|
|
|
|
atext="$(sed ':begin;$!N;s/\n/%0a/;tbegin' <<<"$atext")"
|
|
|
|
# replace ampersands
|
|
|
|
atext=$(sed 's/&/%26/g' <<<"${atext}")
|
2021-06-03 09:01:36 +10:00
|
|
|
|
2023-12-09 08:47:07 +11:00
|
|
|
if [[ $? -eq 0 ]]; then
|
|
|
|
botwords="I noticed that:%0a"
|
|
|
|
botwords="${botwords}${atext}%0a%0a"
|
|
|
|
botwords="${botwords}I'm going to do this to fix it:%0a"
|
|
|
|
fixnum=1
|
|
|
|
for x in ${!airconcmd[@]}; do
|
|
|
|
thisprob=${airconproblem[$x]}
|
|
|
|
thisfix=$(sed 's/&/%26/g' <<<"${airconcomment[$x]}")
|
|
|
|
if [[ $cronmode -eq 1 ]]; then
|
|
|
|
echo "telegram_debug: thisprob=[$thisprob]"
|
|
|
|
echo "telegram_debug: airconcomment[$x]=[${airconcomment[$x]}]"
|
|
|
|
echo "telegram_debug: thisfix=[$thisfix]"
|
|
|
|
fi
|
|
|
|
botwords="$botwords$(printf ' %d. %s%%0a' $fixnum "$thisfix")"
|
|
|
|
fixnum=$((fixnum + 1))
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
[[ -n $botwords && $fixnum -gt 1 ]] && telegram_send "$botwords"
|
|
|
|
}
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
p_now=$(date +%s)
|
|
|
|
p_last=$p_now
|
|
|
|
p_str=""
|
|
|
|
|
|
|
|
CONFIGFILE=${DEFAULT_CONFIGFILE}
|
|
|
|
KILLFILE=${DEFAULT_KILLFILE}
|
|
|
|
AIRCON_IP=${DEFAULT_AIRCON_IP}
|
|
|
|
|
|
|
|
airconmode="unknown"
|
|
|
|
airconmyzoneid="n/a"
|
|
|
|
airconmyzone="n/a"
|
|
|
|
globprob=""
|
|
|
|
nairconcommands=0
|
|
|
|
ntempranges=0
|
|
|
|
nadj=0
|
|
|
|
nowners=0
|
|
|
|
npeople=0
|
|
|
|
tolerance_l=${DEFAULT_TOLERANCE}
|
|
|
|
tolerance_h=${DEFAULT_TOLERANCE}
|
|
|
|
constant=""
|
|
|
|
|
|
|
|
DOIT=0
|
|
|
|
makeconfig=0
|
|
|
|
modelock="n/a"
|
|
|
|
cronmode=0
|
|
|
|
logmode=0 #0=none, 1=csv_file, 2=local influxdb
|
|
|
|
influxdb=""
|
2022-01-16 20:35:49 +11:00
|
|
|
influxhost="127.0.0.1"
|
2022-02-02 14:09:02 +11:00
|
|
|
showwho=0 # 1 = show people, 2 = show owners
|
2021-06-03 09:01:36 +10:00
|
|
|
limit=$DEFAULTLIMIT
|
|
|
|
profiler=0
|
|
|
|
csvfile="$DEFAULT_CSVFILE"
|
2021-12-04 20:24:25 +11:00
|
|
|
sanitycheck=0
|
2021-12-05 16:51:14 +11:00
|
|
|
RULEFORMAT=ansi
|
2022-05-29 21:36:08 +10:00
|
|
|
robtest=0
|
2023-12-02 09:51:56 +11:00
|
|
|
USETELEGRAM=""
|
|
|
|
TELEGRAM_FILE=""
|
|
|
|
TELEGRAM_CHAT=""
|
|
|
|
TELEGRAM_TOKEN=""
|
2021-06-03 09:01:36 +10:00
|
|
|
|
|
|
|
# check for config file option first
|
|
|
|
if [[ $* == *-f\ * ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
cf=$(echo "$*" | sed -e 's/.*-f //;s/ .*//')
|
2022-05-29 10:27:40 +10:00
|
|
|
if [[ -n $cf ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
CONFIGFILE="$cf"
|
|
|
|
fi
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
ALLARGS=""
|
|
|
|
if [[ -e $CONFIGFILE ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# load options from file...
|
|
|
|
ALLARGS=$(egrep "^options " $CONFIGFILE | sed -e 's/^options //' | tr '\n' ' ')
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
ALLARGS="$ALLARGS $*"
|
|
|
|
|
2023-12-11 23:02:15 +11:00
|
|
|
expirenotifyfile=""
|
|
|
|
expirenotifytext=""
|
2024-10-16 14:44:21 +11:00
|
|
|
FAKESTRING=""
|
2023-12-11 23:02:15 +11:00
|
|
|
|
2024-10-16 14:44:21 +11:00
|
|
|
optstring="aA:bcD:e:E:f:F:g:hHi:I:k:l:Lo:pmRsSt:T:wWy"
|
2021-06-03 09:01:36 +10:00
|
|
|
while getopts "$optstring" i $ALLARGS; do
|
2021-12-04 20:24:25 +11:00
|
|
|
case "$i" in
|
2023-05-27 06:42:21 +10:00
|
|
|
a)
|
2022-06-28 10:06:06 +10:00
|
|
|
ARPING=${OPTARG}
|
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
A)
|
|
|
|
influxdb="$OPTARG"
|
|
|
|
;;
|
2023-04-10 19:52:05 +10:00
|
|
|
b)
|
2023-04-10 21:18:10 +10:00
|
|
|
RULEDB=1
|
2023-04-10 19:52:05 +10:00
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
c)
|
|
|
|
enable_cronmode
|
|
|
|
;;
|
2023-09-03 16:27:53 +10:00
|
|
|
D)
|
|
|
|
influxhost="${OPTARG}"
|
|
|
|
;;
|
2023-12-11 23:02:15 +11:00
|
|
|
e)
|
|
|
|
expirenotifyfile="$OPTARG"
|
|
|
|
;;
|
|
|
|
E)
|
|
|
|
expirenotifytext="$OPTARG"
|
|
|
|
;;
|
2023-09-03 16:27:53 +10:00
|
|
|
f)
|
|
|
|
CONFIGFILE=${OPTARG}
|
|
|
|
;;
|
2024-10-16 14:44:21 +11:00
|
|
|
F)
|
|
|
|
FAKESTRING="${FAKESTRING} ${OPTARG}"
|
|
|
|
;;
|
2023-12-02 09:51:56 +11:00
|
|
|
g)
|
|
|
|
USETELEGRAM=1
|
|
|
|
TELEGRAM_FILE=${OPTARG}
|
|
|
|
;;
|
2021-12-04 20:24:25 +11:00
|
|
|
h)
|
|
|
|
usage;
|
|
|
|
exit 1;
|
|
|
|
;;
|
2021-12-05 16:51:14 +11:00
|
|
|
H)
|
|
|
|
RULEFORMAT=html
|
|
|
|
;;
|
2021-12-04 20:24:25 +11:00
|
|
|
i)
|
|
|
|
AIRCON_IP=${OPTARG}
|
|
|
|
;;
|
|
|
|
I)
|
|
|
|
logmode=2
|
2022-01-16 20:35:49 +11:00
|
|
|
influxdb="$OPTARG"
|
2021-12-04 20:24:25 +11:00
|
|
|
;;
|
|
|
|
k)
|
|
|
|
KILLFILE=${OPTARG}
|
|
|
|
;;
|
|
|
|
l)
|
|
|
|
limit=${OPTARG}
|
|
|
|
;;
|
|
|
|
L)
|
|
|
|
logmode=1
|
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
m)
|
|
|
|
makeconfig=1
|
2021-12-04 20:24:25 +11:00
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
o)
|
|
|
|
csvfile="$OPTARG"
|
2022-05-29 21:36:08 +10:00
|
|
|
;;
|
2021-12-04 20:24:25 +11:00
|
|
|
p)
|
2023-09-03 20:59:35 +10:00
|
|
|
profiler=1
|
2021-12-04 20:24:25 +11:00
|
|
|
info "Profiler mode enabled"
|
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
R)
|
|
|
|
robtest=1
|
2021-12-04 20:24:25 +11:00
|
|
|
;;
|
|
|
|
s)
|
|
|
|
sanitycheck=1
|
|
|
|
;;
|
|
|
|
S)
|
|
|
|
sanitycheck=2
|
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
t)
|
|
|
|
tolerance_l=${OPTARG}
|
|
|
|
;;
|
|
|
|
T)
|
|
|
|
tolerance_h=${OPTARG}
|
2021-12-04 20:24:25 +11:00
|
|
|
;;
|
|
|
|
w)
|
|
|
|
showwho=1
|
|
|
|
;;
|
2022-02-02 14:09:02 +11:00
|
|
|
W)
|
|
|
|
showwho=2
|
|
|
|
;;
|
2023-09-03 20:59:35 +10:00
|
|
|
y)
|
|
|
|
DOIT=1
|
|
|
|
;;
|
2021-12-04 20:24:25 +11:00
|
|
|
*)
|
|
|
|
usage;
|
2023-09-03 20:59:35 +10:00
|
|
|
exit 1;
|
2021-12-04 20:24:25 +11:00
|
|
|
;;
|
|
|
|
esac
|
2021-06-03 09:01:36 +10:00
|
|
|
done
|
|
|
|
shift $((OPTIND - 1))
|
|
|
|
|
2023-09-03 16:27:53 +10:00
|
|
|
AIRCON_URL="http://${AIRCON_IP}:2025"
|
|
|
|
|
2023-12-11 23:02:15 +11:00
|
|
|
if [[ -n $expirenotifyfile && -z $expirenotifytext ]]; then
|
|
|
|
error "Cannot use -e option without -E."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2022-06-28 10:06:06 +10:00
|
|
|
if [[ ! -e $ARPING ]]; then
|
2023-09-03 20:59:35 +10:00
|
|
|
warn "arping binary '$ARPING' not found, will use ping instead"
|
2022-06-28 10:06:06 +10:00
|
|
|
fi
|
|
|
|
|
2022-01-16 20:35:49 +11:00
|
|
|
if [[ -n $influxdb ]]; then
|
|
|
|
influx_init "$influxdb" || exit 1
|
|
|
|
fi
|
|
|
|
|
2023-12-02 09:51:56 +11:00
|
|
|
if [[ $USETELEGRAM -eq 1 ]]; then
|
|
|
|
if [[ -z $TELEGRAM_FILE || ! -f $TELEGRAM_FILE ]]; then
|
|
|
|
error "Telegram auth file '$TELEGRAM_FILE' doesn't exist."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
TELEGRAM_TOKEN=$(awk NF $TELEGRAM_FILE | head -1)
|
|
|
|
TELEGRAM_CHAT=$(awk NF $TELEGRAM_FILE | tail -1)
|
|
|
|
if [[ -z $TELEGRAM_TOKEN ]]; then
|
|
|
|
error "Telegram token is empty. Check that auth file '$TELEGRAM_FILE' first line is token, second line is chat id."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [[ -z $TELEGRAM_CHAT ]]; then
|
|
|
|
error "Telegram chat id is empty. Check that auth file '$TELEGRAM_FILE' first line is token, second line is chat id."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
if [[ $makeconfig -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
2023-10-22 12:19:33 +11:00
|
|
|
JQ=$(which jq 2>/dev/null)
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
|
|
error "Can't find jq executable in path."
|
|
|
|
exit 1
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
2022-05-28 15:09:29 +10:00
|
|
|
# Must do this BEFORE parsing the config file, otherwise
|
|
|
|
# we can't resolve zone names.
|
|
|
|
get_aircon_info
|
|
|
|
|
|
|
|
if [[ -e $CONFIGFILE ]]; then
|
|
|
|
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
|
|
|
|
fi
|
|
|
|
|
2024-10-16 14:44:21 +11:00
|
|
|
# fake input for testing
|
|
|
|
for x in ${FAKESTRING}; do
|
|
|
|
fake_name="${x%%:*}"
|
|
|
|
fake_wanttemp="${x##*:}"
|
|
|
|
fake_idx=-1
|
|
|
|
for zi in ${!zname[@]}; do
|
|
|
|
if [[ ${zname[zi]^^} == ${fake_name^^} ]]; then
|
|
|
|
fake_idx=$zi
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [[ ${fake_idx} -eq -1 ]]; then
|
|
|
|
error "Unknown zone '${fake_name}' in -f argument '${x}'"
|
|
|
|
exit 1;
|
|
|
|
fi
|
|
|
|
ztemp[$fake_idx]="$fake_wanttemp"
|
|
|
|
info "Faking zone '${fake_name}' temp to ${fake_wanttemp}"
|
|
|
|
done
|
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
# ping all hosts in background to populate arp table
|
2022-06-14 21:09:56 +10:00
|
|
|
#for x in ${devices}; do
|
|
|
|
# ping -c1 -w1 -n -q $ip >/dev/null 2>&1 &
|
|
|
|
#done
|
|
|
|
#wait
|
2021-06-03 09:01:36 +10:00
|
|
|
|
2022-06-28 17:16:21 +10:00
|
|
|
#if [[ $robtest -eq 1 ]]; then
|
|
|
|
# for x in ${!zname[@]}; do
|
|
|
|
# echo "zone ${zname[$x]} owner is [${zowner[$x]}]"
|
|
|
|
# done
|
|
|
|
# exit 1
|
|
|
|
#fi
|
2022-05-29 21:36:08 +10:00
|
|
|
|
2021-06-03 09:01:36 +10:00
|
|
|
if [[ $showwho -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# get max phone name length
|
|
|
|
maxlen=1
|
|
|
|
for x in ${pname[@]}; do
|
|
|
|
[[ ${#x} -gt $maxlen ]] && maxlen=$((${#x} + 3))
|
|
|
|
done
|
2022-06-28 10:06:06 +10:00
|
|
|
maxlen=$((maxlen + 1))
|
2021-12-04 20:24:25 +11:00
|
|
|
# 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
|
2022-05-28 15:09:29 +10:00
|
|
|
if canping ${pdev[$x]}; then
|
2021-12-04 20:24:25 +11:00
|
|
|
thisform="$HFORMAT"
|
|
|
|
str="At home"
|
|
|
|
else
|
|
|
|
thisform="$AFORMAT"
|
|
|
|
str="Out of the house"
|
|
|
|
fi
|
|
|
|
printf "$thisform" "${pname[$x]}" "$str"
|
|
|
|
done
|
|
|
|
echo
|
|
|
|
exit 0
|
2022-02-02 14:09:02 +11:00
|
|
|
elif [[ $showwho -eq 2 ]]; then
|
2022-06-14 21:09:56 +10:00
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Querying zone owners... ${PLAIN}"
|
2022-02-02 14:09:02 +11:00
|
|
|
# get max device hostname length
|
|
|
|
maxlen=1
|
|
|
|
for x in ${ownerhost[@]}; do
|
|
|
|
[[ ${#x} -gt $maxlen ]] && maxlen=$((${#x} + 3))
|
|
|
|
done
|
|
|
|
# get a list of all devices
|
2022-05-31 19:20:27 +10:00
|
|
|
TFORMAT="${BOLD}${UNDERLINE}%-${maxlen}s%-16s%s${PLAIN}\n"
|
|
|
|
HFORMAT="%-${maxlen}s${GREEN}%-16s${PLAIN}%s\n"
|
|
|
|
AFORMAT="%-${maxlen}s${RED}%-16s${PLAIN}%s\n"
|
2022-02-02 14:09:02 +11:00
|
|
|
alldevs=$(echo "${ownerhost[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
|
2022-06-14 21:09:56 +10:00
|
|
|
|
2022-06-28 10:06:06 +10:00
|
|
|
n=0
|
2022-06-14 21:09:56 +10:00
|
|
|
for x in $alldevs; do
|
2022-06-28 17:16:21 +10:00
|
|
|
canping ${x} 2>&1
|
2022-06-28 10:06:06 +10:00
|
|
|
pingres[$n]=$?
|
|
|
|
n=$((n + 1))
|
2022-06-14 21:09:56 +10:00
|
|
|
done
|
|
|
|
|
|
|
|
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -e "${GREEN}${BOLD}ok${PLAIN}"
|
2022-02-02 14:09:02 +11:00
|
|
|
echo
|
2022-06-14 21:09:56 +10:00
|
|
|
|
2022-05-31 19:20:27 +10:00
|
|
|
printf "$TFORMAT" "Devices" "Availability" "Zones owned"
|
2022-06-28 10:06:06 +10:00
|
|
|
n=0
|
2022-02-02 14:09:02 +11:00
|
|
|
for x in $alldevs; do
|
2022-06-28 10:06:06 +10:00
|
|
|
if [[ ${pingres[$n]} -eq 0 ]]; then
|
2022-02-02 14:09:02 +11:00
|
|
|
thisform="$HFORMAT"
|
|
|
|
str="Available"
|
|
|
|
else
|
|
|
|
thisform="$AFORMAT"
|
|
|
|
str="Unavailable"
|
|
|
|
fi
|
2022-06-14 21:09:56 +10:00
|
|
|
unset mydevs || declare -a mydevs
|
2022-05-31 19:20:27 +10:00
|
|
|
for i in ${!ownerzone[@]}; do
|
|
|
|
if [[ ${ownerhost[$i]} == *${x}* ]]; then
|
|
|
|
mydevs+=("${ownerzone[$i]}")
|
2022-06-14 21:09:56 +10:00
|
|
|
fi
|
|
|
|
done
|
|
|
|
allmydevs=$(echo "${mydevs[@]}" | tr '\n' ' ')
|
2022-05-31 19:20:27 +10:00
|
|
|
printf "$thisform" "${x}" "$str" "${allmydevs}"
|
2022-06-28 10:06:06 +10:00
|
|
|
n=$((n + 1))
|
2022-02-02 14:09:02 +11:00
|
|
|
done
|
|
|
|
echo
|
|
|
|
exit 0
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [[ $logmode -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
2021-06-03 09:01:36 +10:00
|
|
|
elif [[ $logmode -eq 2 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
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
|
|
|
|
|
|
|
|
for x in ${!pname[@]}; do
|
2022-05-28 15:09:29 +10:00
|
|
|
canping ${pdev[$x]} && ishome=1 || ishome=0
|
2021-12-04 20:24:25 +11:00
|
|
|
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}
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
generate_actions
|
|
|
|
|
|
|
|
if [[ $cronmode -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
# only show output if we are doing something
|
|
|
|
[[ $nairconcommands -ge 1 ]] && showoutput=1 || showoutput=0
|
2021-06-03 09:01:36 +10:00
|
|
|
else
|
2021-12-04 20:24:25 +11:00
|
|
|
showoutput=1
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if [[ $showoutput -eq 1 ]]; then
|
2021-12-04 20:24:25 +11:00
|
|
|
echo
|
|
|
|
show_aircon_status
|
|
|
|
echo
|
|
|
|
show_analysis
|
|
|
|
echo
|
|
|
|
show_proposed_commands
|
|
|
|
echo
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|
|
|
|
|
|
|
|
# Actually run the commands
|
|
|
|
if [[ $DOIT -eq 1 ]]; then
|
2023-12-15 06:29:12 +11:00
|
|
|
if ! killfile_active; then
|
2021-12-04 20:24:25 +11:00
|
|
|
run_commands
|
|
|
|
[[ $cronmode -ne 1 ]] && echo
|
2023-12-09 08:47:07 +11:00
|
|
|
|
|
|
|
if [[ $USETELEGRAM -eq 1 ]]; then
|
|
|
|
show_telegram_output
|
|
|
|
fi
|
2021-12-04 20:24:25 +11:00
|
|
|
fi
|
2021-06-03 09:01:36 +10:00
|
|
|
fi
|