#!/bin/bash

# Utility to manage R2lab relays to control specific devices such as UP4000 mini-PC and QuectelHat
# Relays are LAN485 devices, each with 8 outlets
# Those relays are only controllable through dumb http requests.
# see documentation on http://s3.amazonaws.com/s3.image.smart/download/101-70-C03/stm32cubef3.zip
# and http://wiki.sainsmart.com/index.php/101-70-141

# the target PDU is supposed to be specified using the following env. variables

# PDU_IP is now passed on the command line
PDU_IP=""
# [[ -z "$PDU_IP" ]] && { echo variable PDU_IP is not configured - exiting; exit 255; }
# not required for this hardware
# [[ -z "$PDU_USERNAME" ]] && { echo variable PDU_USERNAME is not configured - exiting; myexit 255; }
# [[ -z "$PDU_PASSWORD" ]] && { echo variable PDU_PASSWORD is not configured - exiting; myexit 255; }


PORT="30000"

COMMAND=$(basename $0)

function relay-status() {

    function help() {
        echo "$0 status: Retrieve the status of a specific R2lab relay"
        echo "Usage: $COMMAND status IP chain outlet#"
        echo -e "\twith chain being 0 (ignored anyway)"
        echo -e "\twith outlet# in [1:8]"
        exit 255
    }

    [[ "$#" == 2 ]] || help

    # provided but ignored
    local chain="$1"; shift
    local outlet="$1"; shift
    [[ "$outlet" -lt 1 || "$outlet" -gt 8 ]] && help

    url="http://$PDU_IP/$PORT/99"
    full_status=$(curl --silent $url | grep -Eo '>[0-1]+' | grep -Eo '[0-1]+')

    n=$((outlet - 1))
    status=${full_status:$n:1}

    case "$status" in
    0)
        echo "relay-$relay@outlet-$outlet: OFF"
        return 1
        ;;
    1)
        echo "relay-$relay@outlet-$outlet: ON"
        return 0
        ;;
    *)
        echo "Could not retrieve relay-$relay@outlet-$outlet status, returned $status"
        return 255
        ;;
    esac
}

function -relay-on-off() {
    local mode="$1"; shift    # 'on' or 'off'

    function help() {
        echo "$COMMAND $mode: switch $mode a specific relay outlet"
        echo "Usage: $COMMAND on IP chain outlet#"
        echo -e "\twith chain being 0 (ignored anyway)"
        echo -e "\twith outlet# in [1:8]"
        exit 255
    }

    [[ "$#" == 2 ]] || help

    # provided but ignored
    local chain="$1"; shift
    local outlet="$1"; shift
    [[ "$outlet" -lt 1 || "$outlet" -gt 8 ]] && help

    relay-status $chain $outlet >& /dev/null
    local current_status=$?

    case $mode in
    on)
        if [ "$current_status" -eq 0 ]; then
            echo "$COMMAND outlet#$outlet already ON"
            exit 0
        fi
        com=1
        ;;
    off)
        # xxx should maybe ping the IP and attempt a soft shutdown before ?
        # if ping -c 1 -W 1 "$devname" >/dev/null; then
        #     if ssh "$devname" true; then
        # xxx also there seems to be a need to invoke this command on the up* boxes
        # /usr/lib/uhd/utils/b2xx_fx3_utils -D
        #         echo "shutting down $devname before turning it off"
        #         ssh $devname shutdown now
        #         sleep 5
        #     fi
        # fi
        if [ "$current_status" -eq 1 ]; then
            echo "$COMMAND outlet#$outlet already OFF"
            exit 0
        fi
        com=0
        ;;
    esac
    local code=$((outlet * 2 - 2 + $com))
    code=$(printf "%02d" $code)
    local url="http://$PDU_IP/$PORT/$code"
    # echo "curl  --silent $url > /dev/null"
    curl --silent $url >/dev/null

}

function relay-on() {
    -relay-on-off on "$@"
}

function relay-off() {
    -relay-on-off off "$@"
}

function relay-probe() {
    echo "Probing relay $PDU_IP"
    for outlet in $(seq 1 8); do
        relay-status 0 $outlet
    done
}

function main() {

    function help() {
        echo "Usage: $0 status|on|off IP chain outlet"
        exit 255
    }

    [[ "$#" -le 1 ]] && { help; exit 1; }
    local subcommand="$1"; shift
    PDU_IP="$1"; shift

    local function="relay-${subcommand}"
    $function "$@"
}

[[ "$1" == "--debug" ]] && {
    shift
    set -x
}
main "$@"