Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save coreymartella/303151 to your computer and use it in GitHub Desktop.
Save coreymartella/303151 to your computer and use it in GitHub Desktop.
DoorMonitor - Doggy Motion Capture
require 'rubygems'
require 'directory_watcher'
require 'fileutils'
require 'growl'
# require 'ruby_gntp'
SOURCE = "http://172.16.187.5/img/mjpeg.cgi" #URL source of your video stream
#SOURCE = "http://172.16.187.5/img/video.asf" #URL source of your video stream
INTERVAL = 2 #seconds between frame grabs
FUZZ = 10 #fuzz for dealing with lossy jpgs
MIN_DELTA = 5 #delta required to cause a notification to occur
MESSAGE = "The Dogs want out!" #message to show
class DoorMonitor
attr_accessor :frame_size, :last_frame, :current_frame, :ffmpeg_pid, :ffmpeg_process, :frames_changed, :last_notification, :delta
def compare_frames
self.frame_size ||= eval(`identify #{current_frame}`.split(" ")[2].gsub("x","*"))
difference = `compare -metric AE -fuzz #{FUZZ}% #{last_frame} #{current_frame} null 2>&1`.to_i
self.delta = (100.00*difference/frame_size).to_i
print("\r#{Time.now.strftime '%b %e %l:%M:%S%P'} %3d%" % delta);STDOUT.flush
notify if delta >= MIN_DELTA #|| File.basename(current_frame, ".jpg").to_i % 4 == 1
end
def run
#start with a clean dir
FileUtils.rm_rf "frames"
FileUtils.mkdir_p "frames"
self.last_notification = Time.now - 360
dw = DirectoryWatcher.new 'frames/', :glob => '*.jpg', :interval => INTERVAL
dw.add_observer do |*args|
args.each do |event|
if event.type.to_s == 'added' && event.path !~ /notify/
#nuke the old frame
FileUtils.rm_f self.last_frame if self.last_frame && ENV['CLEANUP'] != 'off'
self.last_frame = self.current_frame
self.current_frame = event.path
end
end
#compare frames if we have two of them and we have new frames according to DirWatcher
compare_frames if self.last_frame
end
dw.start
#start ffmpeg
self.ffmpeg_process = IO.popen("ffmpeg -i #{SOURCE} -y -ss #{INTERVAL} -an -sameq -f image2 -r 1/#{INTERVAL} frames/%07d.jpg </dev/null 2>&1")
self.ffmpeg_pid = self.ffmpeg_process.pid
puts "ffmpeg pid: #{ffmpeg_pid}"
# when the user hits "q" the script will terminate
while gets.strip != 'q'
end
dw.stop
end
protected
def notify
#don't go nuts on the notification
return unless (Time.now - self.last_notification) > 1.minute
self.last_notification = Time.now
#make a copy of the frame for safe keeping
notify_frame = "frames/notify-#{Time.now.strftime "%Y%m%d%H%M%S"}.jpg"
FileUtils.cp current_frame, notify_frame
Growl.notify do |n|
n.message = MESSAGE
n.image = File.expand_path(notify_frame)
n.name = "door_monitor"
n.title = "Door Monitor"
n.sticky!
end
end
end
door_monitor = DoorMonitor.new
door_monitor.run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment