summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xmisc/relayctl67
1 files changed, 67 insertions, 0 deletions
diff --git a/misc/relayctl b/misc/relayctl
new file mode 100755
index 0000000..b356031
--- /dev/null
+++ b/misc/relayctl
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+# setup
+set -e
+die() { echo "usage: $0 [-r relay] [-s state] [-ght] [device]" && exit $1 ; }
+
+getstate() {
+ tty=$1
+ relay=${2:-1}
+
+ # write 0xFF for status
+ printf '\377' > $tty
+
+ # read status response for selected relay
+ while read r; do case "$r" in "CH${relay}: "*) echo "$r" && return ;; esac; done < $tty
+}
+
+genbytes() {
+ # the relay is controled by a fixed 4 byte command as follows:
+ start=160 # always 0xA0
+ relay=$1 # relay id (counts from 1)
+ state=$2 # whether to energize 1 or 0
+ checksum=$(( start + relay + state )) # checksum is just a sum
+
+ # generate the octal sequence with printf, then convert to bytes with printf again
+ printf "$(printf '\\%03o\\%03o\\%03o\\%03o' $start $relay $state $checksum)"
+}
+
+# args
+relay=1
+state=1
+
+while getopts 'r:s:ght' opt; do
+ case "$opt" in
+ r) relay="$OPTARG" ;;
+ s) state="$OPTARG" ;;
+ g) get=1 ;;
+ t) get=1 && toggle=1 ;;
+ h) die 0 ;;
+ \?) die 1 ;;
+ esac
+done
+
+shift $((OPTIND - 1)) # shift to final arg
+tty="${1:-/dev/stdout}" # output to stdout as fallback
+
+# validate
+case $relay in [1-9]|[1-9][0-9]*) ;; *) die 1 ;; esac
+case $state in [01]) ;; *) die 1 ;; esac
+[ -n "$get" ] && [ "$tty" = "/dev/stdout" ] && die 1
+
+# handle get commands
+if [ -n "$get" ]; then
+ s=$(getstate "$tty" $relay) || die 1
+
+ if [ -z "$toggle" ]; then
+ echo "$s" && exit 0 # exit when no toggle
+ else
+ case "$s" in
+ *ON) state=0 ;;
+ *OFF) state=1 ;;
+ esac
+ fi
+fi
+
+# go
+genbytes $relay $state > "$tty"