#!/usr/bin/env bash # govee.sh - small CLI wrapper for Govee "control device" API # Requirements: curl, jq, uuidgen (or openssl) # Usage examples at bottom. API_BASE="${GOVEE_API_BASE:-https://openapi.api.govee.com}" CONTROL_ENDPOINT="${API_BASE}/router/api/v1/device/control" #API_KEY="${GOVEE_API_KEY:-}" API_KEY="933194fa-d341-4362-b371-de290cb99a58" mySKU="H6110" myID="20:11:A4:C1:38:9B:CB:54" if [[ -z "$API_KEY" ]]; then echo "ERROR: Set GOVEE_API_KEY environment variable (export GOVEE_API_KEY=xxxx)" exit 2 fi get_info() { local reqid reqid="$(uuid)" # local entry="router/api/v1/user/devices" # json=$(curl -s -k ${API_BASE}/${entry} \ # -H "Content-Type: application/json" \ # -H "Govee-API-Key: ${API_KEY}") # sku=$(echo "$json" | jq -r ".data[].sku") # device=$(echo "$json" | jq -r ".data[].device") echo curl -s -k -X POST "${API_BASE}/router/api/v1/device/state" \ -H "Content-Type: application/json" \ -H "Govee-API-Key: ${API_KEY}" \ -d "{ \"requestId\": \"${uuid}\", \"payload\": { \"sku\": \"${mySKU}\", \"device\": \"${myID}\" } }" # echo "SKU=$sku" # echo "device=$device" # echo "json:" echo "$json" } # helpers uuid() { if command -v uuidgen >/dev/null 2>&1; then uuidgen else # fallback date +%s%N | sha1sum | cut -c1-32 fi } # convert hex/rrggbb or r,g,b to integer (0..16777215) rgb_to_int() { local in="$1" if [[ "$in" =~ ^#?[0-9A-Fa-f]{6}$ ]]; then # hex in="${in#'#'}" printf "%d\n" "$((0x$in))" return fi # r,g,b IFS=',' read -r r g b <<< "$in" r=${r:-0}; g=${g:-0}; b=${b:-0} # validate numeric for val in "$r" "$g" "$b"; do if ! [[ "$val" =~ ^[0-9]+$ ]] || (( val < 0 )) || (( val > 255 )); then echo "ERR" # caller should handle return 1 fi done echo $(( (r << 16) + (g << 8) + b )) } # build and send the control request _govee_control() { local sku="$1"; shift local device="$1"; shift local type="$1"; shift local instance="$1"; shift local value="$1" local reqid reqid="$(uuid)" local body body=$(jq -n \ --arg rid "$reqid" \ --arg sku "$sku" \ --arg device "$device" \ --arg type "$type" \ --arg instance "$instance" \ --argjson value "$value" \ '{requestId:$rid, payload: { sku:$sku, device:$device, capability: { type:$type, instance:$instance, value:$value } } }') curl -sS -X POST "$CONTROL_ENDPOINT" \ -H "Content-Type: application/json" \ -H "Govee-API-Key: $API_KEY" \ -d "$body" } print_usage() { cat < [options] Commands: power Turn device on or off toggle <0|1> brightness <0..100> Set brightness (range depends on device) color_rgb Set RGB color (hex like ff8800 or "255,100,0") temp_k Set color temperature (e.g. 2700) mode Set a mode or scene by numeric value raw Accepts raw JSON payload from stdin and sends it Examples: ./govee.sh power H605C "64:09:C5:32:37:36:2D:13" on ./govee.sh brightness H605C "64:09:C5:32:37:36:2D:13" 50 ./govee.sh color_rgb H605C "64:09:C5:32:37:36:2D:13" ff0088 ./govee.sh color_rgb H605C "64:09:C5:32:37:36:2D:13" 255,0,136 Note: You must know device SKU and device id (from /user/devices endpoint). EOF } if (( $# == 0 )); then print_usage exit 1 fi ### cmd="$1"; shift cmdline="" while [ -n "$1" ]; do case "$1" in --sku) mySKU="$2"; shift 2;; --dev|--id) myID="$2"; shift 2;; -c|--cmd) cmd="$2"; shift 2;; *) break;; esac done case "$cmd" in in*) get_info exit ;; po*) # args: sku device on|off sku="$mySKU"; device="$myID"; state="$1" if [[ -z "$sku" || -z "$device" || -z "$state" ]]; then print_usage; exit 1; fi if [[ "$state" == "on" ]]; then val=1; else val=0; fi _govee_control "$sku" "$device" "devices.capabilities.on_off" "powerSwitch" "$val" | jq . ;; to*) # sku device instance 0|1 sku="$mySKU"; device="$myID"; instance="$1"; val="$2" _govee_control "$sku" "$device" "devices.capabilities.toggle" "$instance" "$val" | jq . ;; br*) sku="$mySKU"; device="$myID"; val="$1" if [[ -z "$val" ]]; then print_usage; exit 1; fi _govee_control "$sku" "$device" "devices.capabilities.range" "brightness" "$val" | jq . ;; co*) sku="$mySKU"; device="$myID"; color="$1" if [[ -z "$color" ]]; then print_usage; exit 1; fi rgbint=$(rgb_to_int "$color") || { echo "Bad color"; exit 1; } _govee_control "$sku" "$device" "devices.capabilities.color_setting" "colorRgb" "$rgbint" | jq . ;; te*) sku="$mySKU"; device="$myID"; kelvin="$1" if [[ -z "$kelvin" ]]; then print_usage; exit 1; fi _govee_control "$sku" "$device" "devices.capabilities.color_setting" "colorTemperatureK" "$kelvin" | jq . ;; mo*) sku="$mySKU"; device="$myID"; instance="$1"; val="$2" _govee_control "$sku" "$device" "devices.capabilities.mode" "$instance" "$val" | jq . ;; raw) # read raw payload JSON from stdin (should include payload object) body=$(cat -) if [[ -z "$body" ]]; then echo "Provide JSON on stdin"; exit 1; fi curl -sS -X POST "$CONTROL_ENDPOINT" \ -H "Content-Type: application/json" \ -H "Govee-API-Key: $API_KEY" \ -d "$body" | jq . ;; *) print_usage exit 1 ;; esac