]> git.vanrenterghem.biz Git - elgato-keylight-script.git/blob - keylights.sh
Rough draft
[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,list,pretty}=0
15 declare action="usage"
16 declare -A lights
17 declare lights_json
18 declare call="curl --silent --show-error --location --header 'Accept: application/json' --request"
19 declare devices="/elgato/lights"
20 declare accessory_info="/elgato/accessory-info"
21 declare settings="/elgato/lights/settings"
23 if [ ! -r "${icon}" ]; then icon=sunny; fi
25 notify() {
26     echo "mm"
27     if [ $silent -eq 0 ]; then
28         notify-send -i "$icon" "Key Light Controller" "$1"
29     fi
30 }
32 error() {
33     echo >&2 -e "${1-}"
34 }
36 die() {
37     local msg=$1
38     local code=${2-1} # default exit status 1
39     error "$msg"
40     exit "$code"
41 }
43 destroy() {
44     code=$?
45     rm "$temp_file" 2>/dev/null
47     exit ${code}
48 }
50 usage() {
51     cat <<EOF
52 Usage: $(basename "${BASH_SOURCE[0]}") [-h] [-l] [-p] [-s] [-v] <action>
54 Elgato Lights controller. Works for Key Light and Key Light Air.
56 Available actions:
57     list        List available lights
58     status      Get state of lights
59     on          Turn all lights on
60     off         Turn all lights off
61     temperature  Set temperature level (260-470)
62     brightness  Set brightness level (0-100)
63     increase    Increases brightness by 10
64     decrease    Decreases brightness by 10
66 Available options:
68 -h, --help      Print this help and exit
69 -p, --pretty    Pretty print console output
70 -v, --verbose   Print script debug info
71 -f, --flag      Some flag description
72 -s, --silent    Supress notifications
73 EOF
74     exit
75 }
77 parse_params() {
78     # default values of variables set from params
80     while :; do
81         case "${1-}" in
82         -h | --help) usage ;;
83         -p | --pretty) pretty=1;;
84         -v | --verbose) set -x ;;
85         -s | --silent) silent=1 ;;
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     #[[ -z "${param-}" ]] && die "Missing required parameter: param"
97     [[ ${#args[@]} -ne 1 ]] && die "Incorrect action count, 1 allowed"
98     
99     [[ -n "${actions[${args[0]}]}" ]] && action="${args[0]}"
100     
101     return 0
104 dependencies() {
105     for var in "$@"; do
106         if ! command -v $var &>/dev/null; then
107             error "Dependency $var was not found, please install and try again"
108         fi
109     done
113 produce_json() {
114     declare json
115     for l in "${!lights[@]}"; do
116         json+="${lights[$l]},"
117     done
119     lights_json="[${json%,}]"
122 print_json() {
123     if [[ $pretty -eq 1 ]]; then
124         echo "$1"|jq '.' 
125     else
126         echo "$1"|jq -c -M '.'
127     fi
128     
129     exit 0
132 print_status() {
133     die "To be implemented"
136 set_state() {
137     new_state=$1
138     die "To be implemented"
142 find_lights() {
143     # Scan the network for Elgato devices
144     avahi-browse -d local _elg._tcp --resolve -t | grep -v "^\+" >"$temp_file"
146     # Extract data
147     declare {device,hostname,manufacturer,ip,port,mac,protocol,sku}="N/A"
148     cat "$temp_file" > tmp
149     while read -r line; do
151         # Gather information about the light
152         if [[ ($line == =*) && ($line =~ IPv4[[:space:]](.+)[[:space:]]_elg) ]]; then
153             device=$(eval echo "${BASH_REMATCH[1]}") # eval to strip whitespace
154         elif [[ $line =~ hostname.+\[(.+)\] ]]; then hostname=${BASH_REMATCH[1]};
155         elif [[ $line =~ address.+\[(.+)\] ]]; then ip=${BASH_REMATCH[1]};
156         elif [[ $line =~ port.+\[(.+)\] ]]; then port=${BASH_REMATCH[1]};
157         elif [[ $line =~ txt.+\[(.+)\] ]]; then
158             txt=$(eval echo "${BASH_REMATCH[1]}") # eval to strip single and double quotes
160             if [[ $txt =~ mf=([^[[:space:]]*]*) ]]; then manufacturer=${BASH_REMATCH[1]}; fi
161             if [[ $txt =~ id=([^[[:space:]]*]*) ]]; then mac=${BASH_REMATCH[1]}; fi
162             if [[ $txt =~ md=.+[[:space:]]([^[[:space:]]*]*)[[:space:]]id= ]]; then sku=${BASH_REMATCH[1]}; fi
164             
165             # Get information from the light
166             declare {cfg,url,info,light}="{}"
167             if [[ ! (-z $ip) && ! (-z $port) ]]; then
168                 url="http://$ip:$port"
169                 #echo "${call} GET ${url}${settings}"
170                 cfg=$(eval "${call} GET ${url}${settings}") > /dev/null
171                 #echo "${call} GET ${url}${accessory_info}"
172                 info=$(eval "${call} GET ${url}${accessory_info}") > /dev/null
173                 #echo "${call} GET ${url}${devices}"
174                 light=$(eval "${call} GET ${url}${devices}") > /dev/null
175             fi
176             # Store the light as json
177             lights["$ip"]=$( jq -n \
178                     --arg dev "$device" \
179                     --arg hn "$hostname" \
180                     --arg ip "$ip" \
181                     --arg port "$port" \
182                     --arg mf "$manufacturer" \
183                     --arg mac "$mac" \
184                     --arg sku "$sku" \
185                     --arg url "$url" \
186                     --argjson light "$light" \
187                     --argjson cfg "$cfg" \
188                     --argjson info "$info" \
189                     '{device: $dev, manufacturer: $mf, hostname: $hn, url: $url, ip: $ip, 
190                     port: $port, mac: $mac, sku: $sku, light: $light, settings: $cfg, info: $info}' )
191             
192             declare {device,hostname,manufacturer,url,ip,port,mac,protocol,sku,cfg}="N/A"
193         fi
194     done <"$temp_file"
195     
196     rm "$temp_file" 2>/dev/null
199 # Manage user parameters
200 parse_params "$@"
202 # Make sure dependencies are installed
203 dependencies avahi-browse curl notify-send jq
205 find_lights
207 # Fail if we cannot find lights
208 [[ ${#lights[@]} -eq 0 ]] && error "No lights found" 1
210 produce_json
212 # Dispatch actions
213 [[ $action == "usage" ]] && usage
214 [[ $action == "list" ]] && print_json "${lights_json}"
215 [[ $action == "status" ]] && status
216 [[ $action == "on" ]] && set_state 1
217 [[ $action == "off" ]] && set_state 0
221 # Manage printing (parameter -l/--list specicified)