#! /usr/bin/perl

use FileHandle;

$code_file = $ARGV[0];

die "usage: flicread code_file\n" unless $code_file;

$tty = "/dev/rfcomm0";

flic_init();
flic_open($tty);
flic_open_code_file($code_file);

%code_hash = ();

for (;;)
{
  ($code,$count) = flic_fetch_code();
  
  next if ($code_hash{$count} == $code);
  
  $code_hash{$count} = $code;
  flic_record_scan($code);
  print "code: $code\n";
}

flic_close();

sub flic_open_code_file
{
  open CODE, ">>$code_file" or die "Could not open code file\n";
  CODE->autoflush(1);
}

sub flic_record_scan
{
  my $code = shift;
  my $ts = flic_get_ts();
  print CODE "$ts,$code\n";
}

sub flic_get_addr
{
  # hack, grab the first line matching the pattern
  # fix it if it has side effects 
  my $line = `grep device /etc/bluetooth/rfcomm.conf`;
  my $addr;
  if ($line =~ /([0-9A-Fa-f][0-9A-Fa-f](:[0-9A-Fa-f][0-9A-Fa-f])+)/)
  {
    $addr = $1;
  } 
  
  die "Did not find Flic address" unless (defined($addr));
  return $addr;
}

sub flic_reinit
{
  flic_close();
  flic_init();
  flic_open($tty);
}

sub flic_init
{
  my $addr;
  $addr = flic_get_addr();
  print "Connecting to $addr\n";
  system("/usr/sbin/hciconfig hci0 up");
  system("/usr/bin/hcitool dc $addr")  ;
  system("/usr/sbin/hciconfig hci0 up");
  
  if (system("/usr/bin/hcitool cc $addr"))
  {
    die "Could not pair with Flic: error code $?\n";
  }
  
  if (system("/usr/bin/rfcomm bind 0"))
  {
    die "Could not bind to Flic: $?\n";
  } 
}


sub flic_fetch_code
{
  my $line,$code,$count;
  
  $line = flic_read_line();
  $code = "invalid";
  
  if ($line =~ /^\x02/)
  {
    $line =~ s/^\x02//;
    $count = substr($line,length($line)-4,4);
    #print "count: $count\n";
    flic_write($count.chr(0x06));
    $code = substr($line,0,length($line)-4);
  }
  
  return ($code,$count);
}

sub flic_read_line
{
  my $c,$res;

  $res = "";
  $last_nn = 0;
  
  for (;;)
  {
    $c = flic_readc();

    if (!defined($c))
    {
      next;
    }
      
    if ($c eq "\x0a")
    {
      return $res if ($last_nn);
      $last_nn = 1;
      next;
    }  
       
    $res .= $c;   
  }
}

sub flic_readc
{
  my $c;
  $n = read(FLIC,$c,1);

  if ($n == 0)
  {
    print "Read error\n";
    sleep(1);
    flic_reinit();
    return undef;
  }  
    
  #printf("read: %02x\n", unpack("C",$c));
  return $c;
}

sub flic_get_ts
{
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
       localtime(time);
  return sprintf("02%d-02%d-02%d %02d:%02d:%02d", $year + 1900,
   $mon + 1, $mday, $hour,$min,$sec);
}

sub flic_write
{
  my $data = shift;
  print FLIC $data; 
}

sub flic_open
{
  my $tty = shift;
  while (!open FLIC, "+<$tty")
  {
    print "Error opening $tty, retrying in 2 seconds...\n";
    sleep(2);
    flic_init();
  }
  binmode(FLIC);
  FLIC->autoflush(1);
}

sub flic_close
{
  close FLIC;
}

