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__ |