rename Reader implementation all over [0.02]
[Biblio-RFID.git] / lib / RFID / Biblio / Readers.pm
1 package RFID::Biblio::Readers;
2
3 use warnings;
4 use strict;
5
6 use Data::Dump qw(dump);
7 use Time::HiRes;
8 use lib 'lib';
9 use RFID::Biblio;
10
11 =head1 NAME
12
13 RFID::Biblio::Readers - autodetect supported readers
14
15 =head1 FUNCTIONS
16
17 =head2 new
18
19   my $rfid = RFID::Biblio::Readers->new( 'optional reader filter' );
20
21 =cut
22
23 sub new {
24         my ( $class, $filter ) = @_;
25         my $self = {};
26         bless $self, $class;
27         $self->{_readers} = [ $self->_available( $filter ) ];
28         return $self;
29 }
30
31 =head2 tags
32
33   my @visible = $rfid->tags(
34                 enter => sub {},
35                 leave => sub {},
36   );
37
38 =cut
39
40 sub tags {
41         my $self = shift;
42         my $triggers = {@_};
43
44         $self->{inventory} ||= {};
45         $self->{inventory}->{$_} = 0 foreach keys %{$self->{inventory}};
46         my $t = time;
47
48         foreach my $rfid ( @{ $self->{_readers} } ) {
49                 warn "# inventory on $rfid";
50                 my @tags = $rfid->inventory;
51
52                 foreach my $tag ( @tags ) {
53
54                         $self->{blocks}->{$tag} ||= $rfid->read_blocks( $tag )->{$tag};
55                         $self->{afi}->{$tag}    ||= $rfid->read_afi( $tag );
56
57                         $triggers->{enter}->( $self, $tag ) if ! $self->{inventory}->{$tag} && $triggers->{enter};
58                         $self->{inventory}->{$tag} = $t;
59
60                 }
61
62                 foreach my $tag ( grep { $self->{inventory}->{$_} == 0 } keys %{ $self->{inventory} } ) {
63                         $triggers->{leave}->( $self, $tag ) if $triggers->{leave};
64                 }
65
66         }
67
68         warn "## tags ",dump($self);
69
70         return grep { $self->{inventory}->{$_} } keys %{ $self->{inventory} };
71 }
72
73 =head2 blocks
74
75   my $blocks_arrayref = $rfid->blocks( $tag );
76
77 =head2 afi
78
79   my $afi = $rfid->afi( $tag );
80
81 =cut
82
83 sub blocks { $_[0]->{ 'blocks' }->{$_[1]} || die "no blocks for $_[1]"; };
84 sub afi    { $_[0]->{ 'afi'    }->{$_[1]} || die "no afi for $_[1]"; };
85
86 =head1 PRIVATE
87
88 =head2 _available
89
90 Probe each RFID reader supported and returns succefull ones
91
92   my $rfid_readers = RFID::Biblio::Readers->_available( $regex_filter );
93
94 =cut
95
96 my @readers = ( '3M810', 'CPRM02', 'librfid' );
97
98 sub _available {
99         my ( $self, $filter ) = @_;
100
101         $filter = '' unless defined $filter;
102
103         warn "# filter: $filter";
104
105         my @rfid;
106
107         foreach my $reader ( @readers ) {
108                 next if $filter && $reader !~ /$filter/i;
109                 my $module = "RFID::Biblio::$reader";
110                 eval "use $module";
111                 die $@ if $@;
112                 if ( my $rfid = $module->new( device => '/dev/ttyUSB0' ) ) {
113                         push @rfid, $rfid;
114                         warn "# added $module\n";
115                 } else {
116                         warn "# ignored $module\n";
117                 }
118         }
119
120         die "no readers found" unless @rfid;
121
122         return @rfid;
123 }
124
125 =head1 AUTOLOAD
126
127 On any other function calls, we just marshall to all readers
128
129 =cut
130
131 # we don't want DESTROY to fallback into AUTOLOAD
132 sub DESTROY {}
133
134 our $AUTOLOAD;
135 sub AUTOLOAD {
136         my $self = shift;
137         my $command = $AUTOLOAD;
138         $command =~ s/.*://;
139
140         my @out;
141
142         foreach my $r ( @{ $self->{_readers} } ) {
143                 push @out, $r->$command(@_);
144         }
145
146         return @out;
147 }
148
149 1
150 __END__
151
152 =head1 SEE ALSO
153
154 =head2 RFID reader implementations
155
156 L<RFID::Biblio::Reader::3M810>
157
158 L<RFID::Biblio::Reader::CPRM02>
159
160 L<RFID::Biblio::Reader::librfid>
161