rfid / attendance

# Generate a CSV of who has attended an event and what time they scanned in.
# Reads IDs from the serial port and looks them up in the CSV database
use warnings;
use strict;
use IO::Handle;

my $dev_file = '/dev/tty.usbmodem12341';
my $csv_in_file = 'users.csv';
my $csv_out_file = 'output.csv';

open CSV, "<$csv_in_file"
	or die "$csv_in_file: Unable to open: $!\n";
my %users;

while (<CSV>)
	next if $. == 1;
	my ($last,$first,$id) = split /\s*,\s*/;

	die "$id: Duplicate?\n" if exists $users{$id};
	$users{$id} = [ $last, $first ];

open DEV, "<$dev_file"
	or die "$dev_file: Unable to open: $!\n";

my $count = 0;
my $out;

if (-r $csv_out_file)
	# File exists; find out how many are already there and add to it
	open IN, "<$csv_out_file"
		or die "$csv_out_file: Unable to read\n";

	$count++ while <IN>;
	$count--; # skip header

	# Start appending to the file now
	close IN;
	open $out, ">>$csv_out_file"
		or die "$csv_out_file: Unable to append: $!\n";
} else {
	open $out, ">$csv_out_file"
		or die "$csv_out_file: Unable to write: $!\n";
	print $out "last,first,id,time\n";

# Force writes to the CSV immediately

while (<DEV>)

	unless (/^[01]+$/)
		warn "Invalid ID? '$_'\n";

	# Try for a 16 bit ID
	my $id = $_;
	my $id16 = 0;
	for my $bit (split //, substr($id, -17, 16))
		$id16 = ($id16 << 1) | $bit;

	my $user = $users{$id16};

	unless ($user)
		warn "$id16 ($_): Not in database?\n";

	printf "%d: %s\n", $count, $user->[1];

	my $now = localtime;
	print $out "$user->[0],$user->[1],$id,$now\n";