#!/bin/bash # ========================================================================== # UNIVERSAL KASA HS103 NAGIOS PLUGIN # Usage: ./check_kasa.sh # ========================================================================== plugIP="" plugPort="9999" metric="" while getopts "H:m:P:" opt; do case "$opt" in H) plugIP="$OPTARG";; P) plugPort="$OPTARG";; m) metric="$OPTARG";; esac done shift $((OPTIND - 1)) restOfLine="$@" if [ -z "$plugIP" ] || [ -z "$metric" ]; then echo "UNKNOWN - Missing arguments. Usage: $0 " echo " metric: relay_state rssi on_time sw_ver hw_ver mac model" exit 3 fi # Pre-encrypted XOR payload for get_sysinfo # NOTE: Why this value is what it is is beyond the scope of this script PAYLOAD="AAAAI9Dw0qHYq9+61/XPtJS20bTAn+yV5o/hh+jK8J7rh+vLtpbr" # Fetch raw binary stream as clean decimal strings RAW_STREAM=$(echo "$PAYLOAD" | base64 -d | nc -w 3 "$plugIP" "$plugPort" | od -An -v -t u1) if [ -z "$RAW_STREAM" ]; then echo "CRITICAL - No network response from HS103 at $plugIP" exit 2 fi # XOR Decryption Loop DECRYPTED_JSON="" KEY=171 for BYTE in $RAW_STREAM; do if [ "$BYTE" -eq 0 ] && [ -z "$DECRYPTED_JSON" ]; then continue fi OUTPUT=$(( BYTE ^ KEY )) KEY=$BYTE DECRYPTED_JSON+="$(printf "\\$(printf '%03o' "$OUTPUT")")" done # Clean out trailing encryption anomalies CLEAN_JSON=$(echo "$DECRYPTED_JSON" | grep -o '{.*}' | sed 's/.$//') # Extract the alias name universally for clean alert messaging ALIAS=$(echo "$CLEAN_JSON" | jq -r '.get_sysinfo.alias') # Dynamic Evaluation Engine based on your CLI parameter Choice case "$metric" in relay_state) VALUE=$(echo "$CLEAN_JSON" | jq '.get_sysinfo.relay_state') if [ "$VALUE" -eq 1 ]; then echo "OK - ${ALIAS} Relay is ON | relay_state=1;;;;" exit 0 else echo "CRITICAL - ${ALIAS} Relay is OFF | relay_state=0;;;;" exit 2 fi ;; rssi) VALUE=$(echo "$CLEAN_JSON" | jq '.get_sysinfo.rssi') # Standard Wi-Fi signal threshold parameters if [ "$VALUE" -ge -70 ]; then echo "OK - ${ALIAS} Wi-Fi Signal Strength: ${VALUE} dBm | rssi=${VALUE};-75;-85;;" exit 0 elif [ "$VALUE" -lt -70 ] && [ "$VALUE" -ge -82 ]; then echo "WARNING - ${ALIAS} Wi-Fi Signal Weak: ${VALUE} dBm | rssi=${VALUE};-75;-85;;" exit 1 else echo "CRITICAL - ${ALIAS} Wi-Fi Signal Dropping Out: ${VALUE} dBm | rssi=${VALUE};-75;-85;;" exit 2 fi ;; on_time) VALUE=$(echo "$CLEAN_JSON" | jq '.get_sysinfo.on_time') # Converts raw seconds to readable hours for clear telemetry status HOURS=$(echo "scale=2; $VALUE / 3600" | bc) echo "OK - ${ALIAS} Continuous Active Runtime: ${HOURS} Hours | on_time=${VALUE};;;;" exit 0 ;; sw_ver|hw_ver|mac|model) # Dynamic handling for inventory/metadata parameters VALUE=$(echo "$CLEAN_JSON" | jq -r ".get_sysinfo.${metric}") echo "OK - ${ALIAS} ${metric}: ${VALUE}" exit 0 ;; *) echo "UNKNOWN - Unsupported metric: ${metric}. Choose: relay_state, rssi, on_time, sw_ver, hw_ver, mac, model" exit 3 ;; esac