X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=scripts%2FRFID-JSONP-server.pl;h=f29c638262586f47c38991455af544e9dd7d5b7f;hb=5f2e55f0a56d3ea9dd7f360445e17c2c523933d0;hp=d9ea81469449673bf7b6f339b0b354cbb294d7cb;hpb=300bb4482fc3fe21b1d0d2205ee7e336f6824f5f;p=Biblio-RFID.git diff --git a/scripts/RFID-JSONP-server.pl b/scripts/RFID-JSONP-server.pl index d9ea814..f29c638 100755 --- a/scripts/RFID-JSONP-server.pl +++ b/scripts/RFID-JSONP-server.pl @@ -1,12 +1,12 @@ #!/usr/bin/perl -=head1 RFID-JSONP-server +=head1 NAME -This is simpliest possible JSONP server which provides local web interface to RFID readers +RFID-JSONP-server - simpliest possible JSONP server which provides local web interface to RFID readers -Usage: +=head1 USAGE - ./scripts/RFID-JSONP-server.pl + ./scripts/RFID-JSONP-server.pl [--debug] [--listen=127.0.0.1:9000] [--reader=filter] =cut @@ -17,35 +17,140 @@ use Data::Dump qw/dump/; use JSON::XS; use IO::Socket::INET; +use LWP::UserAgent; +use URI; +use POSIX qw(strftime); +use Encode; my $debug = 1; +my $listen = '127.0.0.1:9000'; +$listen = ':9000'; +my $reader; +my $koha_url = 'http://ffzg.koha-dev.rot13.org:8080'; +# internal URL so we can find local address of machine and vmware NAT +my $rfid_url = 'http://rfid.koha-dev.vbz.ffzg.hr'; +my $sip2 = { + server => '10.60.0.11:6002', # must be IP! +# user => 'sip2-user', +# password => 'sip2-passwd', + user => 'sip2user', + password => 'viva2koha', + loc => 'FFZG', +}; +my $afi = { + secure => 0xDA, + unsecure => 0xD7, +}; + +use Getopt::Long; + +GetOptions( + 'debug!' => \$debug, + 'listen=s', => \$listen, + 'reader=s', => \$reader, + 'koha=s', => \$koha_url, +) || die $!; + +our $rfid_sid_cache; + +sub rfid_borrower { + my $hash = shift; + if ( my $json = $rfid_sid_cache->{ $hash->{sid} } ) { + return $json; + } + my $ua = LWP::UserAgent->new; + my $url = URI->new( $koha_url . '/cgi-bin/koha/ffzg/rfid/borrower.pl'); + $url->query_form( + RFID_SID => $hash->{sid} + , OIB => $hash->{OIB} + , JMBAG => $hash->{JMBAG} + ); + warn "GET ",$url->as_string; + my $response = $ua->get($url); + if ( $response->is_success ) { + my $json = decode_json $response->decoded_content; + $rfid_sid_cache->{ $hash->{sid} } = $json; + return $json; + } else { + warn "ERROR ", $response->status_line; + } +} + + +sub sip2_message { + my $send = shift; + + my $sock = $sip2->{sock} || die "no sip2 socket"; + + local $/ = "\r"; + + $send .= "\r" unless $send =~ m/\r$/; + warn "SIP2 >>>> ",dump($send), "\n"; + print $sock $send; + $sock->flush; + + my $expect = substr($send,0,2) | 0x01; + + my $in = <$sock>; + $in =~ s/^\n//; + warn "SIP2 <<<< ",dump($in), "\n"; + + die "expected $expect" unless substr($in,0,2) != $expect; + + $in =~ s/\r$//; + + my $hash; + if ( $in =~ s/^([0-9\s]+)// ) { + $hash->{fixed} = $1; + } + foreach ( split(/\|/, $in ) ) { + my ( $f, $v ) = ( $1, $2 ) if m/([A-Z]{2})(.+)/; + $hash->{$f} = decode('utf-8',$v); + } + + warn "# sip2 hash response ",dump($hash); + + return $hash; +} -my $listen_port = 9000; # pick something not in use -my $server_url = "http://localhost:$listen_port"; +if ( my $server = $sip2->{server} ) { + my $sock = $sip2->{sock} = IO::Socket::INET->new( $server ) || die "can't connect to $server: $!"; + warn "SIP2 server ", $sock->peerhost, ":", $sock->peerport, "\n"; + # login + if ( sip2_message("9300CN$sip2->{user}|CO$sip2->{password}|")->{fixed} !~ m/^941/ ) { + die "SIP2 login failed"; + } + +} use lib 'lib'; -use RFID::Biblio::RFID501; -use RFID::Biblio::3M810; -my $rfid = RFID::Biblio::3M810->new; +use Biblio::RFID::RFID501; +use Biblio::RFID::Reader; +my $rfid = Biblio::RFID::Reader->new( shift @ARGV ); +$rfid->debug( $debug ); my $index_html; { local $/ = undef; $index_html = ; + $index_html =~ s{http://koha.example.com:8080}{$koha_url}sg; } +my $server_url; + sub http_server { my $server = IO::Socket::INET->new( Proto => 'tcp', - LocalPort => $listen_port, + LocalAddr => $listen, Listen => SOMAXCONN, Reuse => 1 ); die "can't setup server: $!" unless $server; + $server_url = 'http://' . $listen; print "Server $0 ready at $server_url\n"; while (my $client = $server->accept()) { @@ -69,13 +174,38 @@ sub http_server { if ( $path eq '/' ) { print $client "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n$index_html"; + } elsif ( $path =~ m{^/(examples/.+)} ) { + $path = $1; # FIXME prefix with dir for installation + my $size = -s $path; + warn "static $path $size bytes\n"; + my $content_type = 'text/plain'; + $content_type = 'application/javascript' if $path =~ /\.js$/; + $content_type = 'text/html' if $path =~ /\.html$/; + print $client "HTTP/1.0 200 OK\r\nContent-Type: $content_type\r\nContent-Length: $size\r\n\r\n"; + { + local $/ = undef; + open(my $fh, '<', $path) || die "can't open $path: $!"; + while(<$fh>) { + print $client $_; + } + close($fh); + } } elsif ( $method =~ m{/scan} ) { - my $tags = $rfid->scan; + my @tags = $rfid->tags; my $json = { time => time() }; - foreach my $tag ( keys %$tags ) { - my $hash = RFID::Biblio::RFID501->to_hash( $tags->{$tag} ); + foreach my $tag ( @tags ) { + my $hash = $rfid->to_hash( $tag ); $hash->{sid} = $tag; - $hash->{security} = uc unpack 'H*', $rfid->read_afi( $tag ); + if ( $hash->{tag_type} eq 'SmartX' ) { + my $borrower = rfid_borrower $hash; + if ( exists $borrower->{error} ) { + warn "ERROR ", dump($borrower); + } else { + $hash->{borrower} = $borrower->{borrower}; + } + } else { + $hash->{security} = uc unpack 'H*', $rfid->afi( $tag ); + } push @{ $json->{tags} }, $hash; }; warn "#### ", encode_json($json); @@ -88,13 +218,13 @@ sub http_server { foreach my $p ( keys %$param ) { next unless $p =~ m/^(E[0-9A-F]{15})$/; my $tag = $1; - my $content = "\x04\x11\x00\x01" . $param->{$p}; - $content = "\x00" if $param->{$p} eq 'blank'; + my $content = Biblio::RFID::RFID501->from_hash({ content => $param->{$p} }); + $content = Biblio::RFID::RFID501->blank if $param->{$p} eq 'blank'; $status = 302; warn "PROGRAM $tag $content\n"; - write_tag( $tag, $content ); - secure_tag_with( $tag, $param->{$p} =~ /^130/ ? 'DA' : 'D7' ); + $rfid->write_blocks( $tag => $content ); + $rfid->write_afi( $tag => chr( $param->{$p} =~ /^130/ ? $afi->{secure} : $afi->{unsecure} ) ); } print $client "HTTP/1.0 $status $method\r\nLocation: $server_url\r\n\r\n"; @@ -112,7 +242,7 @@ sub http_server { $status = 302; warn "SECURE $tag $data\n"; - secure_tag_with( $tag, $data ); + $rfid->write_afi( $tag => hex($data) ); } if ( $json ) { @@ -122,6 +252,42 @@ sub http_server { print $client "HTTP/1.0 $status $method\r\nLocation: $server_url\r\n\r\n"; } + } elsif ( $method =~ m{/sip2/(\w+)/(.+)} ) { + my ( $method, $args ) = ( $1, $2 ); + warn "SIP2: $method [$args]"; + + my $ts = strftime('%Y%m%d %H%M%S', localtime()); + my $loc = $sip2->{loc} || die "missing sip->{loc}"; + my $password = $sip2->{password} || die "missing sip->{password}"; + + my $hash; + + if ( $method eq 'patron_info' ) { + my $patron = $args; + $hash = sip2_message("63000${ts} AO$loc|AA$patron|AC$password|"); + + } elsif ( $method eq 'checkout' ) { + my ($patron,$barcode,$sid) = split(/\//, $args, 3); + $hash = sip2_message("11YN${ts} AO$loc|AA$patron|AB$barcode|AC$password|BON|BIN|"); + if ( substr( $hash->{fixed}, 2, 1 ) == 1 ) { + $rfid->write_afi( $sid => chr( $afi->{unsecure} ) ); + } + + } elsif ( $method eq 'checkin' ) { + my ($patron,$barcode,$sid) = split(/\//, $args, 3); + $hash = sip2_message("09N${ts}${ts}AP|AO${loc}|AB$barcode|AC|BIN|"); + if ( substr( $hash->{fixed}, 2, 1 ) == 1 ) { + $rfid->write_afi( $sid => chr( $afi->{secure} ) ); + } + } else { + print $client "HTTP/1.0 500 $method not implemented\r\n\r\n"; + } + + if ( $hash ) { + print $client "HTTP/1.0 200 OK\r\nContent-Type: application/json\r\n\r\n", + encode_json( $hash ); + } + } else { print $client "HTTP/1.0 404 Unkown method\r\n\r\n"; } @@ -134,6 +300,38 @@ sub http_server { die "server died"; } +sub rfid_register { + my $ip; + + foreach ( split(/\n/, `ip addr` ) ) { + if ( /^\d:\s(\w+):\s/ ) { + $ip->{last} = $1; + } elsif ( /^\s+inet\s((\d+)\.(\d+)\.(\d+)\.(\d+))\/(\d+)/ ) { + $ip->{ $ip->{last} } = $1; + } else { + warn "# SKIP [$_]\n"; + } + + } + + my $ua = LWP::UserAgent->new; + my $url = URI->new( $rfid_url . '/register.pl'); + $url->query_form( + local_ip => $ip->{eth0}, + ); + warn "GET ",$url->as_string; + my $response = $ua->get($url); + if ( $response->is_success ) { + warn "# ", $response->decoded_content; + my $json = decode_json $response->decoded_content; + warn "REGISTER: ",dump($json); + return $json; + } else { + warn "ERROR ", $response->status_line; + } +} + +rfid_register; http_server; __DATA__ @@ -179,15 +377,25 @@ function got_visible_tags(data,textStatus) { html = '