Removed requirement for pymyair - default is now to call json api directly.

This commit is contained in:
Rob Pearce 2023-09-03 20:59:35 +10:00
parent f945018efb
commit 0a8d0f8e3e
2 changed files with 70 additions and 67 deletions

View File

@ -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:

View File

@ -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,51 +1957,42 @@ 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"
;;
P)
JSONAPI=0
;;
p)
profiler=1
info "Profiler mode enabled"
;; ;;
R) R)
robtest=1 robtest=1
;; ;;
c)
enable_cronmode
;;
p)
profiler=1
info "Profiler mode enabled"
;;
m)
makeconfig=1
;;
s) s)
sanitycheck=1 sanitycheck=1
;; ;;
S) S)
sanitycheck=2 sanitycheck=2
;; ;;
y) t)
DOIT=1 tolerance_l=${OPTARG}
;;
T)
tolerance_h=${OPTARG}
;; ;;
w) w)
showwho=1 showwho=1
@ -2000,9 +2003,12 @@ while getopts "$optstring" i $ALLARGS; do
x) x)
MYAIR="${OPTARG}" MYAIR="${OPTARG}"
;; ;;
y)
DOIT=1
;;
*) *)
usage; usage;
exit 1; exit 1;
;; ;;
esac esac
done done
@ -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