[
  {
    "path": "README.md",
    "content": "presence\n=======\n\n***Note: as of `presence` 0.5.1, triggered scans, guest scanning, and beacon scanning are removed from `presence.sh` for simplification. Please consider using [monitor](http://github.com/andrewjfreyer/monitor) instead for beacon scanning and detection and for generic device detection. It is unlikely that `presence` will receive substantive updates after version 0.5.1.***\n\n____\n\n\n***TL;DR***: *Bluetooth-based presence detection useful for [mqtt-based](http://mqtt.org) home automation. More granular, responsive, and reliable than device-reported GPS. Cheaper, more reliable, more configurable, and less mqtt-spammy than Happy Bubbles. Does not require any app to be running or installed. Does not require device pairing. Designed to run as service on a [Raspberry Pi Zero W](https://www.raspberrypi.org/products/raspberry-pi-zero-w/).*\n\nNote that the more frequently you scan for devices, the more 2.4GHz bandwidth you will use. This script may cause interference with Wi-Fi or other bluetooth devices for particularly short delays between scans. \n\n<h1>Summary</h1>\n\nA JSON-formatted MQTT message is reported to a broker whenever a specified bluetooth device responds to a **name** query. If the device responds, the JSON message includes the name of the device and a **confidence** of 100. \n\nAfter a delay, another **name** query is sent and, if the device does not respond, a verification-of-absence loop begins that queries for the device (on a shorter interval) a set number of times. Each time, the device does not respond, the **confidence** is reduced, eventually to 0. \n\nA configuration file defines 'owner devices' that contains the mac addresses of the devices you'd like to regularly ping to determine presence. \n\nTopics are formatted like this:\n\n     location/pi_zero_location/00:00:00:00:00:00 \n\nMessages are JSON formatted and contain **name** and **confidence** fields, including a javascript-formatted timestamp and a duration of a particular scan (in ms):\n\n     { confidence : 100, name : Andrew’s iPhone, scan_duration_ms: 500, timestamp : Sat Apr 21 2018 11:52:04 GMT-0600 (MDT)}\n     { confidence : 0, name : Andrew’s iPhone or Unknown, scan_duration_ms: 5000, timestamp : Sat Apr 21 2018 11:52:04 GMT-0600 (MDT)}\n\n___\n\n<h1>Example Use with Home Assistant</h1>\n\nThe presence script can be used as an input to a number of [mqtt sensors](https://www.home-assistant.io/components/sensor.mqtt/) in [Home Assistant.](https://www.home-assistant.io). Output from these sensors can be averaged to give a highly-accurate numerical occupancy confidence. \n\nIn order to detect presence in a home that has three floors and a garage, we might include one Raspberry Pi per floor. For average houses, a single well-placed sensor can probably work, but for more reliability at the edges of the house, more sensors are better. \n\n\n```\n- platform: mqtt\n  state_topic: 'location/first floor/00:00:00:00:00:00'\n  value_template: '{{ value_json.confidence }}'\n  unit_of_measurement: '%'\n  name: 'Andrew First Floor'\n\n- platform: mqtt\n  state_topic: 'location/second floor/00:00:00:00:00:00'\n  value_template: '{{ value_json.confidence }}'\n  unit_of_measurement: '%'\n  name: 'Andrew Second Floor'\n\n- platform: mqtt\n  state_topic: 'location/third floor/00:00:00:00:00:00'\n  value_template: '{{ value_json.confidence }}'\n  unit_of_measurement: '%'\n  name: 'Andrew Third Floor'\n\n- platform: mqtt\n  state_topic: 'location/garage/00:00:00:00:00:00'\n  value_template: '{{ value_json.confidence }}'\n  unit_of_measurement: '%'\n  name: 'Andrew Garage'\n```\n\nThese sensors can be combined/averaged using a [min_max](https://www.home-assistant.io/components/sensor.min_max/):\n\n```\n- platform: min_max\n  name: \"Andrew Home Occupancy Confidence\"\n  type: mean\n  round_digits: 0\n  entity_ids:\n    - sensor.andrew_garage\n    - sensor.andrew_third_floor\n    - sensor.andrew_second_floor\n    - sensor.andrew_first_floor\n```\n\nSo, as a result of this combination, we use the entity **sensor.andrew_home_occupancy_confidence** in automations to control the state of an **input_boolean** that represents a very high confidence of a user being home or not. \n\nAs an example:\n\n```\n- alias: Andrew Occupancy \n  hide_entity: true\n  trigger:\n    - platform: numeric_state\n      entity_id: sensor.andrew_home_occupancy_confidence\n      above: 10\n  action:\n    - service: homeassistant.turn_on\n      data:\n        entity_id: input_boolean.andrew_occupancy\n```\n\n___\n\n\n<h1>Installation Instructions (Raspbian Jessie Lite Stretch):</h1>\n\n<h2>Setup of SD Card</h2>\n\n1. Download latest version of **jessie lite stretch** [here](https://downloads.raspberrypi.org/raspbian_lite_latest)\n\n2. Download etcher from [etcher.io](https://etcher.io)\n\n3. Image **jessie lite stretch** to SD card. [Instructions here.](https://www.raspberrypi.org/magpi/pi-sd-etcher/)\n\n4. Mount **boot** partition of imaged SD card (unplug it and plug it back in)\n\n5. **[ENABLE SSH]** Create blank file, without any extension, in the root directory called **ssh**\n\n6. **[SETUP WIFI]** Create **wpa_supplicant.conf** file in root directory and add Wi-Fi details for home Wi-Fi:\n\n```\ncountry=US\n    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n    update_config=1\n\nnetwork={\n    ssid=\"Your Network Name\"\n    psk=\"Your Network Password\"\n    key_mgmt=WPA-PSK\n}\n```\n\n 7. **[FIRST STARTUP]** Insert SD card and power on Raspberry Pi Zero W. On first boot, the newly-created **wpa_supplicant.conf** file and **ssh** will be moved to appropriate directories. Find the IP address of the Pi via your router. One method is scanning for open ssh ports (port 22) on your local network:\n```\nnmap 192.168.1.0/24 -p 22\n```\n\n<h2>Configuration and Setup of Raspberry Pi Zero W</h2>\n\n1. SSH into the Raspberry Pi (password: raspberry):\n```\nssh pi@theipaddress\n```\n\n2. Change the default password:\n```\nsudo passwd pi\n```\n\n3. **[PREPARATION]** Update and upgrade:\n\n```\nsudo apt-get update\nsudo apt-get upgrade -y\nsudo apt-get dist-upgrade -y\nsudo rpi-update\nsudo reboot\n```\n\n5. **[BLUETOOTH]** Install Bluetooth Firmware:\n```\n#install bluetooth drivers for Pi Zero W\nsudo apt-get install pi-bluetooth\n\n#verify that bluetooth is working\nsudo service bluetooth start\nsudo service bluetooth status\n```\n\n6. **[OPTIONAL: BLUEZ UPGRADE]** Compile/install latest **bluez** \n\nThis is not strictly required anymore, as **pi-bluetooth** appears to have been updated to support bluez 0.5.43.\n\n```\n\n#purge old bluez\nsudo apt-get --purge remove bluez\n\n#get latest version number from: https://www.kernel.org/pub/linux/bluetooth/\n#current version as of this writing is 5.49\ncd ~; wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.49.tar.xz\ntar xvf bluez-5.49.tar.xz\n\n#update errythang again\nsudo apt-get update\n\n#install necessary packages\nsudo apt-get install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev\n\n#move into new unpacked directory\ncd bluez-5.49\n\n#set exports\nexport LDFLAGS=-lrt\n\n#configure \n./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --enable-library -disable-systemd\n\n#make & install\nmake\nsudo make install\n\n#cleanup\ncd ~\nrm -r bluez-5.49/\nrm bluez-5.49.tar.xz\n\n#update again\nsudo apt-get update\nsudo apt-get upgrade\n\n#verify bluez version \nbluetoothd -v\n```\n\n7. **[REBOOT]**\n```\nsudo reboot\n```\n\n8. **[INSTALL MOSQUITTO]**\n```\n\n# get repo key\nwget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key\n\n#add repo\nsudo apt-key add mosquitto-repo.gpg.key\n\n#download appropriate lists file \ncd /etc/apt/sources.list.d/\nsudo wget http://repo.mosquitto.org/debian/mosquitto-stretch.list\n\n#update caches and install \napt-cache search mosquitto\nsudo apt-get update\nsudo aptitude install libmosquitto-dev mosquitto mosquitto-clients\n```\n\n\n9. **[INSTALL PRESENCE]**\n```\n#install git\ncd ~\nsudo apt-get install git\n\n#clone this repo\ngit clone git://github.com/andrewjfreyer/presence\n\n#enter presence directory\ncd presence/\n```\n\n10. **[CONFIGURE PRESENCE]** create file named **mqtt_preferences** and include content:\n```\nnano mqtt_preferences\n```\n\nThen...\n\n```\nmqtt_address=\"ip.address.of.broker\"\nmqtt_port=\"optional broker network port number. Defaults to 1883\"\nmqtt_user=\"your broker username\"\nmqtt_password=\"your broker password\"\nmqtt_topicpath=\"location\"\nmqtt_room=\"your pi's location\"\n```\n\n11. **[CONFIGURE PRESENCE]** create file named **owner_devices** and include mac addresses of devices on separate lines. \n\n```\nnano owner_devices\n```\n\nThen...\n\n```\n00:00:00:00:00 #comments \n00:00:00:00:00\n```\n\n12. **[CONFIGURE SERVICE]** Create file at **/etc/systemd/system/presence.service** and include content:\n\n```\nsudo nano /etc/systemd/system/presence.service\n```\n\nThen...\n\n```\n[Unit]\nDescription=Presence service\n\n[Service]\nUser=root\nExecStart=/bin/bash /home/pi/presence/presence.sh &\nWorkingDirectory=/home/pi/presence\nRestart=always\nRestartSec=10\n\n[Install]\nWantedBy=multi-user.target\n\n```\n\n13. **[CONFIGURE SERVICE]** Enable service by:\n```\nsudo systemctl enable presence.service\nsudo systemctl start presence.service\n```\n\nThat's it. Your broker should be receiving messages and the presence service will restart each time the Raspberry Pi boots.  \n\n"
  },
  {
    "path": "presence.sh",
    "content": "\n#!/bin/bash\n\n# ----------------------------------------------------------------------------------------\n# GENERAL INFORMATION\n# ----------------------------------------------------------------------------------------\n#\n# Written by Andrew J Freyer\n# GNU General Public License\n# http://github.com/andrewjfreyer/presence\n#\n# ----------------------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------------------\n# INCLUDES & VARIABLES\n# ----------------------------------------------------------------------------------------\n\n#VERSION NUMBER\nVERSION=0.5.1\n\n#COLOR OUTPUT FOR RICH DEBUG \nORANGE='\\033[0;33m'\nRED='\\033[0;31m'\nNC='\\033[0m'\nGREEN='\\033[0;32m'\nPURPLE='\\033[1;35m'\n\n#BASE DIRECTORY REGARDLESS OF INSTALLATION; ELSE MANUALLY SET HERE\nbase_directory=$(dirname \"$(readlink -f \"$0\")\")\n\n#FIND MQTT PATH, ELSE MANUALLY SET HERE\nmosquitto_pub_path=$(which mosquitto_pub)\nmosquitto_sub_path=$(which mosquitto_sub)\n\n#ERROR CHECKING FOR MOSQUITTO PUBLICATION \n[ -z \"$mosquitto_pub_path\" ] && echo \"Required package 'mosquitto_pub' not found. Please install.\" && exit 1\n[ -z \"$mosquitto_sub_path\" ] && echo \"Required package 'mosquitto_sub' not found. Please install.\" && exit 1\n\n# ----------------------------------------------------------------------------------------\n# LOAD PREFERENCES\n# ----------------------------------------------------------------------------------------\n\n#OR LOAD FROM A SOURCE FILE\nif [ ! -f \"$base_directory/behavior_preferences\" ]; then \n\techo -e \"${GREEN}presence $VERSION ${RED}WARNING:  ${NC}Behavior preferences are not defined:${NC}\"\n\techo -e \"/behavior_preferences. Creating file and setting default values.${NC}\"\n  \techo -e \"\" \n\n  \t#DEFAULT VALUES\n  \techo \"\n#DELAY BETWEEN SCANS OF OWNER DEVICES WHEN AWAY FROM HOME\ndelay_between_owner_scans_away=6\n\n#DELAY BETWEEN SCANS OF OWNER DEVICES WHEN HOME \ndelay_between_owner_scans_present=30\n\n#HOW MANY VERIFICATIONS ARE REQUIRED TO DETERMINE A DEVICE IS AWAY \nverification_of_away_loop_size=6\n\n#HOW LONG TO DELAY BETWEEN VERIFICATIONS THAT A DEVICE IS AWAY \nverification_of_away_loop_delay=3\n\n#PREFERRED HCI DEVICE\nhci_device='hci0'\" > \"$base_directory/behavior_preferences\"\nfi \n\n# ----------------------------------------------------------------------------------------\n# VARIABLE DEFINITIONS \n# ----------------------------------------------------------------------------------------\n\n#SET PREFERENCES FROM FILE\nDELAY_CONFIG=\"$base_directory/behavior_preferences\" ; [ -f $DELAY_CONFIG ] && source $DELAY_CONFIG\n\n#LOAD DEFAULT VALUES IF NOT PRESENT\n[ -z \"$hci_device\" ] && hci_device='hci0' \n[ -z \"$name_scan_timeout\" ] && name_scan_timeout=5\n[ -z \"$delay_between_owner_scans_away\" ] && delay_between_owner_scans_away=6 \n[ -z \"$delay_between_owner_scans_present\" ] && delay_between_owner_scans_present=30\n[ -z \"$verification_of_away_loop_size\" ] && verification_of_away_loop_size=6\n[ -z \"$verification_of_away_loop_delay\" ] && verification_of_away_loop_delay=3\n\n#LOAD PREFERENCES IF PRESENT\nMQTT_CONFIG=$base_directory/mqtt_preferences ; [ -f $MQTT_CONFIG ] && source $MQTT_CONFIG\n[ ! -f \"$MQTT_CONFIG\" ] && echo \"warning: please configure mqtt preferences file. exiting.\" && echo \"\" > \"$MQTT_CONFIG\" && exit 1\n\n#FILL ADDRESS ARRAY WITH SUPPORT FOR COMMENTS\n[ ! -f \"$base_directory/owner_devices\" ] && \"\" > \"$base_directory/owner_devices\"\nmacaddress_owners=($(cat \"$base_directory/owner_devices\" | grep -oiE \"([0-9a-f]{2}:){5}[0-9a-f]{2}\" ))\n[ -z \"$macaddress_owners\" ] && echo \"warning: no owner devices are specified. exiting.\" && exit 1\n\n\n#NUMBER OF CLIENTS THAT ARE MONITORED\nnumber_of_owners=$((${#macaddress_owners[@]}))\n\n# ----------------------------------------------------------------------------------------\n# HELP TEXT\n# ----------------------------------------------------------------------------------------\n\nshow_help_text() {\n\techo \"Usage:\"\n\techo \"  presence -h \tshow usage information\"\n\techo \"  presence -d \tprint debug messages and mqtt messages\"\n\techo \"  presence -b \tbinary output only; either 100 or 0 confidence\"\n\techo \"  presence -c \tonly post confidence status changes for owners/guests\"\n\techo \"  presence -V\t\tprint version\"\n}\n\n# ----------------------------------------------------------------------------------------\n# PROCESS OPTIONS (technique: https://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash)\n# ----------------------------------------------------------------------------------------\n\nOPTIND=1\n\n# INITIALIZE OUR OWN VARIABLES:\ndebug=0\nbinary_only=0\nchanges_only=0\n\nwhile getopts \"h?Vdbct:\" opt; do\n    case \"$opt\" in\n    h|\\?)\n        show_help_text\n        exit 0\n        ;;\n    V)  \n\t\techo \"$VERSION\"\n\t\texit 0\n\t\t;;\n    d)  debug=1\n\t\t;;\n    b)  binary_only=1\n\t\t;;\n\tc)  changes_only=1\n\t\t;;\n\t*)\techo \"warning: unknown or depreciated option: $opt\"\n    esac\ndone\n\n#RESET OPTION INDEX\nshift $((OPTIND-1))\n\n#SHIFT IF NECESSARY\n[ \"$1\" = \"--\" ] && shift\n\n# ----------------------------------------------------------------------------------------\n# DEBUG FUNCTION\n# ----------------------------------------------------------------------------------------\n\ndebug_echo () {\n\tif [ \"$debug\" == \"1\" ]; then \n\t\t(>&2 echo -e \"${ORANGE}DEBUG MSG:\t$1${NC}\")\n\tfi \n}\n\n# ----------------------------------------------------------------------------------------\n# SCAN \n# ----------------------------------------------------------------------------------------\n\nscan () {\n\tif [ ! -z \"$1\" ]; then \n\t\tlocal result=$(hcitool -i $hci_device name \"$1\" 2>&1 | grep -v 'not available' | grep -vE \"hcitool|timeout|invalid|error\" )\n\t\tdebug_echo \"Scan result: [$result]\"\n\t\techo \"$result\" \n\tfi\n}\n\n# ----------------------------------------------------------------------------------------\n# PUBLISH MESSAGE\n# ----------------------------------------------------------------------------------------\n\npublish () {\n\tif [ ! -z \"$1\" ]; then \n\n\t\t#SET NAME FOR 'UNKONWN'\n\t\tlocal name=\"$3\"\n\n\t\t#IF NO NAME, RETURN \"UNKNOWN\"\n\t\tif [ -z \"$3\" ]; then \n\t\t\tname=\"Unknown\"\n\t\tfi \n\n\t\t#TIMESTAMP\n\t\tstamp=$(date \"+%a %b %d %Y %H:%M:%S GMT%z (%Z)\")\n\n\t\t#DEBUGGING \n\t\t[ \"$debug\" == \"1\" ] && (>&2 echo -e \"${PURPLE}$mqtt_topicpath$1 { confidence : $2, name : $name, scan_duration_ms: $4, timestamp : $stamp} ${NC}\")\n\n\t\t#POST TO MQTT\n\t\t$mosquitto_pub_path -h \"$mqtt_address\" -p \"${mqtt_port:=1883}\" -u \"$mqtt_user\" -P \"$mqtt_password\" -t \"$mqtt_topicpath$1\" -m \"{\\\"confidence\\\":\\\"$2\\\",\\\"name\\\":\\\"$name\\\",\\\"scan_duration_ms\\\":\\\"$4\\\",\\\"timestamp\\\":\\\"$stamp\\\"}\"\n\tfi\n}\n\n# ----------------------------------------------------------------------------------------\n# MAIN LOOP\n# ----------------------------------------------------------------------------------------\n\ndevice_statuses=()\t\t\t#STORES STATUS FOR EACH BLUETOOTH DEVICES\ndevice_names=()\t\t\t\t#STORES DEVICE NAMES FOR BOTH BEACONS AND BLUETOOTH DEVICES\none_owner_home=0 \t\t\t#FLAG FOR AT LEAST ONE OWNER BEING HOME\n\n# ----------------------------------------------------------------------------------------\n# START THE OPERATIONAL LOOP\n# ----------------------------------------------------------------------------------------\n\n#MAIN LOOP\nwhile true; do \n\n\t#RESET AT LEAST ONE DEVICE HOME\n\tone_owner_home=0\n\n\t#--------------------------------------\n\t#\tUPDATE STATUS OF ALL USERS WITH NAME QUERY\n\t#--------------------------------------\n\tfor ((index=0; index<${#macaddress_owners[*]}; index++));\n\tdo\n\t\t#CLEAR PER-LOOP VARIABLES\n\t\tname_scan_result=\"\"\n\t\tname_scan_result_verify=\"\"\n\t\tok_to_publish=1\n\n\t\t#OBTAIN INDIVIDUAL ADDRESS\n\t\tcurrent_device_address=\"${macaddress_owners[$index]}\"\n\n\t\t#CHECK FOR ADDITIONAL BLANK LINES IN ADDRESS FILE\n\t\tif [ -z \"$current_device_address\" ]; then \n\t\t\tcontinue\n\t\tfi\n\n\t\t#MARK BEGINNING OF SCAN OPERATION\n\t\tstart_timer=$(date +%s%N)\n\n\t\t#OBTAIN RESULTS AND APPEND EACH TO THE SAME\n\t\tname_scan_result=$(scan $current_device_address)\n\t\t\n\t\t#MARK END OF SCAN OPERATION\n\t\tend_time=$(date +%s%N)\n\t\t\n\t\t#CALCULATE DIFFERENCE\n\t\tduration_timer=$(( (end_time - start_timer) / 1000000 )) \n\n\t\t#THIS DEVICE NAME IS PRESENT\n\t\tif [ \"$name_scan_result\" != \"\" ]; then\n\n\t\t\t#STATE IS SAME && ONLY REPORT CHANGES THEN DISABLE PUBLICATION\n\t\t\t[ \"${device_statuses[$index]}\" == '100' ] && [ \"$changes_only\" == 1 ] && ok_to_publish=0\n\n\t\t\t#NO DUPLICATE MESSAGES\n\t\t\t[ \"$ok_to_publish\" == \"1\" ] && publish \"/$mqtt_room/$current_device_address\" '100' \"$name_scan_result\" \"$duration_timer\"\n\n\t\t\t#USER STATUS\t\t\t\n\t\t\tdevice_statuses[$index]=\"100\"\n\n\t\t\t#SET AT LEAST ONE DEVICE HOME\n\t\t\tone_owner_home=1\n\n\t\t\t#SET NAME ARRAY\n\t\t\tdevice_names[$index]=\"$name_scan_result\"\n\n\t\telse\n\n\t\t\t#USER STATUS\t\t\t\n\t\t\tstatus=\"${device_statuses[$index]}\"\n\n\t\t\tif [ -z \"$status\" ]; then \n\t\t\t\tstatus=\"0\"\n\t\t\tfi \n\n\t\t\t#BY DEFAULT, SET REPETITION TO PREFERENCE\n\t\t\trepetitions=\"$verification_of_away_loop_size\"\n\n\t\t\t#IF WE ARE JUST STARTING OR, ALTERNATIVELY, WE HAVE RECORDED THE STATUS \n\t\t\t#OF NOT HOME ALREADY, ONLY SCAN ONE MORE TIME. \n\t\t\tif [ \"$status\" == 0 ];then \n\t\t\t\trepetitions=1\n\t\t\tfi \n\n\t\t\t#SHOULD VERIFY ABSENSE\n\t\t\tfor repetition in $(seq 1 $repetitions); \n\t\t\tdo \n\t\t\t\t#RESET OK TO PUBLISH\n\t\t\t\tok_to_publish=1\n\n\t\t\t\t#VERIFICATION LOOP DELAY\n\t\t\t\tsleep \"$verification_of_away_loop_delay\"\n\n\t\t\t\t#GET PERCENTAGE\n\t\t\t\tpercentage=$(($status * ( $repetitions - $repetition) / $repetitions))\n\n\t\t\t\t#ONLY SCAN IF OUR STATUS IS NOT ALREADY 0\n\t\t\t\tif [ \"$status\" != 0 ];then \n\n\t\t\t\t\t#MARK BEGINNING OF SCAN OPERATION\n\t\t\t\t\tstart_timer=$(date +%s%N)\n\n\t\t\t\t\t#PERFORM SCAN\n\t\t\t\t\tname_scan_result_verify=$(scan $current_device_address)\n\n\t\t\t\t\t#MARK END OF SCAN OPERATION\n\t\t\t\t\tend_time=$(date +%s%N)\n\t\t\t\t\t\n\t\t\t\t\t#CALCULATE DIFFERENCE\n\t\t\t\t\tduration_timer=$(( (end_time - start_timer) / 1000000 )) \n\n\t\t\t\t\t#CHECK SCAN \n\t\t\t\t\tif [ \"$name_scan_result_verify\" != \"\" ]; then\t\t\t\t\t\t\n\n\t\t\t\t\t\t#STATE IS SAME && ONLY REPORT CHANGES THEN DISABLE PUBLICATION\n\t\t\t\t\t\t[ \"${device_statuses[$index]}\" == '100' ] && [ \"$changes_only\" == 1 ] && ok_to_publish=0\n\n\t\t\t\t\t\t#PUBLISH\n\t\t\t\t\t\t[ \"$ok_to_publish\" == \"1\" ] && publish \"/$mqtt_room/$current_device_address\" '100' \"$name_scan_result_verify\" \"$duration_timer\"\n\n\t\t\t\t\t\t#SET AT LEAST ONE DEVICE HOME\n\t\t\t\t\t\tone_owner_home=1\n\n\t\t\t\t\t\t#WE KNOW THAT WE MUST HAVE BEEN AT A PREVIOUSLY-SEEN USER STATUS\n\t\t\t\t\t\tdevice_statuses[$index]=\"100\"\n\n\t\t\t\t\t\t#UPDATE NAME ARRAY\n\t\t\t\t\t\tdevice_names[$index]=\"$name_scan_result_verify\"\n\n\t\t\t\t\t\t#MUST BREAK CONFIDENCE SCANNING LOOP; 100' ISCOVERED\n\t\t\t\t\t\tbreak\n\t\t\t\t\tfi\n\t\t\t\tfi \n\n\t\t\t\t#RETREIVE LAST-KNOWN NAME FOR PUBLICATION; SINCE WE OBVIOUSLY DIDN'T RECEIVE A NAME SCAN RESULT \n\t\t\t\texpectedName=\"${device_names[$index]}\"\n\n\t\t\t\tif [ \"$percentage\" == \"0\" ]; then \n\t\t\t\t\t#STATE IS SAME && ONLY REPORT CHANGES THEN DISABLE PUBLICATION\n\t\t\t\t\t[ \"${device_statuses[$index]}\" == '0' ] && [ \"$changes_only\" == 1 ] && ok_to_publish=0\n\n\t\t\t\t\t#PRINT ZERO CONFIDENCE OF A DEVICE AT HOME\n\t\t\t\t\t[ \"$ok_to_publish\" == \"1\" ] && publish \"/$mqtt_room/$current_device_address\" \"0\" \"$expectedName\" \"$duration_timer\"\n\t\t\t\telse \n\t\t\t\t\t#STATE IS SAME && ONLY REPORT CHANGES THEN DISABLE PUBLICATION\n\t\t\t\t\t[ \"${device_statuses[$index]}\" == '$percentage' ] && [ \"$changes_only\" == 1 ] && ok_to_publish=0\n\n\t\t\t\t\t#IF BINARY ONLY, THEN DISABLE PUBLICATION\n\t\t\t\t\t[ \"$binary_only\" == \"1\" ] && ok_to_publish=0\n\n\t\t\t\t\t#REPORT CONFIDENCE DROP\n\t\t\t\t\t[ \"$ok_to_publish\" == \"1\" ] && publish \"/$mqtt_room/$current_device_address\" \"$percentage\" \"$expectedName\" \"$duration_timer\"\n\t\t\t\tfi \n\n\t\t\t\t#UPDATE STATUS ARRAY\n\t\t\t\tdevice_statuses[$index]=\"$percentage\" \n\t\t\tdone\n\t\tfi\n\tdone\n\n\t#CHECK STATUS ARRAY FOR ANY DEVICE MARKED AS 'HOME'\n\twait_duration=0\n\n\t#DETERMINE APPROPRIATE DELAY\n\tif [ \"$one_owner_home\" == 1 ]; then \n\t\t wait_duration=$delay_between_owner_scans_present\n\telse\n\t\twait_duration=$delay_between_owner_scans_away\n\tfi\n\n\tsleep \"$wait_duration\"\ndone\n"
  }
]