Monitoring Wireless Sensors
In this post we’ll cover how to monitor inexpensive wireless security sensors. There are two types of wireless sensors that we’ll be working with, door reed switches and passive infra red motion detectors. Each of these sensors transmit a broadcast radio message on the 433Mhz frequency. We’ll be expanding on earlier work with RTL_433. This post will cover how to identify a specific sensor and take appropriate action as needed, all that with a single bash script, let’s begin.
The first thing will be the command to run the RTL_433 command. The path to the command is included in the bash script. CRON might be able to know the path, but it’s better to include it just in case. If the path isn’t known, type “whereis
/usr/local/bin/rtl_433 -R 86 -F json:"$JsonOutput" -E
Since the above command is saving its output to a variable, we will define all of the variables at the beginning of the script.
DoorSensorEmail="/home/local/Tasks/DoorSensorEmail.txt" JsonOutput="/home/local/Tasks/A_JsonOutput.txt" Message="/home/local/Tasks/A_Message.txt" MessageOutside="/home/local/Tasks/A_MessageOutside.txt" PIRCounter="/home/local/Tasks/BasementPIRCounter.txt" Counter=$(cat "$PIRCounter") CactiHost='cacti.host.local' Mate1FTPUser='' Mate1FTPPass=''
This script will be called from CRON on bootup. I like to add a 2 minute delay before staring the rest of the script. This is done with this command.
sleep 120
After this period of time, the variables will be loaded into memory and our main loop function will begin by starting RTL_433. It will continue running RTL_433 until one of a sensor transmits. When data is decoded by RTL_433, that process will end and we will enter into a series of if else conditions.
The first condition will check if the JSON output contains the identifier for a door sensor. If it doesn’t, it will continue on with the next check of another identifier and so on. However, if the JSON output does contain the identifier then a series of commands will execute.
# Door Sensor ID = ##### if grep -q ##### "$JsonOutput" ; then echo "Door Sensor Tripped" > $Message # Process paths need to be included for CRON, use whereis "command" to find path. cat "$JsonOutput" | /usr/bin/logger -n syslog.host.local rm "$JsonOutput" # Process paths need to be included for CRON, use whereis "command" to find path. /usr/sbin/ssmtp admin@email.local < "$DoorSensorEmail" >/dev/null 2>&1
The above if condition will log the results to a syslog server named “syslog.host.local”. It then removes the JSON file for housekeeping. Finally, it sends an email notifying admin@email.local with a pre-formatted email message. Certain sensors merit immediate attention, while others can simply be logged to the syslog server.
In the next if condition, we’ll log the JSON result to our syslog server. In addition to that, we’ll also tally a counter of the occurrence of the event. This value will then be uploaded to a FTP host that runs Cacti. I won’t cover the configuration of Cacti here, see earlier posts for that. If you have a number, Cacti will graph it.
# PIR Sensor ID = ##### elif grep -q ##### "$JsonOutput" ; then echo "PIR Tripped" > $Message # Process paths need to be included for CRON, use whereis "command" to find path. cat "$JsonOutput" | /usr/bin/logger -n syslog.host.local Counter=$((Counter+1)) echo "$Counter" > "$PIRCounter" echo " verbose open $CactiHost user $Mate1FTPUser $Mate1FTPPass cd Tasks bin put "$PIRCounter" bye " | ftp -n rm "$JsonOutput"
The last condition we’ll check is a catch all. If none of our devices were found in earlier conditions, then some unknown device transmitted data. This condition will take action based on that. Since I covered email, syslog, and cacti, we could use any or all of these in this catch all condition. At the conclusion of this, we return to the start of our loop and run the RTL_433 command again.
Using a single bash script and some inexpensive hardware, we can monitor security sensors and take action based on their activity. Here is the complete code for the script, names have been changed to protect the innocent.
#!/bin/sh # /home/local/Tasks/DoorSensor.sh # Version 6.0 (12312018) # Purpose - Run SDR scan of Door and PIR Sensors, log readings to Syslog / Cacti, and send email alert # Author - Patrick Gilfeather - CloudACM # Delay the start of the script for 2 minutes so system has time to boot sleep 120 # Set variables for work files DoorSensorEmail="/home/local/Tasks/DoorSensorEmail.txt" JsonOutput="/home/local/Tasks/A_JsonOutput.txt" Message="/home/local/Tasks/A_Message.txt" MessageOutside="/home/local/Tasks/A_MessageOutside.txt" PIRCounter="/home/local/Tasks/BasementPIRCounter.txt" Counter=$(cat "$PIRCounter") CactiHost='**********' Mate1FTPUser='**********' Mate1FTPPass='**********' # Run the process in a loop endlessly while : do # Run RTL_433 process to detect door sensor with SDR and capture results to a JSON formatted file. # Process paths need to be included for CRON, use whereis "command" to find path. /usr/local/bin/rtl_433 -R 86 -F json:"$JsonOutput" -E # Door Sensor ID = ********** if grep -q ********** "$JsonOutput" ; then echo "********** Sensor Tripped" > $Message # Process paths need to be included for CRON, use whereis "command" to find path. cat "$JsonOutput" | /usr/bin/logger -n ********** rm "$JsonOutput" # Process paths need to be included for CRON, use whereis "command" to find path. /usr/sbin/ssmtp ********** < "$DoorSensorEmail" >/dev/null 2>&1 # Door Sensor ID = ********** elif grep -q ********** "$JsonOutput" ; then echo "********** Sensor Tripped" > $Message # Process paths need to be included for CRON, use whereis "command" to find path. cat "$JsonOutput" | /usr/bin/logger -n ********** rm "$JsonOutput" # PIR Sensor ID = ********** elif grep -q ********** "$JsonOutput" ; then echo "********** Sensor Tripped" > $Message # Process paths need to be included for CRON, use whereis "command" to find path. cat "$JsonOutput" | /usr/bin/logger -n ********** Counter=$((Counter+1)) echo "$Counter" > "$PIRCounter" echo " verbose open $CactiHost user $Mate1FTPUser $Mate1FTPPass cd Tasks bin put "$PIRCounter" bye " | ftp -n rm "$JsonOutput" # Undefined Sensor else echo "Foreign Sensor Tripped" >> $MessageOutside rm "$JsonOutput" fi done exit