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