Cat-a-log: cat tracking with RFID

My wife was always worried when she had not seen all of our cats daily, and sometimes stayed up late to see them all in the house.

All of our cats have a RFID chip implanted to identify them, so the idea was to build a RFID reader in the catflap. The data is collected in a database and made available on the Internet. This was already foreseen when we built the house, so there is a CAT5 cable from the front door to a patch panel.

Hardware

At first I tried the thesis from Leonid Kuritsin, but with an EM4095 in stead of the U2270, but I could not get reliable readings. After that I decided for the RFIDLOG from Priority 1 Design which has all the required functions and is not too expensive.

The antenna around the cat flap. Copper colored coil of fine wire on the inside of a brown cat flap
The reader near the cat flap. The 50 by 50 millimeter red box to the left of the catflap

Data collection

The MySQL database schema consists of 2 tables; "entry" with the chip-id and the date-time and "name" with chip-id and the name of the cat.

The data is gathered with a small Perl program, to be run as a deamon:

#!/usr/bin/perl
use strict;
use warnings;
use Device::SerialPort;
use DBI;
# callback signal handler for signals.
$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&signalHandler;
$SIG{PIPE} = 'ignore';
my $running = 1;
my $con = DBI->connect("dbi:mysql:dbname=cats","username","password",{RaiseError => 1},) or die "Connect DBI::errstr";
my $port = new Device::SerialPort("/dev/ttyUSB0");
print "open err " unless ($port);
$port->baudrate(9600); 
$port->parity("none");
$port->databits(8);
$port->stopbits(1);
$port->handshake("none");
$port->write_settings;
$port->are_match("\r", "\n");
$port->lookclear;

my $resp='';
while ($running)
{
  until ( $resp ne '')
  {
    $resp=$port->lookfor;
    sleep 1;
  }
   if (length($resp) >= 15) 
  { #the following lines remove some of the glitches
    if ((index ("0123456789",substr($resp,0,1)) < 0) && (length($resp) >= 16))
    {
 	$resp = substr($resp,1);
        if ((index ("0123456789",substr($resp,0,1)) < 0) && (length($resp) >= 16))
        {
 	    $resp = substr($resp,1);
        }		
    }
    my $sth = $con->prepare("INSERT INTO entry (zeit,chip) VALUES (now(),\"" . $resp . "\")") or warn "Prepare DBI::errstr";
    # print $resp . "\n";
    my $rc = $sth->execute() or warn "Excecute DBI::errstr";
  }
  $resp = '';
  $port->lookclear;
}
warn "cat-a-log server terminating";
$con->close();
$port->close;

# catch signals and end the program if one is caught.
sub signalHandler 
{
   $running = 0;    # this will cause the "infinite loop" to exit
}

Data presentation

The data is presentend as a table of the 4 most recent events per cat using a simple PHP program.

<table border="2" cellspacing="1" cellpadding="13">
<?php
$mysqli = new mysqli('localhost','username','password','cats') or die('No connection to DB');
$i=1;
$names = $mysqli->query('SELECT * FROM name') or die(' select name');
if ($names->num_rows > 0) {
  while ($namerow = $names->fetch_assoc() ) {
  echo "<tr>";
    $name = $namerow["name"];
    echo '<td> ' . $name . ' </td>';
    $sel = 'SELECT zeit FROM entry WHERE chip=' . '\'' . $namerow["chip"] . '\'' . ' ORDER BY zeit DESC LIMIT 4';
    $times = $mysqli->query($sel) or die('Error select entry'); 
    if ($times->num_rows > 0) {
      while ($timerow = $times->fetch_assoc() ) {
        $time = date_create($timerow["zeit"]);
        echo '<td>' . date_format($time, 'm-d H:i') . "</td>";
      }
    }
    else
    {
       echo "<td>No Time</td>";
    } 
    echo "</tr>";   
    }
}
else 
{
  die('No names'); 
}
$mysqli->close();
?>
</table>

The output