Removed requirement for pymyair - default is now to call json api directly.
This commit is contained in:
parent
f945018efb
commit
0a8d0f8e3e
38
README.md
38
README.md
|
@ -11,10 +11,6 @@ It can also log to an influxdb database for easy integration into Grafana or sim
|
||||||
![grafana integration](https://cube.nethack.net/images/aircon_grafana.png "grafana integration")
|
![grafana integration](https://cube.nethack.net/images/aircon_grafana.png "grafana integration")
|
||||||
|
|
||||||
|
|
||||||
# Requirements
|
|
||||||
|
|
||||||
- [pymyair](https://github.com/smallsam/pymyair)
|
|
||||||
|
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|
||||||
|
@ -25,35 +21,40 @@ It can also log to an influxdb database for easy integration into Grafana or sim
|
||||||
- Turn the entire aircon system on/off as needed to control temperature
|
- Turn the entire aircon system on/off as needed to control temperature
|
||||||
- Turn zones on/off based on ARP table entries for specific MAC addresses (for example, if a TV is turned on or a person's phone is detected)
|
- Turn zones on/off based on ARP table entries for specific MAC addresses (for example, if a TV is turned on or a person's phone is detected)
|
||||||
- Log temperature measurements to a CSV file or InfluxDB
|
- Log temperature measurements to a CSV file or InfluxDB
|
||||||
|
- Optional integration with [pymyair](https://github.com/smallsam/pymyair) (but not required)
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
```text
|
```text
|
||||||
root@gridbug:~# scripts/aircon.sh -h
|
usage: ./aircon.sh [options]
|
||||||
usage: scripts/aircon.sh [options]
|
|
||||||
|
|
||||||
Modifies aircon based on configured parameters in /root/.airconrc.
|
Modifies aircon based on configured parameters in /Users/rob/.airconrc.
|
||||||
|
|
||||||
-h Show this text.
|
-a file Specify location of arping binary (default: /usr/local/sbin/arping).
|
||||||
-c Cron mode. Only show output if actions were taken.
|
-b Rule debug mode. Show processing of time rules.
|
||||||
-i x.x.x.x Specify IP address for aircon (default is 10.99.99.1)
|
|
||||||
-D dbhost Specify influxdb hostname for -I and -A options (default: localhost)
|
|
||||||
-I db Log all zone temperatures to given influxdb database, then exit (see -o).
|
|
||||||
-A db Log actions to given influxdb database.
|
-A db Log actions to given influxdb database.
|
||||||
|
-c Cron mode. Only show output if actions were taken.
|
||||||
|
-D dbhost Specify influxdb hostname for -I and -A options (default: localhost)
|
||||||
-f file Specify an alternate config file.
|
-f file Specify an alternate config file.
|
||||||
-k file If file exists, never change aircon settings (default: /root/.aircon_noaction).
|
-h Show this text.
|
||||||
|
-i x.x.x.x Specify IP address for aircon (default is 10.99.99.1)
|
||||||
|
-I db Log all zone temperatures to given influxdb database, then exit (see -o).
|
||||||
|
-k file If file exists, never change aircon settings (default: /Users/rob/.aircon_noaction).
|
||||||
-l num Set number of too hot/cold zones at which to taking action.
|
-l num Set number of too hot/cold zones at which to taking action.
|
||||||
-L Log all zone temperatures to CSV file, then exit (see -o).
|
-L Log all zone temperatures to CSV file, then exit (see -o).
|
||||||
-o file Specify CSV output file. Default: /root/acstats.csv
|
|
||||||
-m Generate a config file based on current aircon setup.
|
-m Generate a config file based on current aircon setup.
|
||||||
|
-o file Specify CSV output file. Default: /Users/rob/acstats.csv
|
||||||
|
-P Use pymyair instead of direct JSON API calls (also see -x).
|
||||||
-p Profiler mode.
|
-p Profiler mode.
|
||||||
-s Validate config file then exit.
|
-s Validate config file then exit.
|
||||||
-S[H] Show configured rules in human-readable format
|
-S[H] Show configured rules in human-readable format
|
||||||
(HTML if -H given, otherwise ANSI).
|
(HTML if -H given, otherwise ANSI).
|
||||||
-w List which people are available then exit.
|
|
||||||
-W List zone-owning devices are available then exit.
|
|
||||||
-t num Specify degrees below min temperature before taking action.
|
-t num Specify degrees below min temperature before taking action.
|
||||||
-T num Specify degrees above max temperature before taking action.
|
-T num Specify degrees above max temperature before taking action.
|
||||||
|
-w List which people are available then exit.
|
||||||
|
-W List zone-owning devices are available then exit.
|
||||||
|
-x path Specify location of 'pymyair' (from https://github.com/smallsam/pymyair)
|
||||||
|
(only used if -P specified)
|
||||||
-y Actually run commands/db inserts. By default, commands are just displayed.
|
-y Actually run commands/db inserts. By default, commands are just displayed.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -92,7 +93,6 @@ adj Study Family
|
||||||
|
|
||||||
person Rob robsphone
|
person Rob robsphone
|
||||||
person Beth bethsphone
|
person Beth bethsphone
|
||||||
person Mel melsphone
|
|
||||||
person Brendan brendansphone
|
person Brendan brendansphone
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ person Brendan brendansphone
|
||||||
Media 18-22 close 20 21.6 n/a
|
Media 18-22 close 20 21.6 n/a
|
||||||
Rob&Beth 18-22 close 18 19.5 n/a
|
Rob&Beth 18-22 close 18 19.5 n/a
|
||||||
Study n/a close 19 20.6 n/a
|
Study n/a close 19 20.6 n/a
|
||||||
Mel&Rob 18-21 close 18 19.5 n/a
|
Bedroom2 18-21 close 18 19.5 n/a
|
||||||
Nursery 17-19 open 19 18.9 set_myzone
|
Nursery 17-19 open 19 18.9 set_myzone
|
||||||
|
|
||||||
Analysis:
|
Analysis:
|
||||||
|
@ -163,7 +163,7 @@ person Brendan brendansphone
|
||||||
Media 18-22 close 20 21.6 n/a
|
Media 18-22 close 20 21.6 n/a
|
||||||
Rob&Beth 18-22 close 18 19.5 n/a
|
Rob&Beth 18-22 close 18 19.5 n/a
|
||||||
Study n/a close 19 20.6 n/a
|
Study n/a close 19 20.6 n/a
|
||||||
Mel&Rob 18-21 close 18 19.5 n/a
|
Bedroom2 18-21 close 18 19.5 n/a
|
||||||
Nursery 17-19 open 19 18.9 set_myzone
|
Nursery 17-19 open 19 18.9 set_myzone
|
||||||
|
|
||||||
Analysis:
|
Analysis:
|
||||||
|
|
91
aircon.sh
91
aircon.sh
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
# TODO: comparison to previous reading
|
# TODO: comparison to previous reading
|
||||||
# TODO: gnuplot of given time range
|
# TODO: gnuplot of given time range
|
||||||
# TODO: ditch pymyair
|
|
||||||
# TODO: manual controls
|
# TODO: manual controls
|
||||||
|
|
||||||
DEFAULT_KILLFILE="${HOME}/.aircon_noaction"
|
DEFAULT_KILLFILE="${HOME}/.aircon_noaction"
|
||||||
|
@ -72,6 +71,7 @@ function usage() {
|
||||||
echo " -L Log all zone temperatures to CSV file, then exit (see -o)."
|
echo " -L Log all zone temperatures to CSV file, then exit (see -o)."
|
||||||
echo " -m Generate a config file based on current aircon setup."
|
echo " -m Generate a config file based on current aircon setup."
|
||||||
echo " -o file Specify CSV output file. Default: $DEFAULT_CSVFILE"
|
echo " -o file Specify CSV output file. Default: $DEFAULT_CSVFILE"
|
||||||
|
echo " -P Use pymyair instead of direct JSON API calls (also see -x)."
|
||||||
echo " -p Profiler mode."
|
echo " -p Profiler mode."
|
||||||
echo " -s Validate config file then exit."
|
echo " -s Validate config file then exit."
|
||||||
echo " -S[H] Show configured rules in human-readable format"
|
echo " -S[H] Show configured rules in human-readable format"
|
||||||
|
@ -80,6 +80,8 @@ function usage() {
|
||||||
echo " -T num Specify degrees above max temperature before taking action."
|
echo " -T num Specify degrees above max temperature before taking action."
|
||||||
echo " -w List which people are available then exit."
|
echo " -w List which people are available then exit."
|
||||||
echo " -W List zone-owning devices are available then exit."
|
echo " -W List zone-owning devices are available then exit."
|
||||||
|
echo " -x path Specify location of 'pymyair' (from https://github.com/smallsam/pymyair)"
|
||||||
|
echo " (only used if -P specified)"
|
||||||
echo " -y Actually run commands/db inserts. By default, commands are just displayed."
|
echo " -y Actually run commands/db inserts. By default, commands are just displayed."
|
||||||
echo
|
echo
|
||||||
}
|
}
|
||||||
|
@ -88,6 +90,10 @@ function action() {
|
||||||
echo -e "$BOLD$GREEN>> Running action: $PLAIN$GREEN$*$PLAIN"
|
echo -e "$BOLD$GREEN>> Running action: $PLAIN$GREEN$*$PLAIN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function warn() {
|
||||||
|
echo -e "$BOLD${YELLOW}Warning: $PLAIN$YELLOW$*$PLAIN" >/dev/stderr
|
||||||
|
}
|
||||||
|
|
||||||
function error() {
|
function error() {
|
||||||
echo -e "$BOLD${RED}ERROR: $PLAIN$RED$*$PLAIN" >/dev/stderr
|
echo -e "$BOLD${RED}ERROR: $PLAIN$RED$*$PLAIN" >/dev/stderr
|
||||||
}
|
}
|
||||||
|
@ -694,7 +700,7 @@ function gen_aircon_command() {
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
# add_aircon_command zone_idx "comment goes here" "actual pymyair command to run"
|
# add_aircon_command zone_idx "comment goes here" " pymyair command to run"
|
||||||
function add_aircon_command() {
|
function add_aircon_command() {
|
||||||
local x idx otheridx comment db cmd jcmd
|
local x idx otheridx comment db cmd jcmd
|
||||||
|
|
||||||
|
@ -1524,18 +1530,18 @@ function get_aircon_info() {
|
||||||
if [[ $JSONAPI -eq 1 ]]; then
|
if [[ $JSONAPI -eq 1 ]]; then
|
||||||
url="${AIRCON_URL}/getSystemData"
|
url="${AIRCON_URL}/getSystemData"
|
||||||
jsoninfo=$(curl -s "$url" 2>/dev/null)
|
jsoninfo=$(curl -s "$url" 2>/dev/null)
|
||||||
zones=$(echo "$jsoninfo" | jq -r '.aircons.ac1.zones[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ')
|
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 '" ')
|
state=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.state' | tr -d '" ')
|
||||||
if [[ $state == "off" ]]; then
|
if [[ $state == "off" ]]; then
|
||||||
airconmode="off"
|
airconmode="off"
|
||||||
else
|
else
|
||||||
airconmode=$(echo "$jsoninfo" | jq -r '.aircons.ac1.info.mode' | tr -d '" ')
|
airconmode=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.mode' | tr -d '" ')
|
||||||
fi
|
fi
|
||||||
airconmyzoneid=$(echo "$jsoninfo" | jq -r '.aircons.ac1.info.myZone ' | tr -d '" ')
|
airconmyzoneid=$(echo "$jsoninfo" | $JQ -r '.aircons.ac1.info.myZone ' | tr -d '" ')
|
||||||
else
|
else
|
||||||
zones=$(myair $AIRCON_IP zones | jq -r '.[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ')
|
zones=$($MYAIR $AIRCON_IP zones | $JQ -r '.[] | [ .name, .state, .setTemp, .measuredTemp, .number ] | @csv' | tr -d '" ')
|
||||||
airconmode=$(myair $AIRCON_IP mode)
|
airconmode=$($MYAIR $AIRCON_IP mode)
|
||||||
airconmyzoneid=$(myair $AIRCON_IP myzone)
|
airconmyzoneid=$($MYAIR $AIRCON_IP myzone)
|
||||||
fi
|
fi
|
||||||
nzones=0
|
nzones=0
|
||||||
for line in $zones; do
|
for line in $zones; do
|
||||||
|
@ -1757,7 +1763,7 @@ function combine_commands() {
|
||||||
combinejq="${combinejq} * .[$((x + 1))]"
|
combinejq="${combinejq} * .[$((x + 1))]"
|
||||||
done
|
done
|
||||||
|
|
||||||
jcmd=$(jq -s "$combinejq" $basefile ${tfile[@]} )
|
jcmd=$($JQ -s "$combinejq" $basefile ${tfile[@]} )
|
||||||
[[ $? -ne 0 ]] && { error "couldnt merge json command files " >&2; exit 1; }
|
[[ $? -ne 0 ]] && { error "couldnt merge json command files " >&2; exit 1; }
|
||||||
[[ -z $jcmd ]] && { error "got empty merged json command" >&2; exit 1; }
|
[[ -z $jcmd ]] && { error "got empty merged json command" >&2; exit 1; }
|
||||||
jurl="${AIRCON_URL}/setAircon?json=$jcmd"
|
jurl="${AIRCON_URL}/setAircon?json=$jcmd"
|
||||||
|
@ -1779,7 +1785,7 @@ function run_commands() {
|
||||||
|
|
||||||
[[ -n ${airconcomment[$x]} ]] && action "${airconcomment[$x]}"
|
[[ -n ${airconcomment[$x]} ]] && action "${airconcomment[$x]}"
|
||||||
if [[ $JSONAPI -eq 1 ]]; then
|
if [[ $JSONAPI -eq 1 ]]; then
|
||||||
myair $AIRCON_IP ${airconcmd[$x]} >/dev/null 2>&1
|
$MYAIR $AIRCON_IP ${airconcmd[$x]} >/dev/null 2>&1
|
||||||
fi
|
fi
|
||||||
influx_insert "INSERT aircon action=\"${airconcomment[$x]}\",comment=\"${airconproblem[$x]}\""
|
influx_insert "INSERT aircon action=\"${airconcomment[$x]}\",comment=\"${airconproblem[$x]}\""
|
||||||
done
|
done
|
||||||
|
@ -1787,7 +1793,7 @@ function run_commands() {
|
||||||
if [[ $JSONAPI -eq 1 ]]; then
|
if [[ $JSONAPI -eq 1 ]]; then
|
||||||
jurl=$(combine_commands)
|
jurl=$(combine_commands)
|
||||||
res=$(curl -s -g "$jurl" 3>/dev/null)
|
res=$(curl -s -g "$jurl" 3>/dev/null)
|
||||||
jqres=$(echo "$res" | jq -r '.ack' 2>/dev/null)
|
jqres=$(echo "$res" | $JQ -r '.ack' 2>/dev/null)
|
||||||
if [[ $jqres != "true" ]]; then
|
if [[ $jqres != "true" ]]; then
|
||||||
error "Myair API call failed:"
|
error "Myair API call failed:"
|
||||||
echo -e "$RED curl -s -g $jurl$PLAIN"
|
echo -e "$RED curl -s -g $jurl$PLAIN"
|
||||||
|
@ -1896,7 +1902,7 @@ limit=$DEFAULTLIMIT
|
||||||
profiler=0
|
profiler=0
|
||||||
csvfile="$DEFAULT_CSVFILE"
|
csvfile="$DEFAULT_CSVFILE"
|
||||||
sanitycheck=0
|
sanitycheck=0
|
||||||
JSONAPI=0
|
JSONAPI=1
|
||||||
RULEFORMAT=ansi
|
RULEFORMAT=ansi
|
||||||
robtest=0
|
robtest=0
|
||||||
|
|
||||||
|
@ -1916,15 +1922,21 @@ fi
|
||||||
|
|
||||||
ALLARGS="$ALLARGS $*"
|
ALLARGS="$ALLARGS $*"
|
||||||
|
|
||||||
optstring="aA:bcD:f:hHi:I:jk:l:Lo:pmRsSt:T:wWx:y"
|
optstring="aA:bcD:f:hHi:I:k:l:Lo:pPmRsSt:T:wWx:y"
|
||||||
while getopts "$optstring" i $ALLARGS; do
|
while getopts "$optstring" i $ALLARGS; do
|
||||||
case "$i" in
|
case "$i" in
|
||||||
a)
|
a)
|
||||||
ARPING=${OPTARG}
|
ARPING=${OPTARG}
|
||||||
;;
|
;;
|
||||||
|
A)
|
||||||
|
influxdb="$OPTARG"
|
||||||
|
;;
|
||||||
b)
|
b)
|
||||||
RULEDB=1
|
RULEDB=1
|
||||||
;;
|
;;
|
||||||
|
c)
|
||||||
|
enable_cronmode
|
||||||
|
;;
|
||||||
D)
|
D)
|
||||||
influxhost="${OPTARG}"
|
influxhost="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
|
@ -1945,42 +1957,30 @@ while getopts "$optstring" i $ALLARGS; do
|
||||||
logmode=2
|
logmode=2
|
||||||
influxdb="$OPTARG"
|
influxdb="$OPTARG"
|
||||||
;;
|
;;
|
||||||
j)
|
|
||||||
JSONAPI=1
|
|
||||||
;;
|
|
||||||
A)
|
|
||||||
influxdb="$OPTARG"
|
|
||||||
;;
|
|
||||||
k)
|
k)
|
||||||
KILLFILE=${OPTARG}
|
KILLFILE=${OPTARG}
|
||||||
;;
|
;;
|
||||||
l)
|
l)
|
||||||
limit=${OPTARG}
|
limit=${OPTARG}
|
||||||
;;
|
;;
|
||||||
o)
|
|
||||||
csvfile="$OPTARG"
|
|
||||||
;;
|
|
||||||
L)
|
L)
|
||||||
logmode=1
|
logmode=1
|
||||||
;;
|
;;
|
||||||
t)
|
m)
|
||||||
tolerance_l=${OPTARG}
|
makeconfig=1
|
||||||
;;
|
;;
|
||||||
T)
|
o)
|
||||||
tolerance_h=${OPTARG}
|
csvfile="$OPTARG"
|
||||||
;;
|
;;
|
||||||
R)
|
P)
|
||||||
robtest=1
|
JSONAPI=0
|
||||||
;;
|
|
||||||
c)
|
|
||||||
enable_cronmode
|
|
||||||
;;
|
;;
|
||||||
p)
|
p)
|
||||||
profiler=1
|
profiler=1
|
||||||
info "Profiler mode enabled"
|
info "Profiler mode enabled"
|
||||||
;;
|
;;
|
||||||
m)
|
R)
|
||||||
makeconfig=1
|
robtest=1
|
||||||
;;
|
;;
|
||||||
s)
|
s)
|
||||||
sanitycheck=1
|
sanitycheck=1
|
||||||
|
@ -1988,8 +1988,11 @@ while getopts "$optstring" i $ALLARGS; do
|
||||||
S)
|
S)
|
||||||
sanitycheck=2
|
sanitycheck=2
|
||||||
;;
|
;;
|
||||||
y)
|
t)
|
||||||
DOIT=1
|
tolerance_l=${OPTARG}
|
||||||
|
;;
|
||||||
|
T)
|
||||||
|
tolerance_h=${OPTARG}
|
||||||
;;
|
;;
|
||||||
w)
|
w)
|
||||||
showwho=1
|
showwho=1
|
||||||
|
@ -2000,6 +2003,9 @@ while getopts "$optstring" i $ALLARGS; do
|
||||||
x)
|
x)
|
||||||
MYAIR="${OPTARG}"
|
MYAIR="${OPTARG}"
|
||||||
;;
|
;;
|
||||||
|
y)
|
||||||
|
DOIT=1
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
usage;
|
usage;
|
||||||
exit 1;
|
exit 1;
|
||||||
|
@ -2011,7 +2017,7 @@ shift $((OPTIND - 1))
|
||||||
AIRCON_URL="http://${AIRCON_IP}:2025"
|
AIRCON_URL="http://${AIRCON_IP}:2025"
|
||||||
|
|
||||||
if [[ ! -e $ARPING ]]; then
|
if [[ ! -e $ARPING ]]; then
|
||||||
info "Warning: arping binary '$ARPING' not found, will use ping instead"
|
warn "arping binary '$ARPING' not found, will use ping instead"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n $influxdb ]]; then
|
if [[ -n $influxdb ]]; then
|
||||||
|
@ -2029,17 +2035,16 @@ if [[ $makeconfig -eq 1 ]]; then
|
||||||
exit $rv
|
exit $rv
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if [[ $showwho -eq 0 ]]; then
|
if [[ $showwho -eq 0 ]]; then
|
||||||
if [[ $JSONAPI -eq 1 ]]; then
|
if [[ $JSONAPI -eq 1 ]]; then
|
||||||
JQ=$(which myair 2>/dev/null)
|
JQ=$(which jq 2>/dev/null)
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
error "Can't find jq executable in path."
|
error "Can't find jq executable in path."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
if [[ -n $MYAIR ]]; then
|
||||||
|
warn "-x option ignored as -P not used."
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if [[ -z $MYAIR ]]; then
|
if [[ -z $MYAIR ]]; then
|
||||||
MYAIR=$(which myair 2>/dev/null)
|
MYAIR=$(which myair 2>/dev/null)
|
||||||
|
@ -2056,8 +2061,6 @@ if [[ $showwho -eq 0 ]]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Must do this BEFORE parsing the config file, otherwise
|
# Must do this BEFORE parsing the config file, otherwise
|
||||||
# we can't resolve zone names.
|
# we can't resolve zone names.
|
||||||
get_aircon_info
|
get_aircon_info
|
||||||
|
|
Loading…
Reference in New Issue