diff --git a/a.html b/a.html
new file mode 100644
index 0000000..84ff8fa
--- /dev/null
+++ b/a.html
@@ -0,0 +1,20 @@
+- Only operate the aircon in cool mode
+- Close vent in Study if [robsphone] isn't online
+- Close vent in Rob&Beth if [robsphone bethsphone] aren't online
+- Close vent in Brendan if [brendansphone bethsphone] aren't online
+- Close vent in Media if [lg-wifi] isn't online
+- Close vent in Ben/Sewing if [bensipad] isn't online
+- From Mon to Fri between 08:30 and 18:00, Close vent in Ben/Sewing if [brendansphone] isn't online
+- Prevent Nursery from being the MyZone
+- Prevent Ben/Sewing from being the MyZone
+- From Mon to Tue between 08:30 and 16:30, Force the vent in Nursery to be closed
+- Force the vent in Nursery to be closed
+- From Sat to Sun, Ignore Study temperature when deciding what to do
+- Between 06:00 and 23:59, Keep temperature of Family between 20-23 degrees
+- Between 20:00 and 07:00, Keep temperature of Brendan between 20-23 degrees
+- Keep temperature of Media between 18-23 degrees
+- Keep temperature of Rob&Beth between 20-23 degrees
+- From Mon to Fri between 08:30 and 17:30, Keep temperature of Study between 20-22 degrees
+- Between 20:00 and 07:00, Keep temperature of Ben/Sewing between 20-23 degrees
+- From Mon to Fri between 08:30 and 17:30, Keep temperature of Ben/Sewing between 20-23 degrees
+
diff --git a/aircon.sh b/aircon.sh
index 82e5a6f..5438adc 100755
--- a/aircon.sh
+++ b/aircon.sh
@@ -70,7 +70,7 @@ function usage() {
echo " -S[H] Show configured rules in human-readable format"
echo " (HTML if -H given, otherwise ANSI)."
echo " -w List which people are available then exit."
- echo " -W List zone owners' devices are available then exit."
+ echo " -W List zone-owning devices are available then exit."
echo " -t num Specify degrees below min temperature before taking action."
echo " -T num Specify degrees above max temperature before taking action."
echo " -y Actually run commands/db inserts. By default, commands are just displayed."
@@ -117,7 +117,7 @@ function getzoneaction() { # populates zproblem[] and zaction[]
else
if [[ -z ${zowner[$idx]} ]]; then
pingok=1
- elif canping "${zowner[$idx]}"; then
+ elif canping ${zowner[$idx]}; then
pingok=1
else
pingok=0
@@ -151,6 +151,7 @@ function getzoneaction() { # populates zproblem[] and zaction[]
#info "${zname[$idx]} priority is $priority"
zproblem[$idx]="$problem"
zpri[$idx]="$priority"
+ zownerhome[$idx]="$pingok"
if [[ $problem == "owner_not_home" ]]; then
# turn the zone off
@@ -337,6 +338,7 @@ function generate_actions() { # populates global: nairconcommands & airconcmd
for x in ${!zname[@]}; do
getzoneaction $x
+#echo "zoneignore for ${zname[$x]} is ${zignore[$x]}" >/dev/stderr
done
# pass 1
@@ -637,6 +639,7 @@ function add_aircon_command() {
airconcmdzone[$nairconcommands]="${zname[$idx]}"
airconcmdotherzone[$nairconcommands]="${zname[$otheridx]}"
airconproblem[$nairconcommands]="${zname[$idx]} is ${zproblem[$idx]/_/ }"
+ooooooooooo
#if [[ $otheridx -ne -1 ]]; then
# airconcomment[$nairconcommands]="${airconcomment[$nairconcommands]}, update nearby zone ${zname[$otheridx]}"
#fi
@@ -672,8 +675,12 @@ function addforcevent() {
[[ $idx == $nforcevents ]] && nforcevents=$((nforcevents + 1))
}
-function addtemprange() {
- local x idx
+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
idx=$ntempranges
for x in ${!tr_zonename[@]}; do
if [[ ${tr_zonename[$x]} == "$1" ]]; then
@@ -681,9 +688,36 @@ function addtemprange() {
break;
fi
done
+
tr_zonename[$idx]="$1"
tr_range[$idx]="$2"
+
+ 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
+
+
+
+
+
+
[[ $idx == $ntempranges ]] && ntempranges=$((ntempranges + 1))
+
+
+
+
+
}
function addadj() {
@@ -721,9 +755,13 @@ function addperson() {
[[ $idx == $npeople ]] && npeople=$((npeople + 1))
}
-function addowner() {
- local z h local x idx db
+function addowner() { # zone "host1 host2 ..."
+ local z h local x idx db doset=0
db=0
+ if [[ $1 == "-s" ]]; then
+ doset=1
+ shift
+ fi
z="$1"
shift
@@ -745,21 +783,28 @@ function addowner() {
fi
[[ $db -eq 1 ]] && info " hosts val is: ${ownerhost[$idx]}"
[[ $idx == $nowners ]] && nowners=$((nowners + 1))
+
+ if [[ $doset -eq 1 ]]; then
+ local zidx
+ zidx=$(getidxfromname "$z")
+ zowner[$zidx]="${ownerhost[$idx]}";
+ #zownerperson[$zidx]=$(getownerperson "$z"); # may be overwritten later
+ fi
}
# getownerperson zone_name
# returns name of person who owns zone
-function getownerperson() {
- local x retval
- retval=""
- for x in ${!ownerzone[@]}; do
- if [[ ${ownerzone[$x]} == "$1" ]]; then
- retval="${ownerperson[$x]}"
- break
- fi
- done
- echo "$retval"
-}
+#function getownerperson() {
+# local x retval
+# retval=""
+# for x in ${!ownerzone[@]}; do
+# if [[ ${ownerzone[$x]} == "$1" ]]; then
+# retval="${ownerperson[$x]}"
+# break
+# fi
+# done
+# echo "$retval"
+#}
# getowner zone_name
# returns devices associated woth zone
@@ -832,6 +877,7 @@ function load_config() {
db=0
rv=0
while read line; do
+ ok=1 # default to okay
line=${line%%#*} # remove comments
if [[ -n ${line// } ]]; then
# time based options
@@ -847,7 +893,7 @@ function load_config() {
if [[ $ok -eq 1 ]]; then
IFS=' ' read -ra tok <<< "$line"
if [[ ${tok[0]} == "temp" ]]; then
- addtemprange ${tok[1]} ${tok[2]}
+ addtemprange -s ${tok[1]} ${tok[2]}
elif [[ ${tok[0]} == "constant" ]]; then
constant=${tok[1]}
elif [[ ${tok[0]} == "adj" ]]; then
@@ -859,7 +905,7 @@ function load_config() {
elif [[ ${tok[0]} == "force" ]]; then
addforcevent ${tok[1]} ${tok[2]}
elif [[ ${tok[0]} == "owner" ]]; then
- addowner ${tok[1]} ${tok[@]:2}
+ addowner -s ${tok[1]} ${tok[@]:2}
elif [[ ${tok[0]} == "person" ]]; then
addperson ${tok[1]} ${tok[@]:2}
elif [[ ${tok[0]} == "modelock" ]]; then
@@ -975,11 +1021,14 @@ function processtimeconditions() {
fi
done
+ [[ $db -eq 1 ]] && info " ok=$ok nonmatches=$nonmatches"
+
if [[ $ok -eq 0 || $nonmatches -gt 0 ]]; then
rv=1
else
rv=0
fi
+ [[ $db -eq 1 ]] && info " returning $rv"
return $rv
}
@@ -1052,6 +1101,7 @@ function parse_config() {
local cond allconds x
local db fileok=1 linenum show=0
local config_human line_human errstr
+ local ign="" thisignored=0 oneof
if [[ -n $1 ]]; then
show=$1
@@ -1065,6 +1115,7 @@ function parse_config() {
ok=1
active_cols
line=${line%%#*} # remove comments
+ thisignored=0
line_human=""
if [[ ! -z ${line// } ]]; then
# time based options
@@ -1081,11 +1132,14 @@ function parse_config() {
fi
fi
+
IFS=' ' read -ra tok <<< "$line"
if [[ ${tok[0]} == "temp" ]]; then
local min max
min=${tok[2]%-*}
max=${tok[2]#*-}
+ [[ $ign == *\ ${tok[1]}* ]] && thisignored=1 # zone is being ignored
+ [[ $thisignored -eq 1 ]] && inactive_cols
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
@@ -1097,6 +1151,7 @@ function parse_config() {
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"
+ ign="${ign} ${tok[1]}"
elif [[ ${tok[0]} == "force" ]]; then
if [[ $VALID_ZONE_STATES == *\ ${tok[2]}\ * ]]; then
local adj
@@ -1110,13 +1165,16 @@ function parse_config() {
elif [[ ${tok[0]} == "owner" ]]; then
local devices verb
devices="${devc}${tok[@]:2}${linec}"
- devices="${devbc}[${linec}${devices}${devbc}]${linec}"
if [[ ${#tok[@]} -eq 3 ]]; then
verb="isn't"
+ oneof=""
+ devices="${devbc}${linec}${devices}${devbc}${linec}"
else
verb="aren't"
+ oneof=" one of"
+ devices="${devbc}(${linec}${devices}${devbc})${linec}"
fi
- line_human="${line_human}${statec}Close${linec} vent in ${roomc}${tok[1]}${linec} if $devices $verb online"
+ line_human="${line_human}${statec}Close${linec} vent in ${roomc}${tok[1]}${linec} if${oneof} $devices $verb online"
elif [[ ${tok[0]} == "modelock" ]]; then
if [[ $VALID_MODES == *\ ${tok[1]}\ * ]]; then
local col
@@ -1136,7 +1194,9 @@ function parse_config() {
fi
if [[ -n $line_human ]]; then
if [[ $ok -eq 0 ]]; then
- line_human="${plainc}${inactc} ${linec}${line_human}"
+ line_human="${plainc}${inactc}[out-of-hours] ${linec}${line_human}"
+ elif [[ $thisignored -eq 1 ]]; then
+ line_human="${plainc}${inactc}[ignored] ${linec}${line_human}"
fi
config_human="${config_human}- ${linec}${line_human}${plainc}$nl"
fi
@@ -1175,7 +1235,8 @@ function canping() {
thisrv=1
else
arp -d $ip >/dev/null 2>&1
- ping -c1 -w1 -n -q $ip >/dev/null 2>&1 &
+ #ping -c1 -w1 -n -q $ip >/dev/null 2>&1 &
+ arping -c10 -W0.1 -w2 -C1 -q ${ip} 2>/dev/null
sleep 0.3
mac=$(arp -n $ip)
mac=$(echo "$mac" | egrep -v "Host|xpired" | awk '{print $2}')
@@ -1205,17 +1266,18 @@ function addzone() {
zproblem[$nzones]="n/a"
zaction[$nzones]="n/a"
zactionfail[$nzones]=0
- zowner[$nzones]=$(getowner "$name")
- zownerperson[$nzones]=$(getownerperson "$name")
+ zowner[$nzones]=$(getowner "$name") # devices which 'own' the zone - may be overwritten later
+ #zownerperson[$nzones]=$(getownerperson "$name") # may be overwritten later
+ zownerhome[$nzones]=1
#info "zone $name owner is [${zowner[$nzones]}]"
zignore[$nzones]=0
znomyzone[$nzones]=0
zpri[$nzones]=0
wanttemp=$(gettemprange "$name")
if [[ $wanttemp == "n/a" ]]; then
- zwanttemp[$nzones]="n/a"
- zwantmin[$nzones]="-99"
- zwantmax[$nzones]="99"
+ 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
else
zwanttemp[$nzones]="$wanttemp"
zwantmin[$nzones]="${wanttemp%-*}"
@@ -1288,6 +1350,7 @@ function gen_config() {
function get_aircon_info() {
profile "query aircon"
[[ $cronmode -eq 0 && $logmode -eq 0 ]] && echo -en "${GREEN}${BOLD}>> ${PLAIN}${GREEN}Querying aircon... ${PLAIN}"
+
zones=$(myair $AIRCON_IP zones | jq -r '.[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ')
airconmode=$(myair $AIRCON_IP mode)
nzones=0
@@ -1303,10 +1366,11 @@ function get_aircon_info() {
function show_aircon_status() {
local zonestr zonecol settempcol actioncol thiswantcol thisstate thisstateform
- local thisformat x powercol lockcol
+ local actualtempformat x powercol lockcol actionstr
local FORMAT1 FORMAT2 FORMATHOT FORMATCOLD FORMATOK CLOSEDFORM OPENFORM
+ local ownercol ownerform
- FORMAT1="${BOLD}%-16s%-7s%-8s%-7s%-7s%s${PLAIN}"
+ FORMAT1="${BOLD}%-16s%-9s%-8s%-7s%-7s%-7s%s${PLAIN}"
FORMAT2="${UNDERLINE}${FORMAT1}${PLAIN}"
FORMATHOT="${RED}%-7s${PLAIN}"
FORMATCOLD="${CYAN}%-7s${PLAIN}"
@@ -1327,15 +1391,15 @@ function show_aircon_status() {
echo
- printf "$FORMAT1\n" "" "Valid" "" "Set" "Actual" "Proposed "
- printf "$FORMAT2\n" "Zone" "Temp" "State" "Temp" "Temp" "Action "
+ printf "$FORMAT1\n" "" "Valid" "" "Set" "Actual" "Owner" "Proposed "
+ printf "$FORMAT2\n" "Zone" "Temp" "State" "Temp" "Temp" "Home" "Action "
for x in ${!zname[@]}; do
if [[ ${zproblem[$x]} == "too_hot" ]]; then
- thisformat="${FORMATHOT}"
+ actualtempformat="${FORMATHOT}"
elif [[ ${zproblem[$x]} == "too_cold" ]]; then
- thisformat="${FORMATCOLD}"
+ actualtempformat="${FORMATCOLD}"
else
- thisformat="${FORMATOK}"
+ actualtempformat="${FORMATOK}"
fi
if [[ ${airconmode} == "off" ]]; then
thisstateform="${CLOSEDFORM}"
@@ -1353,6 +1417,13 @@ function show_aircon_status() {
else
thiswantcol="$PLAIN"
fi
+
+ # override
+ if [[ ${zignore[$x]} -eq 1 ]]; then
+ thiswant="ignore"
+ thiswantcol="$GREY"
+ fi
+
if [[ ${zactionfail[$x]} -eq 1 || ${zaction[$x]} == "n/a" ]]; then
actioncol="$GREY"
else
@@ -1376,7 +1447,23 @@ function show_aircon_status() {
zonestr="${zname[$x]} (C)"
fi
- printf "$zonecol%-16s$PLAIN$thiswantcol%-7s$PLAIN$thisstateform$settempcol%-7s$PLAIN$thisformat$actioncol%s$PLAIN\n" "${zonestr}" "${thiswant}" "${thisstate}" "${zsettemp[$x]}" "${ztemp[$x]}" "${zaction[$x]}"
+ 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}"
done
}
@@ -1399,12 +1486,21 @@ function show_analysis() {
[[ $what == "close" ]] && what="${what}d"
echo "- ${zname[$x]} is forced $what"
else
- if [[ $constant == ${zname[$x]} ]]; then
- append=" (constant zone)"
+ if [[ ${zownerhome[$x]} -ne 1 ]]; then
+ if [[ ${zowner[$x]} == *\ * ]]; then
+ append1=", but (${zowner[$x]}) aren't online"
+ else
+ append1=", but ${zowner[$x]} isn't online"
+ fi
else
- append=""
+ append1=""
fi
- echo "- ${zname[$x]} is ${zproblem[$x]/_/ }${append}"
+ if [[ $constant == ${zname[$x]} ]]; then
+ append2=" (constant zone)"
+ else
+ append2=""
+ fi
+ echo "- ${zname[$x]} is ${zproblem[$x]/_/ }${append1}${append2}"
fi
count=$((count + 1))
fi
@@ -1558,7 +1654,6 @@ csvfile="$DEFAULT_CSVFILE"
sanitycheck=0
RULEFORMAT=ansi
-
# check for config file option first
if [[ $* == *-f\ * ]]; then
cf=$(echo "$*" | sed -e 's/.*-f //;s/ .*//')
@@ -1670,18 +1765,9 @@ if [[ $makeconfig -eq 1 ]]; then
exit $rv
fi
-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
+
+
+
if [[ $showwho -eq 0 ]]; then
if [[ -z $MYAIR ]]; then
@@ -1698,6 +1784,25 @@ if [[ $showwho -eq 0 ]]; then
fi
fi
+
+
+# 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
+
# ping all hosts in background to populate arp table
for x in ${devices}; do
ping -c1 -w1 -n -q $ip >/dev/null 2>&1 &
@@ -1717,7 +1822,7 @@ if [[ $showwho -eq 1 ]]; then
echo
printf "$TFORMAT" "Person" "Availability"
for x in ${!pname[@]}; do
- if canping "${pdev[$x]}"; then
+ if canping ${pdev[$x]}; then
thisform="$HFORMAT"
str="At home"
else
@@ -1742,7 +1847,7 @@ elif [[ $showwho -eq 2 ]]; then
echo
printf "$TFORMAT" "Devices" "Availability"
for x in $alldevs; do
- if canping "${x}"; then
+ if canping ${x}; then
thisform="$HFORMAT"
str="Available"
else
@@ -1756,9 +1861,6 @@ elif [[ $showwho -eq 2 ]]; then
fi
-
-get_aircon_info
-
if [[ $logmode -eq 1 ]]; then
now=$(date +'%d/%m/%Y %H:%M:%S')
if [[ ! -e $csvfile ]]; then
@@ -1786,7 +1888,7 @@ elif [[ $logmode -eq 2 ]]; then
done
for x in ${!pname[@]}; do
- canping "${pdev[$x]}" && ishome=1 || ishome=0
+ canping ${pdev[$x]} && ishome=1 || ishome=0
influx_insert "INSERT attendance,person=${pname[$x]} value=$ishome"
done
[[ $airconmode == "off" ]] && pw=0 || pw=1
diff --git a/aircon_grafana.png b/aircon_grafana.png
new file mode 100755
index 0000000..4b167aa
Binary files /dev/null and b/aircon_grafana.png differ
diff --git a/b.html b/b.html
new file mode 100644
index 0000000..8f5bfa0
--- /dev/null
+++ b/b.html
@@ -0,0 +1,2 @@
+strikedstill striked
+what about now