dbb51a8473a7dfd4dafec3705233c172cf0ee261
[Biblio-RFID.git] / scripts / RFID-JSONP-server.pl
1 #!/usr/bin/perl
2
3 =head1 RFID-JSONP-server
4
5 This is simpliest possible JSONP server which provides local web interface to RFID readers
6
7 Usage:
8
9   ./scripts/RFID-JSONP-server.pl
10
11 =cut
12
13 use strict;
14 use warnings;
15
16 use Data::Dump qw/dump/;
17
18 use JSON;
19 use IO::Socket::INET;
20
21 my $debug = 1;
22
23 my $listen_port = 9000;                  # pick something not in use
24 my $server_url  = "http://localhost:$listen_port";
25
26
27 use lib 'lib';
28 use RFID::Serial::3M810;
29 my $rfid = RFID::Serial::3M810->new;
30
31 my $index_html;
32 {
33         local $/ = undef;
34         $index_html = <DATA>;
35 }
36
37 sub http_server {
38
39         my $server = IO::Socket::INET->new(
40                 Proto     => 'tcp',
41                 LocalPort => $listen_port,
42                 Listen    => SOMAXCONN,
43                 Reuse     => 1
44         );
45                                                                   
46         die "can't setup server: $!" unless $server;
47
48         print "Server $0 ready at $server_url\n";
49
50         while (my $client = $server->accept()) {
51                 $client->autoflush(1);
52                 my $request = <$client>;
53
54                 warn "WEB << $request\n" if $debug;
55                 my $path;
56
57                 if ($request =~ m{^GET (/.*) HTTP/1.[01]}) {
58                         my $method = $1;
59                         my $param;
60                         if ( $method =~ s{\?(.+)}{} ) {
61                                 foreach my $p ( split(/[&;]/, $1) ) {
62                                         my ($n,$v) = split(/=/, $p, 2);
63                                         $param->{$n} = $v;
64                                 }
65                                 warn "WEB << param: ",dump( $param ) if $debug;
66                         }
67                         $path = $method;
68
69                         if ( $path eq '/' ) {
70                                 print $client "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n$index_html";
71                         } elsif ( $method =~ m{/scan} ) {
72                                 my $tags = $rfid->scan;
73                                 my $json = {
74                                         time => time(),
75                                         tags => $tags,
76                                 };
77                                 print $client "HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n",
78                                         $param->{callback}, "(", to_json($json), ")\r\n";
79                         } elsif ( $method =~ m{/program} ) {
80
81                                 my $status = 501; # Not implementd
82
83                                 foreach my $p ( keys %$param ) {
84                                         next unless $p =~ m/^(E[0-9A-F]{15})$/;
85                                         my $tag = $1;
86                                         my $content = "\x04\x11\x00\x01" . $param->{$p};
87                                         $content = "\x00" if $param->{$p} eq 'blank';
88                                         $status = 302;
89
90                                         warn "PROGRAM $tag $content\n";
91                                         write_tag( $tag, $content );
92                                         secure_tag_with( $tag, $param->{$p} =~ /^130/ ? 'DA' : 'D7' );
93                                 }
94
95                                 print $client "HTTP/1.0 $status $method\r\nLocation: $server_url\r\n\r\n";
96
97                         } elsif ( $method =~ m{/secure(.js)} ) {
98
99                                 my $json = $1;
100
101                                 my $status = 501; # Not implementd
102
103                                 foreach my $p ( keys %$param ) {
104                                         next unless $p =~ m/^(E[0-9A-F]{15})$/;
105                                         my $tag = $1;
106                                         my $data = $param->{$p};
107                                         $status = 302;
108
109                                         warn "SECURE $tag $data\n";
110                                         secure_tag_with( $tag, $data );
111                                 }
112
113                                 if ( $json ) {
114                                         print $client "HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n",
115                                                 $param->{callback}, "({ ok: 1 })\r\n";
116                                 } else {
117                                         print $client "HTTP/1.0 $status $method\r\nLocation: $server_url\r\n\r\n";
118                                 }
119
120                         } else {
121                                 print $client "HTTP/1.0 404 Unkown method\r\n\r\n";
122                         }
123                 } else {
124                         print $client "HTTP/1.0 500 No method\r\n\r\n";
125                 }
126                 close $client;
127         }
128
129         die "server died";
130 }
131
132 http_server;
133
134 __DATA__
135 <html>
136 <head>
137 <title>RFID JSONP</title>
138 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
139 <style type="text/css">
140 .status {
141         background: #ff8;
142 }
143
144 .da {
145         background: #fcc;
146 }
147
148 .d7 {
149         background: #cfc;
150 }
151
152 label[for=pull-reader] {
153         position: absolute;
154         top: 1em;
155         right: 1em;
156         background: #eee;
157 }
158
159 </style>
160 <script type="text/javascript">
161
162 function got_visible_tags(data,textStatus) {
163         var html = 'No tags in range';
164         if ( data.tags ) {
165                 html = '<ul class="tags">';
166                 $.each(data.tags, function(i,tag) {
167                         console.debug( i, tag );
168                         html += '<li><tt class=' + tag.security + '>' + tag.sid;
169                         if ( tag.content ) {
170                                 html += ' <a href="https://koha-dev.rot13.org:8443/cgi-bin/koha/members/member.pl?member=' + tag.content + '" title="lookup in Koha" target="koha-lookup">' + tag.content + '</a>';
171                                 html += '</tt>';
172                                 html += '<form method=get action=program style="display:inline">'
173                                         + '<input type=hidden name='+tag.sid+' value="blank">'
174                                         + '<input type=submit value="Blank" onclick="return confirm(\'Blank tag '+tag.sid+'\')">'
175                                         + '</form>'
176                                 ;
177                         } else {
178                                 html += '</tt>';
179                                 html += ' <form method=get action=program style="display:inline">'
180                                         + '<!-- <input type=checkbox name=secure value='+tag.sid+' title="secure tag"> -->'
181                                         + '<input type=text name='+tag.sid+' size=12>'
182                                         + '<input type=submit value="Program">'
183                                         + '</form>'
184                                 ;
185                         }
186                 });
187                 html += '</ul>';
188         }
189
190         var arrows = Array( 8592, 8598, 8593, 8599, 8594, 8600, 8595, 8601 );
191
192         html = '<div class=status>'
193                 + textStatus
194                 + ' &#' + arrows[ data.time % arrows.length ] + ';'
195                 + '</div>'
196                 + html
197                 ;
198         $('#tags').html( html );
199         window.setTimeout(function(){
200                 scan_tags();
201         },200); // re-scan every 200ms
202 };
203
204 function scan_tags() {
205         console.info('scan_tags');
206         if ( $('input#pull-reader').attr('checked') )
207                 $.getJSON("/scan?callback=?", got_visible_tags);
208 }
209
210 $(document).ready(function() {
211                 $('input#pull-reader').click( function() {
212                         scan_tags();
213                 });
214                 $('input#pull-reader').attr('checked', true); // force check on load
215
216                 $('div#tags').click( function() {
217                         $('input#pull-reader').attr('checked', false);
218                 } );
219
220                 scan_tags();
221 });
222 </script>
223 </head>
224 <body>
225
226 <h1>RFID tags in range</h1>
227
228 <label for=pull-reader>
229 <input id=pull-reader type=checkbox checked=1>
230 active
231 </label>
232
233 <div id="tags">
234 RFID reader not found or driver program not started.
235 </div>
236
237 </body>
238 </html>