File Coverage

blib/lib/Device/RFXCOM/Decoder/X10.pm
Criterion Covered Total %
statement 55 55 100.0
branch 18 18 100.0
condition 6 6 100.0
subroutine 11 11 100.0
pod 4 4 100.0
total 94 94 100.0


line stmt bran cond sub pod time code
1 4     4   3531 use strict;
  4         10  
  4         145  
2 4     4   20 use warnings;
  4         7  
  4         186  
3             package Device::RFXCOM::Decoder::X10;
4             $Device::RFXCOM::Decoder::X10::VERSION = '1.142010';
5             # ABSTRACT: Device::RFXCOM::Decoder::X10 decode X10 RF messages
6              
7              
8 4     4   74 use 5.006;
  4         118  
  4         189  
9 4     4   22 use constant DEBUG => $ENV{DEVICE_RFXCOM_DECODER_X10_DEBUG};
  4         8  
  4         231  
10 4     4   21 use Carp qw/croak/;
  4         8  
  4         198  
11 4     4   19 use base 'Device::RFXCOM::Decoder';
  4         8  
  4         356  
12 4     4   3164 use Device::RFXCOM::Response::X10;
  4         10  
  4         2263  
13              
14              
15             sub new {
16 8     8 1 118 my $pkg = shift;
17 8         58 $pkg->SUPER::new(unit_cache => {}, default_x10_level => 10, @_);
18             }
19              
20              
21             sub decode {
22 41     41 1 90 my ($self, $parent, $message, $bytes, $bits, $result) = @_;
23 41 100       101 my $res = from_rf($bytes) or return;
24 7         14 my $h = $res->{house};
25 7         14 my $f = $res->{command};
26 7 100       59 $self->{unit_cache}->{$h} = $res->{unit} if (exists $res->{unit});
27 7         26 my %r =
28             (
29             command => $f,
30             );
31 7         17 my $u = $self->{unit_cache}->{$h};
32 7         15 my $dont_cache;
33 7 100       19 if (defined $u) {
34 6         23 $r{device} = $h.$u;
35             } else {
36 1         11 warn "Don't have unit code for: $h $f\n";
37 1         7 $result->{dont_cache} = 1;
38 1         2 $r{house} = $h;
39             }
40 7 100 100     52 if ($f eq 'bright' or $f eq 'dim') {
41 3         7 $r{level} = $self->{default_x10_level};
42             }
43 7         14 push @{$result->{messages}}, Device::RFXCOM::Response::X10->new(%r);
  7         118  
44 7         46 return 1;
45             }
46              
47             my %byte_to_house =
48             (
49             '6' => 'a', '7' => 'b', '4' => 'c', '5' => 'd', '8' => 'e', '9' => 'f',
50             '10' => 'g', '11' => 'h', '14' => 'i', '15' => 'j', '12' => 'k',
51             '13' => 'l', '0' => 'm', '1' => 'n', '2' => 'o', '3' => 'p',
52             );
53              
54             my %byte_to_unit =
55             (
56             0x00 => 1, 0x10 => 2, 0x08 => 3, 0x18 => 4, 0x40 => 5, 0x50 => 6,
57             0x48 => 7, 0x58 => 8
58             );
59             my $unit_mask= 0x58;
60              
61             my %byte_to_command =
62             (
63             0x0 => 'on',
64             0x20 => 'off',
65             0x80 => 'all_lights_off',
66             0x88 => 'bright',
67             0x90 => 'all_lights_on',
68             0x98 => 'dim',
69             );
70              
71              
72             sub from_rf {
73 41     41 1 99 my $bytes = shift;
74              
75 41 100       88 return unless (is_x10($bytes));
76 7         26 my %r = ();
77 7         14 my $mask = 0x98;
78 7 100       27 unless ($bytes->[2]&0x80) {
79 4         21 $r{unit} = $byte_to_unit{$bytes->[2]&$unit_mask};
80 4 100       18 $r{unit} += 8 if ($bytes->[0]&0x4);
81 4         9 $mask = 0x20;
82             }
83 7         27 $r{house} = $byte_to_house{($bytes->[0]&0xf0)>>4};
84 7         29 $r{command} = $byte_to_command{$bytes->[2]&$mask};
85 7         37 return \%r;
86             }
87              
88              
89             sub is_x10 {
90 41     41 1 65 my $bytes = shift;
91              
92 41 100       232 return unless (scalar @$bytes == 4);
93              
94 15 100 100     182 (($bytes->[2]^0xff) == $bytes->[3] &&
95             ($bytes->[0]^0xff) == $bytes->[1] &&
96             !($bytes->[2]&0x7));
97             }
98              
99             1;
100              
101             __END__