#! /bin/bash

# Program Name:	hactl
# Purpose:	Read from (i.e. "get") and write to (i.e. "set") the Home Automation (HA) panel's relay control-lines.
#		Mimics the wiringPi "gpio" command with respect to:
#		  1. non-destructive; "reading" of BCM GPIO lines configured as outputs does not reconfigure the lines as inputs, and
#		  2. persistence; maintaining the GPIO output (high/low driven) states after the gpio command exits.
#		When configured; All relay control-lines are outputs (driven high or low), so "reading" in this context returns the line's state.
#		For this HA application; The relays are wired NC (normally closed, vice normally open), so this script uses negative logic.
# Usage:	hactl line get
#		hactl line set on|off
#
#		"line" is a number in the set {1..8} representing one of eight relay control-lines defined in HA_TABLE_FILE.
#
# Change History:
# Date		Programmer					Description
# ----------	-------------------------------------------	---------------------------------------------------------------------------------
# 2020-05-26	Bernie Karmilowicz <karmilow@intencorp.com>	created
# 2021-12-20	Bernie Karmilowicz <karmilow@intencorp.com>	changed from wiringPi to gpiod shell commands 
# 2024-08-13	Bernie Karmilowicz <karmilow@intencorp.com>	Added a short delay ("sleep") after the pkill command to allow the system time to
#								terminate the old gpioset process.

BAD_CMD_LINE_ARGS=0
HA_TABLE_FILE=/home/pi/etc/ha.table
LINE_FOUND=0

if [ "$1" != "1" -a "$1" != "2" -a "$1" != "3" -a "$1" != "4" -a "$1" != "5" -a "$1" != "6" -a "$1" != "7" -a "$1" != "8" ] ; then
  echo "hactl usage error: The first (i.e. \"line\") argument must be an integer in the set {1..8}"
  BAD_CMD_LINE_ARGS=1
fi

if [ "$2" != "set" -a "$2" != "get" ] ; then
  echo "hactl usage error: The second argument must specify an I/O action (either \"get\" or \"set\")"
  BAD_CMD_LINE_ARGS=1
fi

if [ "$2" == "set" -a "$3" != "on" -a "$3" != "off" ] ; then
  echo "hactl usage error: A third argument (either \"on\" or \"off\") is required when the second argument is \"set\""
  BAD_CMD_LINE_ARGS=1
fi

if [ $BAD_CMD_LINE_ARGS -ne 0 ] ; then
  echo "hactl usage:  hactl line get"
  echo "              hactl line set on|off"
  echo "" 
  echo "              \"line\" is a number in the set {1..8} representing one of eight relay control-lines"
  exit -1
fi

if ! [ -r $HA_TABLE_FILE ] ; then
  echo "hactl execution error: $HA_TABLE_FILE does not exist or is not readable"
  exit -1
fi

while IFS= read -r record ; do
  if [ `echo $record | cut -d' ' -f1,1` == "$1" ] ; then
    LINE_FOUND=1
    break
  fi 
done < $HA_TABLE_FILE

if [ $LINE_FOUND -eq 0 ] ; then
  echo "hactl execution error: $HA_TABLE_FILE does not contain a record for \"line\" $1"
  exit -1
fi

BCM_GPIO=`echo $record | cut -d' ' -f2,2`

if [ "$2" == "get" ] ; then
  if [ `pgrep -c -f "gpioset -B disable -m signal -b 0 $BCM_GPIO="` -eq 1 ] ; then 
    pgrep -a -f "gpioset -B disable -m signal -b 0 $BCM_GPIO=" | cut -d '=' -f 2,2
  else
    echo "Relay-control line $1 (BCM GPIO line $BCM_GPIO) is not being driven."
    exit -1
  fi
else
  if [ `pgrep -c -f "gpioset -B disable -m signal -b 0 $BCM_GPIO="` -eq 1 ] ; then
    LINE_STATE=`pgrep -a -f "gpioset -B disable -m signal -b 0 $BCM_GPIO=" | cut -d '=' -f 2,2`
    if [ $LINE_STATE -eq 1 -a "$3" == "on" ] || [ $LINE_STATE -eq 0 -a "$3" == "off" ] ; then
      pkill -2 -f "gpioset -B disable -m signal -b 0 $BCM_GPIO="
      sleep 2
    else
      exit 0
    fi
  fi
  if [ "$3" == "on" ] ; then
    gpioset -B disable -m signal -b 0 $BCM_GPIO=0
  else
    gpioset -B disable -m signal -b 0 $BCM_GPIO=1
  fi
fi

exit 0

