read programmed cards directly from log
[Biblio-RFID.git] / scripts / print.pl
1 #!/usr/bin/perl
2
3 use warnings;
4 use strict;
5
6 use Data::Dump qw(dump);
7 use Getopt::Long;
8 use lib 'lib';
9 use Biblio::RFID::Reader;
10 use Biblio::RFID::RFID501;
11 use Storable;
12
13 my $evolis_dir = '/home/dpavlin/klin/Printer-EVOLIS'; # FIXME
14 use lib '/home/dpavlin/klin/Printer-EVOLIS/lib';
15 use Printer::EVOLIS::Parallel;
16
17 my $loop = 1;
18 my $reader = '3M';
19 my $debug = 0;
20 my $afi   = 0x00; # XXX
21 my $test  = 0;
22
23 my $log_print = 'log.print';
24 mkdir $log_print unless -d $log_print;
25
26 GetOptions(
27         'loop!'     => \$loop,
28         'reader=s', => \$reader,
29         'debug+'    => \$debug,
30         'test+'     => \$test,
31 ) || die $!;
32
33 die "Usage: $0 print.txt\n" unless @ARGV;
34
35 my $programmed;
36 my $numbers;
37 foreach my $log_path ( glob( "$log_print/*.txt" ) ) {
38         warn "# loading $log_path";
39         open( my $in, '<', $log_path ) || die $!;
40         while(<$in>) {
41                 chomp;
42                 my ( $date, $sid, $nr ) = split(/,/,$_,3);
43                 $programmed->{ $sid } = $nr;
44                 $numbers->{ $nr } = $sid;       
45         }
46 }
47
48 warn "# ", scalar keys %$numbers, " programmed cards found\n";
49
50 my @queue;
51 my @done;
52 warn "# reading tab-delimited input: number login\@domain name surname\n";
53 while(<>) {
54         chomp;
55         my @a = split(/\t/,$_);
56         die "invalid: @a in line $_" if $a[0] !~ m/\d{12}/ && $a[1] !~ m/\@/;
57         push @queue, [ @a ] if ! $numbers->{ $a[0] };
58 }
59
60 # sort by card number
61 @queue = sort { $a->[0] <=> $b->[0] } @queue;
62
63 print "# queue ", dump @queue;
64
65 my $rfid = Biblio::RFID::Reader->new( $reader );
66 $Biblio::RFID::debug = $debug;
67
68 sub tag {
69         my $tag = shift;
70         return $tag
71                 , " AFI: "
72                 , uc unpack('H2', $rfid->afi($tag))
73                 , " "
74                 , dump( Biblio::RFID::RFID501->to_hash( $rfid->blocks($tag) ) )
75                 , $/
76                 ;
77 }
78
79 sub iso_date {
80         my @t = localtime(time);
81         return sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $t[5]+1900,$t[4]+1,$t[3],$t[2],$t[1],$t[0];
82 }
83
84 sub print_card;
85
86 my $log_path = "$log_print/" . iso_date . ".txt";
87 die "$log_path exists" if -e $log_path;
88 open(my $log, '>', $log_path) || die "$log_path: $!";
89
90 while ( $rfid->tags ) {
91         print "ERROR: remove all tags from output printer tray\n";
92         sleep 1;
93 }
94
95 print_card;
96
97 do {
98         my @visible = $rfid->tags(
99                 enter => sub {
100                         my $tag = shift;
101                         print localtime()." enter ", eval { tag($tag) };
102                         return if $@;
103
104                         if ( ! $programmed->{$tag} ) {
105                                 my $card = shift @queue;
106                                 my $number = $card->[0];
107                                 print "PROGRAM $tag $number\n";
108                                 $rfid->write_blocks( $tag => Biblio::RFID::RFID501->from_hash({ content => $number }) );
109                                 $rfid->write_afi( $tag => chr($afi) ) if $afi;
110
111                                 $programmed->{$tag} = $number;
112
113                                 print $log iso_date, ",$tag,$number\n";
114                         }
115
116                 },
117                 leave => sub {
118                         my $tag = shift;
119
120                         print_card if $programmed->{$tag};
121                 },
122         );
123
124         warn localtime()." visible: ",join(' ',@visible),"\n";
125
126         sleep 1;
127 } while $loop;
128
129 sub _counters {
130         my $p = shift;
131         my $counters;
132         $counters->{$_} = $p->command("Rco;$_") foreach ( qw/p c a m n l b e f i k s/ );
133         return $counters;
134 }
135
136 sub print_card {
137
138         if ( ! @queue ) {
139                 print "QUEUE EMPTY - printing finished\n";
140                 close($log);
141                 print "$log_path ", -s $log_path, " bytes created\n";
142                 exit;
143         }
144
145         my @data = @{$queue[0]};
146         my $nr = $data[0];
147         print "PRINT @data\n";
148
149         my $p = Printer::EVOLIS::Parallel->new( '/dev/usb/lp0' );
150
151         my $before = _counters $p;
152
153         if ( $test ) {
154
155                 print "insert card ", $p->command( 'Si' ),$/;
156                 sleep 1;
157                 print "eject card ", $p->command( 'Ser' ),$/;
158
159         } else {
160
161                 system "$evolis_dir/scripts/inkscape-render.pl", "$evolis_dir/card/ffzg-2010.svg", @data;
162                 system "$evolis_dir/scripts/evolis-driver.pl out/$nr.front.pbm out/$nr.back.pbm > /dev/usb/lp0";
163
164         }
165
166         my $after = _counters $p;
167
168         if ( $before->{p} = $after->{p} - 2 ) {
169                 print "OK printerd card $nr\n";
170         } else {
171                 die "ERROR printing card $nr\n";
172         }
173
174         warn "# counters ", dump( $before, $after );
175
176 }
177