###########################################
# Switch local X10 devices on and off
# Mike Schilli, 2007 (m@perlmeister.com)
###########################################
package MyX10;
###########################################
use strict;
use warnings;
use Device::SerialPort;
use ControlX10::CM11;
use YAML qw(LoadFile);
use Log::Log4perl qw(:easy);
use DB_File;

###########################################
sub new {
###########################################
  my($class, %options) = @_;

  LOGDIE "You must be root" if $> != 0;

  my $self = {
    serial   => "/dev/ttyS0",
    baudrate => 4800,
    devices  => LoadFile("/etc/x10.conf"),
    commands => {
        on     => "J",
        off    => "K",
        status => undef,
    },
    dbm => {},
    dbmfile => "/var/local/myx10.db",
    %options,
  };

  $self->{devhash} = { 
      map { $_->{device} => $_ } 
      @{$self->{devices}} };

  dbmopen(%{$self->{dbm}}, 
          $self->{dbmfile}, 0644) or 
      LOGDIE "Cannot open $self->{dbmfile}";

  for (keys %{$self->{devhash}}) {
    $self->{dbm}->{$_} ||= "off";
  }

  bless $self, $class;
}

###########################################
sub DESTROY {
###########################################
    my($self) = @_;
    dbmclose(%{$self->{dbm}});
}

###########################################
sub send {
###########################################
  my($self, $device, $cmd) = @_;

  LOGDIE("No device specified") if 
      !defined $device;

  LOGDIE("Unknown device") if 
      !exists $self->{devhash}->{$device};

  LOGDIE("No command specified") if 
      !defined $cmd;

  LOGDIE("Unknown command") if
      !exists $self->{commands}->{$cmd};

  if($cmd eq "status") {
    print $self->status($device), "\n";
    return 1;
  }

  my $serial = Device::SerialPort->new(
    $self->{serial}, undef);

  $serial->baudrate($self->{baudrate});

  my($house_code, $unit_code) = split //,
    $self->{devhash}->{$device}->{code}, 2;

  sleep(1);

    # Address unit
  DEBUG "Addressing HC=$house_code ",
        "UC=$unit_code";
  ControlX10::CM11::send($serial,
               $house_code . $unit_code);
    
  DEBUG "Sending command $cmd ",
        "$self->{commands}->{$cmd}";
  ControlX10::CM11::send($serial, 
    $house_code . 
    $self->{commands}->{$cmd});

  $self->{dbm}->{$device} = $cmd;
}

###########################################
sub status {
###########################################
    my($self, $device) = @_;
    return $self->{dbm}->{$device};
}

1;
