2012-07-18 RFID controller webcam control

My wife and I don't have kids, we have 4 cats.
At every place they (the cats) usually hang out (sleep, eat, play) I installed a webcam. Using these webcams (9 cameras, also one in the garden to film burglars) we then can see from work, over the internet.
Of course, they're also active when we're at home and my wife was not very comfortable with that. They are password protected, but it just did not feel right.
I solved that problem.

I had an old asus eee pc 901 with a broken keyboard just lying around. I then bought a simple RFID reader and a Ampel (from Cleware, they have all kinds of nice USB connected lights, switches, digital I/O, etc.).
The reader is rather simple: it retrieves the serial number of an RFID card and "types" it as like a keyboard would. It does not read any data of the card (which is protected), it only uses the serial number of the card which is returned by the card during the handshake - I myself use an uninitialized (blank) Mifare 1K card for this.
So if I connect a program of my own to tty1 (the virtual console that opens when a system boots up first), I can catch what was "typed" by the RFID reader. This can be accomplished by replacing the following line from /etc/inittab:
1:2345:respawn:/sbin/getty 38400 tty1
with my own:
1:2345:respawn:/rfid.pl
Then it is just a matter of creating a simple perl-script that catches the serial number returned by the RFID-reader, looks it up in a database and if the card is known it tells the webserver to either show or not show the webcams. Using my clewarecontrol I then switch on either the red lights or green lights on the Ampel (and yellow if the card is not known).
Switching on and off the webserver is a matter of copying one of two configuration-files into the appropriate directory and invoking "apache2ctl graceful". This is done by invoking a script on the webserver using a public key authenticated ssh session. My USB webcams (which I monitor using Grabby) are also stopped by remotely terminating the Grabby process.
The RFID card can be any card that always returns the same ID: Dutch travel-card, access/id cards, anything. The Dutch passport won't work: it does have an RFID chip, but everytime you try to read the ID, it returns something new.
The result works really well, and my wife has agreed to use it! :-)




The scripts used:
/rfid.pl, this is invoked from inittab as a replacement of /sbin/getty:
#! /usr/bin/perl -w

use DBI;

$db_type = 'mysql';
$db_host = '172.29.0.1';
$db_name = 'rfid';
$db_user = 'rfid';
$db_pass = 'rfid';

$dbh = DBI->connect("dbi:$db_type:database=$db_name:host=$db_host", $db_user, $db_pass,
{ RaiseError => 0, AutoCommit => 1 }) or die 'cannot connect to server ' . $DBI::errstr;
$query = "SELECT status FROM flags WHERE type='webcams'";
$sth = $dbh -> prepare($query);
$sth -> execute;
@ar1 = $sth->fetchrow_array;
system('/toggle_lights.sh '.$ar1[0]);

sub trim($)
{
	my $string = shift;
	$string =~ s/^\s+//;
	$string =~ s/\s+$//;
	return $string;
}

while(<>
{
	$in = $_;

	if (substr($in, -1) eq "\n")
	{
		chomp $in;
	}

	print '|'.$in."|\n";

	$in = trim($in);
	$id = $in;

	# connect to data input table
	$dbh = DBI->connect("dbi:$db_type:database=$db_name:host=$db_host", $db_user, $db_pass,
{ RaiseError => 0, AutoCommit => 1 }) or die 'cannot connect to server ' . $DBI::errstr;

	$query = "INSERT INTO history(id, ts) VALUES(?, NOW())";
	$sth = $dbh -> prepare($query);
	$sth -> execute($id);

	if ($in eq 'shell')
	{
		system('/bin/bash');
	}
	elsif ($in eq 'quit')
	{
		last;
	}
	else
	{
		$query = "SELECT flags, comment FROM cards WHERE id=? LIMIT 1";
		$sth = $dbh -> prepare($query);
		$sth -> execute($id);

		if (my @ary = $sth->fetchrow_array)
		{
			$query = "SELECT status, exec FROM flags WHERE type='webcams'";
			$sth2 = $dbh -> prepare($query);
			$sth2 -> execute;
			my @ar2 = $sth2->fetchrow_array;
			$sth2 -> finish;
			$status = $ar2[0];

			if ($status eq 'on')
			{ $new_status = 'off'; }
			else
			{ $new_status = 'on'; }
			$cmd = $ar2[1].' '.$new_status.' '.$id;

			$query = 'INSERT INTO history_actions(id, action, ts) VALUES(?, ?, NOW())';
			$sth4 = $dbh -> prepare($query);
			$sth4 -> execute($id, $cmd);
			$sth4 -> finish;

			system($cmd);

			$query = "UPDATE flags SET status=? WHERE type='webcams'";
			$sth3 = $dbh -> prepare($query);
			$sth3 -> execute($new_status);
			$sth3 -> finish;
		}
		else
		{
			system('/toggle_lights.sh unk_on');
			sleep 1;
			system('/toggle_lights.sh unk_off');
		}

		$sth -> finish;
	}

	$dbh -> disconnect or die 'MySQL disconnect failed';
}

/toggle_webcams_lights.sh, this is invoked from /rfid.pl:
#! /bin/bash

STAT=$1

echo status to $STAT | mail -s "rfid card $2 detected" folkert.mobiel@gmail.com

if [ $STAT == 'on' ]
then
	/usr/bin/ssh 172.29.0.10 '/etc/rc.webcams start'
	/usr/bin/ssh 172.29.0.1 \
'/bin/cp /root/rfid/keetweej.vanheusden.com.on /etc/apache2/sites-enabled/keetweej.vanheusden.com ; /usr/sbin/apache2ctl graceful'
	/toggle_lights.sh on
fi

if [ $STAT == 'off' ]
then
	/usr/bin/ssh 172.29.0.10 "/etc/rc.webcams stop"
	/usr/bin/ssh 172.29.0.1 \
'/bin/cp /root/rfid/keetweej.vanheusden.com.off /etc/apache2/sites-enabled/keetweej.vanheusden.com ; /usr/sbin/apache2ctl graceful'
	/toggle_lights.sh off
fi

exit 0

/toggle_lights.sh, this is invoked from /toggle_webcams_lights.pl:
#! /bin/bash

STAT=$1

if [ $STAT == 'on' ]
then
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 0 1 # red on
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 2 0 # green off
fi

if [ $STAT == 'off' ]
then
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 0 0 # red off
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 2 1 # green on
fi

if [ $STAT == 'unk_on' ]
then
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 1 1 # yellow on
fi

if [ $STAT == 'unk_off' ]
then
	/usr/bin/clewarecontrol -d 9177 -c 1 -as 1 0 # yellow off
fi

exit 0

database scheme:
CREATE TABLE `cards` (
  `id` varchar(255) NOT NULL DEFAULT '',
  `flags` varchar(255) NOT NULL,
  `comment` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
);

CREATE TABLE `flags` (
  `type` varchar(255) NOT NULL DEFAULT '',
  `status` varchar(255) NOT NULL,
  `exec` varchar(255) NOT NULL,
  PRIMARY KEY (`type`)
);
INSERT INTO `flags` VALUES ('webcams','off','/toggle_webcams_lights.sh');

CREATE TABLE `history` (
  `id` varchar(255) NOT NULL DEFAULT '',
  `ts` datetime NOT NULL
);

CREATE TABLE `history_actions` (
  `id` varchar(255) NOT NULL,
  `action` text NOT NULL,
  `ts` datetime NOT NULL
);






Check out my united states Mega Millions lottery winning help page