]> git.vanrenterghem.biz Git - elgato-keylight-script.git/blob - keylights.sh
Move declarations of light properties to function, clean whitespace
[elgato-keylight-script.git] / keylights.sh
1 #!/bin/bash
2 #set -x
3 set -o nounset
4 set -Eeuo pipefail
6 trap destroy SIGINT SIGTERM ERR EXIT
8 # Settings
9 temp_file="/tmp/elgatokeylights"
10 script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd -P)
11 icon="${script_dir}/assets/elgato.png"
13 # Declarations
14 declare -i silent=0
15 declare -i pretty=0
16 declare action="usage"
17 declare target=""
18 declare -A lights
19 declare lights_json
20 declare call="curl --silent --show-error --location --header 'Accept: application/json' --request"
21 declare devices="/elgato/lights"
22 declare accessory_info="/elgato/accessory-info"
23 declare settings="/elgato/lights/settings"
25 if [ ! -r "${icon}" ]; then icon=sunny; fi
27 notify() {
28     if [ $silent -eq 0 ]; then
29         notify-send -i "$icon" "Key Light Controller" "$1"
30     fi
31 }
33 die() {
34     echo >&2 -e "${1-}"
35     exit "${2-1}"
36 }
38 destroy() {
39     code=$?
40     rm "$temp_file" 2>/dev/null
42     exit ${code}
43 }
45 usage() {
46     cat <<EOF
47 Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-l] [-p] [-s] [-v] <action>
49 Elgato Lights controller. Works for Key Light and Key Light Air.
51 Available actions:
52     list        List available lights
53     status      Get state of lights
54     on          Turn all lights on
55     off         Turn all lights off
56     temperature  Set temperature level (260-470)
57     brightness  Set brightness level (0-100)
58     increase    Increases brightness by 10
59     decrease    Decreases brightness by 10
61 Available options:
63 -h, --help      Print this help and exit
64 -p, --pretty    Pretty print console output
65 -v, --verbose   Print script debug info
66 -f, --flag      Some flag description
67 -s, --silent    Supress notifications
68 EOF
69     exit
70 }
72 parse_params() {
73     # default values of variables set from params
75     while :; do
76         case "${1-}" in
77         -h | --help) usage ;;
78         -p | --pretty) pretty=1 ;;
79         -v | --verbose) set -x ;;
80         -s | --silent) silent=1 ;;
81         -t | --target)
82             target=1
83             target="${2-""}"
84             shift
85             ;;
86         -?*) die "Unknown option: $1" ;;
87         *) break ;;
88         esac
89         shift
90     done
92     args=("$@")
94     # check required params and arguments
95     declare -A actions=([help]=1 [list]=1)
96     [[ ${#args[@]} -ne 1 ]] && die "Incorrect action count, 1 allowed"
98     [[ ($silent -eq 1) && ($pretty -eq 1) ]] && die "Cannot use silent and pretty options simultaneously"
100     [[ -n "${actions[${args[0]}]}" ]] && action="${args[0]}"
102     return 0
105 dependencies() {
106     for var in "$@"; do
107         if ! command -v $var &>/dev/null; then
108             die "Dependency $var was not found, please install and try again"
109         fi
110     done
113 default_light_properties() {
114     # Default values for json type enforcement
115     declare device="N/A"
116     declare hostname="N/A"
117     declare manufacturer="N/A"
118     declare ip="N/A"
119     declare -i port=0
120     declare mac="N/A"
121     declare sku="N/A"
122     declare cfg="{}"
123     declare url="{}"
124     declare info="{}"
125     declare light="{}"
128 produce_json() {
129     declare json
130     for l in "${!lights[@]}"; do
131         json+="${lights[$l]},"
132     done
134     lights_json="[${json%,}]"
137 print_json() {
138     if [[ $pretty -eq 1 ]]; then
139         echo "$1" | jq '.'
140     else
141         echo "$1" | jq -c -M '.'
142     fi
144     exit 0
147 print_status() {
148     die "To be implemented"
151 set_state() {
152     new_state=$1
153     die "To be implemented"
156 find_lights() {
157     # Scan the network for Elgato devices
158     avahi-browse -d local _elg._tcp --resolve -t | grep -v "^\+" >"$temp_file"
160     default_light_properties
162     while read -r line; do
164         # Gather information about the light
165         if [[ ($line == =*) && ($line =~ IPv4[[:space:]](.+)[[:space:]]_elg) ]]; then
166             device=$(eval echo "${BASH_REMATCH[1]}") # eval to strip whitespace
167         elif [[ $line =~ hostname.+\[(.+)\] ]]; then
168             hostname=${BASH_REMATCH[1]}
169         elif [[ $line =~ address.+\[(.+)\] ]]; then
170             ip=${BASH_REMATCH[1]}
171         elif [[ $line =~ port.+\[(.+)\] ]]; then
172             port=${BASH_REMATCH[1]}
173         elif [[ $line =~ txt.+\[(.+)\] ]]; then
174             txt=$(eval echo "${BASH_REMATCH[1]}") # eval to strip single and double quotes
176             if [[ $txt =~ mf=([^[[:space:]]*]*) ]]; then manufacturer=${BASH_REMATCH[1]}; fi
177             if [[ $txt =~ id=([^[[:space:]]*]*) ]]; then mac=${BASH_REMATCH[1]}; fi
178             if [[ $txt =~ md=.+[[:space:]]([^[[:space:]]*]*)[[:space:]]id= ]]; then sku=${BASH_REMATCH[1]}; fi
180             # Get information from the light
181             if [[ ! (-z $ip) && ! (-z $port) ]]; then
182                 url="http://$ip:$port"
183                 cfg=$(eval "${call} GET ${url}${settings}") >/dev/null
184                 info=$(eval "${call} GET ${url}${accessory_info}") >/dev/null
185                 light=$(eval "${call} GET ${url}${devices}") >/dev/null
186             fi
188             # Store the light as json
189             lights["$ip"]=$(jq -n \
190                 --arg dev "$device" \
191                 --arg hn "$hostname" \
192                 --arg ip "$ip" \
193                 --arg port "$port" \
194                 --arg mf "$manufacturer" \
195                 --arg mac "$mac" \
196                 --arg sku "$sku" \
197                 --arg url "$url" \
198                 --argjson light "$light" \
199                 --argjson cfg "$cfg" \
200                 --argjson info "$info" \
201                 '{device: $dev, manufacturer: $mf, hostname: $hn, url: $url, ip: $ip, 
202                     port: $port, mac: $mac, sku: $sku, light: $light, settings: $cfg, info: $info}')
204             # Reset for next light as we are processing the last avahi line
205             default_light_properties
207         fi
208     done <"$temp_file"
211 # Manage user parameters
212 parse_params "$@"
214 # Make sure dependencies are installed
215 dependencies avahi-browse curl notify-send jq
217 find_lights
219 # Fail if we cannot find lights
220 [[ ${#lights[@]} -eq 0 ]] && die "No lights found" 2
222 produce_json
224 # Dispatch actions
225 [[ $action == "usage" ]] && usage
226 [[ $action == "list" ]] && print_json "${lights_json}"
227 [[ $action == "status" ]] && status
228 [[ $action == "on" ]] && set_state 1
229 [[ $action == "off" ]] && set_state 0