Sump Pump Monitor

From NAS-Central Buffalo - The Linkstation Wiki
Jump to: navigation, search


My setup

Background

Graph of weeks sump pump output
Seagate Dockstar
X Box Microphone

I felt the need to monitor my sump pump after my basement flooded. At first I thought I would use a split core current sensor to monitor my pump with an arduino and an ethernet shield. While I was waiting for these parts to arrive from China I thought: "what parts do I have lying around that I can use to make something in the mean time" A few minutes of rummaging through my box of goodies produced: a Seagate Dockstar, a 2 GB USB thumbdrive and a USB microphone for an Xbox.

That was enough to whip this up in a half a day, not super elegant, and it does sometimes get distracted by ambient noise, but not too shabby for junk I had lying around.

Admittedly this is just a collection of shell scripts, with very poor form.

The meat of the scripting is done by an simple but excellent script I found by Thomer M. Gill written in ruby that I modified just a bit and his tutorial on sound detection using sox. [1]

I just ran some CAT5 down to the dockstar and strapped the microphone near the check valve on the exit pipe. Every time the pump goes off the noise of the check valve triggers an event.

This ramshackle collection of scripts, with cron will:

  • Tweet the total events every day
  • Tweet if there are no events in the last hour
  • Tweet if there are above a threshold number of events in the last hour
  • Email me a graph of the events for the last week every day in the morning

What you need

Any device with network access and a USB port that is capable of running Debian linux will do. I happen to be using a dockstar with Debian installed [2] but you could use a properly debianized linkstation or kurobox instead.


You will Need:

  • Debian based device with Network access and USB port
  • USB Microphone

Need to install

  • Ruby
  • ttytter
  • alsa-utils
  • sox
  • gnuplot
  • mpack

Scripts

Sound Detect

This script is essentially run as a Daemon it samples 3 second sound clips, gets the maximum sound amplitude and writes a timestamp to a file, in this case

/root/myfile.out

(yes I know that's a real bad idea)

#!/usr/bin/ruby -w
#
# Copyright (C) 2014 Uday K. Paul
#
# Aug  28, 2014: Modified for use with sump pump
#
# Derived from original version Copyright (C) 2009 Thomer M. Gil [http://thomer.com/]
#
# Oct  22, 2009: Initial version
# 
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# This program detects the presence of sound and appends a datestamp to a logfile
#

require 'getoptlong'

# You need to replace MICROPHONE with the name of your microphone, as reported
# by /proc/asound/cards
MICROPHONE = 'Logitech'
HWDEVICE = `cat /proc/asound/cards | grep '#{MICROPHONE}' | awk '{print $1}'`.to_i
SAMPLE_DURATION = 3 # seconds
FORMAT = 'S16_LE'   # this is the format that my USB microphone generates
THRESHOLD = 0.15

if !File.exists?('/usr/bin/arecord')
  warn "/usr/bin/arecord not found; install package alsa-utils"
  exit 1
end

if !File.exists?('/usr/bin/sox')
  warn "/usr/bin/sox not found; install package sox"
  exit 1
end

if !File.exists?('/proc/asound/cards')
  warn "/proc/asound/cards not found"
  exit 1
end

$options = {}
opts = GetoptLong.new(*[
  [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ],
])
opts.each { |opt, arg| $options[opt] = arg }

time1=0

loop do
  out = `/usr/bin/arecord -D plughw:#{HWDEVICE},0 -d #{SAMPLE_DURATION} -f #{FORMAT} 2>/dev/null | /usr/bin/sox -t .wav - -n stat 2>&1`
  out.match(/Maximum amplitude:\s+(.*)/m)
  amplitude = $1.to_f
  puts amplitude if $options['--verbose']  
  if amplitude > THRESHOLD
    time2=time1
    time1 = Time.new
    diff = time1-time2
    if diff.to_f > 8.0
    open('/root/myfile.out', 'a') { |f|
    f.puts time1.inspect 
    
      } 
    puts diff 
    else
    end    
else
  end
end

waterd-hourly

This writes a log file out of the events in the last hour and deletes the event file. It will tweet if there are no pump events in the last hour or if they fall above a certain threshold


#!/bin/bash
#
# Copyright (C) 2014 Uday K. Paul
#
# Aug  28, 2014: 
#
# Hourly script to Sum up pump events over the last hour and write to an hourly log file that is kept
# with the pump event file being deleted
#
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# This program detects the presence of sound and appends a datestamp to a logfile every hour,  it will tweet if there are no events in the last hour or more than the highlimit
#

highlimit=30

result=`ps aux | grep -i "sound-detect" | grep -v "grep" | wc -l`
read lines words chars filename <<< $(wc /root/myfile.out)

paste <(date +%D%t%k )  <(wc -l /root/myfile.out ) | awk '{ print $1" "$2" " $3}' >> /root/hourly.log

if [[ $lines -gt $highlimit ]]
 then
ttytter  -status="Pumped in last hour $lines"

elif [[ $lines -eq 0 ]]
 then
ttytter  -status="No Pumping in the last Hour"

else
echo "pump good"
echo $lines "pumped"
fi


 rm /root/myfile.out


if [ $result -ge 1 ]
   then
        echo "script is running"
   else
        /usr/local/bin/sound-detect &
fi

waterd-minute

This just runs every minute to make sure the daemon is running

#!/bin/bash
#
# Copyright (C) 2014 Uday K. Paul
#
# Aug  28, 2014: 
#
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
#


result=`ps aux | grep -i "sound-detect" | grep -v "grep" | wc -l`


if [ $result -ge 1 ]
   then
        echo "script is running"
   else
        /usr/local/bin/sound-detect &
fi

waterd-daily

#!/bin/bash
#
# Copyright (C) 2014 Uday K. Paul
#
# Aug  28, 2014: 
#
# Daily script to Sum up pump events over the day, tweet the total and send a graph of the last weeks events 
#
# This program is free software. You may distribute it under the terms of
# the GNU General Public License as published by the Free Software
# Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
#



times=`grep $(date --date="-1 day" +"%D%t") /root/hourly.log | awk '{total=total + $3}END{print total}'`

ttytter -status="Pumped $times times yesterday"

gnuplot /usr/local/bin/plotgraph && mpack -s Sumppump  out.pdf  EMAIL@ADDRESS && rm out.pdf

plotgraph

The gnuplot file that generates a pdf of the last weeks data from the hourly log file

#!/usr/bin/gnuplot
reset
# set terminal png size 2048,1536 linewidth 9  enhanced font ',30'
# set output "graph.png"

set terminal pdf font ',8'
set output 'out.pdf'

set xdata time
set timefmt "%m/%d/%Y %H"
set format x "%m/%d"
set xlabel "Date"

set ylabel "Cycles in Hour"

set title "Sump Pump" font ',20'

set key reverse Left outside

set style data lines 


 plot "< tail -168 /root/hourly.log" using 1:3 smooth unique title ""
#plot "/root/hourly.log" using 1:3 smooth unique title ""


/etc/crontab

The crontab that runs the above scripts on the day, hour and minute

# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user	command
17 *	* * *	root    cd / && run-parts --report /etc/cron.hourly
25 6	* * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6	* * 7	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6	1 * *	root	test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
00 *    * * *   root    /usr/local/bin/waterd-hourly >/dev/null 2>&1
*  *    * * *   root    /usr/local/bin/waterd-minute >/dev/null 2>&1
00 8    * * *   root    /usr/local/bin/waterd-daily >/dev/null 2>&1
#

References

  1. How to detect the presence of sound/audio
  2. Unlocking your Dockstar, GoFlex, or Pogoplug