#!/bin/bash

# ==========================================================================
# UNIVERSAL KASA HS103 NAGIOS PLUGIN
# Usage: ./check_kasa.sh <IP_ADDRESS> <relay_state|rssi|on_time|sw_ver|mac>
# ==========================================================================

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 <IP> <metric>"
    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
