#!/usr/bin/env bash set -e set -u _scriptName="autoCare" _scriptVersion="Master 2.14" deviceName="" enableLog=0 verbose=0 ts=$(date +%y%m%d_%H%M%S) cred="admin:admin1234" monitor=0 declare -A monitorBeacons declare -A monitorBeaconsCount declare -A lockPID signalC=50 #Signal from single beacon before restart strength="" threshold=-88 beaconMAC="" beaconType="" password="4indoorpos2B" logfile="/tmp/autoCare_${ts}.log" listen=0 errMSG="" avrageIN=() avrageOUT=() outHigh=-150 outLow=150 inHigh=-150 inLow=150 avrMAC="" printOut=0 pid= function ex { eval "exec ${fifoC}<>$fifoN" /usr/bin/expect >&${fifoC} <" send "follow $1\r" expect { "You follow*" { set bar "\$expect_out(0,string)" puts "\$bar\n" expect "START SignalUpdate" { expect "END SignalUpdate" { set foo "\$expect_out(buffer)" puts "START TRACKER:$1\n\$foo\nEND TRACKER:$1\n" expect -re {.*} {} exp_continue } } } "Did not find any device to follow" { exit 2 } } EOD } function ts { date +%y-%m-%dT%H:%M:%S } function println { tsNow=$(ts) if (( $enableLog == 0 )); then printf '%-20s%-17s%-22s%-8s%-15s%s\n' "$tsNow" "Tracker:$tracker" "Beacon:$beaconMAC" "($strength)" "$beaconType" "$@" else printf '%-20s%-20s%-22s%-10s%-16s%s\n' "$tsNow" "Tracker:$tracker" "Beacon:$beaconMAC" "($strength)" "$beaconType" "$@" | tee -a "$logfile" fi } function printCalc { local msg msg=$(tr -d \" <<<$@) printf '%-20s%-17s%-22s\n' "$tsNow" "Tracker:$tracker" "CALC:$msg" } function error { tsNow=$(ts) printf 'ERROR - %s\n' "$@" } function step { tsNow=$(ts) printf '==>%15s\n' "$@" } function reset { if (( $# == 2)); then _IP="$1" _MAC="$2" createLock "$_MAC" 60 if curl -u "$cred" -X POST -d "act=Reset" http://${_IP}/firmware2.htm >/dev/null 2>&1; then return 0 else return 1 fi else error "Missing arg" fi } function factory { if (( $# == 2 )); then _IP="$1" _MAC="$2" createLock "$_MAC" 60 if curl -u "$cred" -X POST -d "act=Factory+Reset" http://${_IP}/firmware2.htm >/dev/null 2>&1; then return 0 else return 1 fi fi } function byebye { echo if (( ${#avrageIN[@]} > 0 )); then avrageC=0 for i in ${avrageIN[@]}; do avrageC=$(( $avrageC + $i )) done if [[ -z $avrMAC ]]; then echo "Avrage strength from all IN (${#avrageIN[@]}): $(( $avrageC / ${#avrageIN[@]} ))" else echo "Avrage strength from $avrMAC IN (${#avrageIN[@]}): $(( $avrageC / ${#avrageIN[@]} ))" fi echo "IN strength MIN:$inLow MAX: $inHigh" fi echo avrageC=0 if (( ${#avrageOUT[@]} >0 )); then for i in ${avrageOUT[@]}; do avrageC=$(( $avrageC + $i )) done if [[ -z $avrMAC ]]; then echo "Avrage strength from all OUT ${#avrageOUT[@]}: $(( $avrageC / ${#avrageOUT[@]} ))" else echo "Avrage strength from $avrMAC OUT (${#avrageOUT[@]}): $(( $avrageC / ${#avrageOUT[@]} ))" fi echo "Out strength MIN:$outLow MAX: $outHigh" fi if (( $monitor == 1 )); then step "Removing fifo" [[ -p /tmp/.${device}.fifo ]] && rm /tmp/.${device}.fifo fi if (( $listen == 1 )); then step "Cleaning up locks" for mac in ${!lockPID[@]}; do wait ${lockPID[$mac]} [[ -f /tmp/.${mac}.lock ]] && rm "/tmp/.${mac}.lock" done # for f in ${!fifoFD[@]}; do # step "Closing FD $f" # eval "exec $f>&-" # done fi if kill -0 $pid &>/dev/null; then step "Killing childs" kill -TERM $pid fi kill 0 } function findIP { #Check packages if (( $# == 1 )); then _MAC="$1" interface=$(route | grep default | awk '{ print $8 }') subnet=$(ip route | grep "$interface proto" | awk '{ print $1 }') #Make MAC of serial (( ${#_MAC} == 12 )) && _MAC=$(sed 's/../&:/g; s/:$//' <<<"$_MAC") if (( ${#_MAC} == 17 )); then #Trying ARP beaconIP=$(arp -a | grep -i $_MAC | sed 's/\(.*(\)\(.*\)\().*\)/\2/g') ping -c1 $beaconIP >/dev/null 2>&1 && return #Trying nmap #beaconIP=$(nmap -sn "$subnet" | egrep -i -A1 "$_MAC" | tail -n1 | sed 's/\(.*for \)\(.*\)/\2/'g) fi fi } function createLock { if (( $# == 2 )); then beaconHost=$1 sleepT=$2 (( $verbose == 1 )) && println "Creating lock file for $sleepT seconds" touch /tmp/.$beaconHost.lock ( sleep 30 && rm /tmp/.$beaconHost.lock ) & lockPID[$beaconHost]=$! fi } function init { trackers=() screenName="autCare_$(date +%d%m%y_%H%M%S)" #Find trackers file=$(find /opt/sensio/indoorpos/Data/OfflineAPI/ -type f -print | xargs grep -l "1041" | head -n1) mapfile -t trackers < <(jq < "$file" '.Devices[] | select(.Type==1039 or .Type==1041) | .Serial' | tr -d \") echo "Tracker count: ${#trackers[@]}" #Start screen i=0 screen -ls | grep -q "$screenName" || screen -dmS "$screenName" for z in "${trackers[@]}"; do screen -S "$screenName" -t "$z" -X screen $i screen -S "$screenName" -t "$z" -p $i -X stuff "autoCare -m \"$z\"\n" ((++i)) done screen -S "$screenName" -t "listen" -X screen $i if (( $enableLog == 0 )); then screen -S "$screenName" -t "listen" -p $i -X stuff "autoCare -l\n" else screen -S "$screenName" -t "listen" -p $i -X stuff "autoCare -lvw\n" fi exit 0 } function help { cat <<-EOD ################################################################################################################################ # autoCare HELP?? # ################################################################################################################################ -a Filter avrage calculation on one beacon. Usage: autoCare -a -h This text -l Listen on signals from trackers and restarte beacon host if nesessary -m Monitor a tracker. Usage $_scriptName -m -s Reset beacon host signal threshold override. Default=$signalC. Usage: $_scriptName -s -v Vebose output then argument -l is in use -w Write log file to /tmp/ when using argument -l EOD } trap "byebye" EXIT tput clear fd=10 fifoC=$(( $(find /tmp -name .*.fifo | wc -l) + fd )) while getopts ":a:him:ls:vw" o; do case "${o}" in a) #Avrage avrMAC=${OPTARG} ;; h) help exit 0 ;; i) init ;; l) ########Listen listen=1 echo "Listening to devices" ;; m) device="${OPTARG}" monitor=1 fifoN="/tmp/.${device}.fifo" [[ -p "$fifoN" ]] || mkfifo "$fifoN" echo "Fetching signals from $device" ( ex "$device" ) & pid=$! (( $? == 2 )) && echo "Could not find device $device" && exit 1 ;; s) #Override default signal threshold signalC="${OPTARG}" echo "Overriding signal threshold with $signalC" ;; v) verbose=1 ;; w) #Write log enableLog=1 ;; esac done shift $((OPTIND-1)) filter="${1:-}" declare -A fifoFD trap 'exit 1' INT mapfile -t fifos < <(find /tmp -type p) fdArr=() fifosC=${#fifos[@]} (( $fifosC == 0 )) && error "No trackers to follow" && exit 1 (( $verbose == 1 )) && echo "Found: $fifosC" ##Create fd for f in ${fifos[@]}; do fifoFD[$fd]="$f" fdArr+="$fd" ((++fd)) done while true; do for f in ${!fifoFD[@]}; do trap 'exit 0' INT eval "exec ${f}<${fifoFD[$f]}" while read -t 1 -u$f line; do case "$line" in *"START TRACKER"*) tracker=$(cut -d : -f2 <<<$line | tr -d \r\n) ;; *SignalStrength*) strength=$(awk '{print $2}' <<<"$line" | tr -d ',\r') ;; *"Mac"*) beaconMAC=$(cut -d "\"" -f4 <<<"$line") beaconType="${beaconMAC:12}" beaconMAC="${beaconMAC:0:12}" case "$beaconType" in "I") beaconType="In (LED:1)" ;; "O") beaconType="Out (LED:2)" ;; esac ;; *"Cannot find device"*) echo "IPS did not find the device $device" continue ;; *"You follow"*) deviceName=$(awk '{ print $4 }' <<<$line) echo "Following $deviceName" ;; *"START CalculationUpdate"*) echo && continue ;; *"\"Position\""*) printCalc "$line" && continue ;; *"StrongestSignal\": \""*) printCalc "$line" && continue ;; *"\"FLOOR"*) printCalc "$line" && continue ;; *"END CalculationUpdate"*) echo && continue ;; ?|*) echo $line >/dev/null ;; esac if ! [[ -z "$strength" ]] && ! [[ -z "$beaconMAC" ]] && ! [[ -z "$tracker" ]]; then if [[ -z $avrMAC ]] || [[ $avrMAC == $beaconMAC ]]; then if [[ "$beaconType" =~ "In" ]]; then avrageIN+=( $strength ) (( $strength > $inHigh )) && inHigh=$strength (( $strength < $inLow )) && inLow=$strength fi if [[ "$beaconType" =~ "Out" ]]; then avrageOUT+=( $strength ) (( $strength > $outHigh )) && outHigh=$strength (( $strength < $outLow )) && outLow=$strength fi fi if (( $listen == 1 )); then if ! [[ -f /tmp/.$beaconMAC.lock ]]; then if ! [[ ${!monitorBeacons[*]} =~ $beaconMAC ]]; then monitorBeacons[$beaconMAC]="$beaconType" monitorBeaconsCount[$beaconMAC]=1 else if [[ ${monitorBeacons[$beaconMAC]} == $beaconType ]]; then if [[ ${!monitorBeaconsCount[*]} =~ $beaconMAC ]] && (( ${monitorBeaconsCount[$beaconMAC]} >= $signalC )); then ##Reset beacon host. println "Reset beacon host" #Find beacon host by MAC findIP "$beaconMAC" if reset "$beaconIP" "$beaconMAC"; then println "($beaconIP) is reset" else println "failed to reset" fi unset 'monitorBeacons[$beaconMAC]' unset 'monitorBeaconsCount[$beaconMAC]' else if (( $strength >= $threshold )); then ((monitorBeaconsCount[$beaconMAC]++)) println "Signals left to reset: ${monitorBeaconsCount[$beaconMAC]}/$signalC" else (( $verbose == 1 )) && println "Signal to weak to count: ${monitorBeaconsCount[$beaconMAC]}/$signalC" fi fi else ##Both beacon are OK println "Beacons are OK" unset 'monitorBeacons[$beaconMAC]' unset 'monitorBeaconsCount[$beaconMAC]' createLock "$beaconMAC" 30 #break fi fi else (( $verbose == 1 )) && println "Beacon is locked" fi else if [[ -n $filter ]]; then println | egrep -i --color "$filter" else println fi fi beaconMAC="" beaconType="" strength="" fi done done done exit 0