summaryrefslogtreecommitdiff
path: root/misc/relayctl
blob: b356031024e1699808ec1bba3c42d51a82f6b456 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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"