3 # This file is part of Koha.
5 # Copyright (C) 2012-2013 ByWater Solutions
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
26 use C4::SIP::Sip::Constants qw(:all);
28 use constant { LANGUAGE => '001' };
39 my $patron_identifier;
44 my $fee_acknowledged = 0;
51 "a|address|host|hostaddress=s" => \$host, # sip server ip
52 "p|port=s" => \$port, # sip server port
53 "su|sip_user=s" => \$login_user_id, # sip user
54 "sp|sip_pass=s" => \$login_password, # sip password
55 "l|location|location_code=s" => \$location_code, # sip location code
57 "patron=s" => \$patron_identifier, # patron cardnumber or login
58 "password=s" => \$patron_password, # patron's password
60 "i|item=s" => \$item_identifier,
62 "fa|fee-acknowledged" => \$fee_acknowledged,
64 "t|terminator=s" => \$terminator,
66 "m|message=s" => \@messages,
81 $terminator = ( $terminator eq 'CR' ) ? $CR : $CRLF;
83 # Set perl to expect the same record terminator it is sending
86 my ( $sec, $min, $hour, $day, $month, $year ) = localtime(time);
88 my $transaction_date = "$year$month$day $hour$min$sec";
90 my $terminal_password = $login_password;
93 print "Attempting socket connection to $host:$port...";
95 my $socket = IO::Socket::INET->new("$host:$port")
96 or die "failed! : $!\n";
102 subroutine => \&build_login_command_message,
104 login_user_id => $login_user_id,
105 login_password => $login_password,
106 location_code => $location_code,
109 patron_status_request => {
110 name => 'Patron Status Request',
111 subroutine => \&build_patron_status_request_command_message,
113 transaction_date => $transaction_date,
114 institution_id => $location_code,
115 patron_identifier => $patron_identifier,
116 terminal_password => $terminal_password,
117 patron_password => $patron_password,
119 optional => [ 'patron_password', ],
121 patron_information => {
122 name => 'Patron Information',
123 subroutine => \&build_patron_information_command_message,
125 transaction_date => $transaction_date,
126 institution_id => $location_code,
127 patron_identifier => $patron_identifier,
128 terminal_password => $terminal_password,
129 patron_password => $patron_password,
131 optional => [ 'patron_password', ],
133 item_information => {
134 name => 'Item Information',
135 subroutine => \&build_item_information_command_message,
137 transaction_date => $transaction_date,
138 institution_id => $location_code,
139 item_identifier => $item_identifier,
140 terminal_password => $terminal_password,
146 subroutine => \&build_checkout_command_message,
148 SC_renewal_policy => 'Y',
150 transaction_date => $transaction_date,
151 nb_due_date => undef,
152 institution_id => $location_code,
153 patron_identifier => $patron_identifier,
154 item_identifier => $item_identifier,
155 terminal_password => $terminal_password,
156 item_properties => undef,
157 patron_password => $patron_password,
158 fee_acknowledged => $fee_acknowledged,
162 'nb_due_date', # defaults to transaction date
171 subroutine => \&build_checkin_command_message,
174 transaction_date => $transaction_date,
175 return_date => $transaction_date,
176 current_location => $location_code,
177 institution_id => $location_code,
178 item_identifier => $item_identifier,
179 terminal_password => $terminal_password,
180 item_properties => undef,
184 'return_date', # defaults to transaction date
192 subroutine => \&build_renew_command_message,
194 third_party_allowed => 'N',
196 transaction_date => $transaction_date,
197 nb_due_date => undef,
198 institution_id => $location_code,
199 patron_identifier => $patron_identifier,
200 patron_password => $patron_password,
201 item_identifier => $item_identifier,
202 title_identifier => undef,
203 terminal_password => $terminal_password,
204 item_properties => undef,
205 fee_acknowledged => $fee_acknowledged,
208 'nb_due_date', # defaults to transaction date
219 my $data = run_command_message('login');
221 if ( $data =~ '^941' ) { ## we are logged in
222 foreach my $m (@messages) {
225 my $data = run_command_message($m);
233 sub build_command_message {
236 ##FIXME It would be much better to use exception handling so we aren't priting from subs
237 unless ( $handlers->{$message} ) {
238 say "$message is an unsupported command!";
242 my $subroutine = $handlers->{$message}->{subroutine};
243 my $parameters = $handlers->{$message}->{parameters};
244 my %optional = map { $_ => 1 } @{ $handlers->{$message}->{optional} };
246 foreach my $key ( keys %$parameters ) {
247 unless ( $parameters->{$key} ) {
248 unless ( $optional{$key} ) {
249 say "$key is required for $message";
255 return &$subroutine($parameters);
258 sub run_command_message {
261 my $command_message = build_command_message($message);
263 return unless $command_message;
265 say "SEND: $command_message";
266 print $socket $command_message . $terminator;
268 my $data = <$socket>;
275 sub build_login_command_message {
278 my $login_user_id = $params->{login_user_id};
279 my $login_password = $params->{login_password};
280 my $location_code = $params->{location_code};
284 . build_field( FID_LOGIN_UID, $login_user_id )
285 . build_field( FID_LOGIN_PWD, $login_password )
286 . build_field( FID_LOCATION_CODE, $location_code );
289 sub build_patron_status_request_command_message {
292 my $transaction_date = $params->{transaction_date};
293 my $institution_id = $params->{institution_id};
294 my $patron_identifier = $params->{patron_identifier};
295 my $terminal_password = $params->{terminal_password};
296 my $patron_password = $params->{patron_password};
302 . build_field( FID_INST_ID, $institution_id )
303 . build_field( FID_PATRON_ID, $patron_identifier )
304 . build_field( FID_TERMINAL_PWD, $terminal_password )
305 . build_field( FID_PATRON_PWD, $patron_password );
308 sub build_patron_information_command_message {
311 my $transaction_date = $params->{transaction_date};
312 my $institution_id = $params->{institution_id};
313 my $patron_identifier = $params->{patron_identifier};
314 my $terminal_password = $params->{terminal_password};
315 my $patron_password = $params->{patron_password};
324 . build_field( FID_INST_ID, $institution_id )
325 . build_field( FID_PATRON_ID, $patron_identifier )
326 . build_field( FID_TERMINAL_PWD, $terminal_password )
327 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } );
330 sub build_item_information_command_message {
333 my $transaction_date = $params->{transaction_date};
334 my $institution_id = $params->{institution_id};
335 my $item_identifier = $params->{item_identifier};
336 my $terminal_password = $params->{terminal_password};
342 . build_field( FID_INST_ID, $institution_id )
343 . build_field( FID_ITEM_ID, $item_identifier )
344 . build_field( FID_TERMINAL_PWD, $terminal_password );
347 sub build_checkout_command_message {
350 my $SC_renewal_policy = $params->{SC_renewal_policy} || 'N';
351 my $no_block = $params->{no_block} || 'N';
352 my $transaction_date = $params->{transaction_date};
353 my $nb_due_date = $params->{nb_due_date};
354 my $institution_id = $params->{institution_id};
355 my $patron_identifier = $params->{patron_identifier};
356 my $item_identifier = $params->{item_identifier};
357 my $terminal_password = $params->{terminal_password};
358 my $item_properties = $params->{item_properties};
359 my $patron_password = $params->{patron_password};
360 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
361 my $cancel = $params->{cancel} || 'N';
363 $SC_renewal_policy = $SC_renewal_policy eq 'Y' ? 'Y' : 'N';
364 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
365 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
366 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
368 $nb_due_date ||= $transaction_date;
376 . build_field( FID_INST_ID, $institution_id )
377 . build_field( FID_PATRON_ID, $patron_identifier )
378 . build_field( FID_ITEM_ID, $item_identifier )
379 . build_field( FID_TERMINAL_PWD, $terminal_password )
380 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
381 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
382 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } )
383 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
386 sub build_checkin_command_message {
389 my $no_block = $params->{no_block} || 'N';
390 my $transaction_date = $params->{transaction_date};
391 my $return_date = $params->{return_date};
392 my $current_location = $params->{current_location};
393 my $institution_id = $params->{institution_id};
394 my $item_identifier = $params->{item_identifier};
395 my $terminal_password = $params->{terminal_password};
396 my $item_properties = $params->{item_properties};
397 my $cancel = $params->{cancel} || 'N';
399 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
400 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
402 $return_date ||= $transaction_date;
409 . build_field( FID_CURRENT_LOCN, $current_location )
410 . build_field( FID_INST_ID, $institution_id )
411 . build_field( FID_ITEM_ID, $item_identifier )
412 . build_field( FID_TERMINAL_PWD, $terminal_password )
413 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
414 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
417 sub build_renew_command_message {
420 my $third_party_allowed = $params->{third_party_allowed} || 'N';
421 my $no_block = $params->{no_block} || 'N';
422 my $transaction_date = $params->{transaction_date};
423 my $nb_due_date = $params->{nb_due_date};
424 my $institution_id = $params->{institution_id};
425 my $patron_identifier = $params->{patron_identifier};
426 my $patron_password = $params->{patron_password};
427 my $item_identifier = $params->{item_identifier};
428 my $title_identifier = $params->{title_identifier};
429 my $terminal_password = $params->{terminal_password};
430 my $item_properties = $params->{item_properties};
431 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
433 $third_party_allowed = $third_party_allowed eq 'Y' ? 'Y' : 'N';
434 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
435 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
437 $nb_due_date ||= $transaction_date;
441 . $third_party_allowed
445 . build_field( FID_INST_ID, $institution_id )
446 . build_field( FID_PATRON_ID, $patron_identifier )
447 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
448 . build_field( FID_ITEM_ID, $item_identifier )
449 . build_field( FID_TITLE_ID, $title_identifier )
450 . build_field( FID_TERMINAL_PWD, $terminal_password )
451 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
452 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } );
456 my ( $field_identifier, $value, $params ) = @_;
460 return q{} if ( $params->{optional} && !$value );
462 return $field_identifier . $value . '|';
466 say q/sip_cli_emulator.pl - SIP command line emulator
468 Test a SIP2 service by sending patron status and patron
469 information requests.
472 sip_cli_emulator.pl [OPTIONS]
475 --help display help message
477 -a --address SIP server ip address or host name
478 -p --port SIP server port
480 -su --sip_user SIP server login username
481 -sp --sip_pass SIP server login password
483 -l --location SIP location code
485 --patron ILS patron cardnumber or username
486 --password ILS patron password
488 --item ILS item identifier ( item barcode )
490 -t --terminator SIP2 message terminator, either CR, or CRLF
493 -fa --fee-acknowledged Sends a confirmation of checkout fee
495 -m --message SIP2 message to execute
497 Implemented Messages:
498 patron_status_request