1 package FS::part_export::huawei_hlr;
3 use vars qw(@ISA %info $DEBUG $CACHE);
5 use FS::Record qw(qsearch qsearchs dbh);
14 @ISA = qw(FS::part_export);
16 tie my %options, 'Tie::IxHash',
17 'opname' => { label=>'Operator login' },
18 'pwd' => { label=>'Operator password' },
19 'tplid' => { label=>'Template number' },
20 'hlrsn' => { label=>'HLR serial number' },
21 'timeout' => { label=>'Timeout (seconds)', default => 120 },
22 'debug' => { label=>'Enable debugging', type=>'checkbox' },
27 'desc' => 'Provision mobile phone service to Huawei HLR9820',
28 'options' => \%options,
30 Connects to a Huawei Subscriber Management Unit via TCP and configures mobile
31 phone services according to a template. The <i>sim_imsi</i> field must be
32 set on the service, and the template must exist.
37 my( $self, $svc_phone ) = (shift, shift);
38 # svc_phone::check should ensure phonenum and sim_imsi are numeric
40 IMSI => '"'.$svc_phone->sim_imsi.'"',
41 ISDN => '"'.$svc_phone->countrycode.$svc_phone->phonenum.'"',
42 TPLID => $self->option('tplid'),
44 unshift @command, 'HLRSN', $self->option('hlrsn')
45 if $self->option('hlrsn');
46 unshift @command, 'ADD TPLSUB';
47 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
48 ref($err_or_queue) ? '' : $err_or_queue;
52 my( $self, $new, $old ) = @_;
54 if ( $new->sim_imsi ne $old->sim_imsi ) {
57 ISDN => '"'.$old->countrycode.$old->phonenum.'"',
58 IMSI => '"'.$old->sim_imsi.'"',
59 NEWIMSI => '"'.$new->sim_imsi.'"',
61 my $err_or_queue = $self->queue_command($new->svcnum, @command);
62 return $err_or_queue unless ref $err_or_queue;
63 $depend_jobnum = $err_or_queue->jobnum;
65 if ( $new->countrycode ne $old->countrycode or
66 $new->phonenum ne $old->phonenum ) {
69 ISDN => '"'.$old->countrycode.$old->phonenum.'"',
70 NEWISDN => '"'.$new->countrycode.$new->phonenum.'"',
72 my $err_or_queue = $self->queue_command($new->svcnum, @command);
73 return $err_or_queue unless ref $err_or_queue;
74 if ( $depend_jobnum ) {
75 my $error = $err_or_queue->depend_insert($depend_jobnum);
76 return $error if $error;
79 # no other svc_phone changes need to be exported
84 my( $self, $svc_phone ) = (shift, shift);
85 $self->_export_lock($svc_phone, 'TRUE');
88 sub _export_unsuspend {
89 my( $self, $svc_phone ) = (shift, shift);
90 $self->_export_lock($svc_phone, 'FALSE');
94 my ($self, $svc_phone, $lockstate) = @_;
95 # XXX I'm not sure this actually suspends. Need to test it.
98 IMSI => '"'.$svc_phone->sim_imsi.'"',
99 ISDN => '"'.$svc_phone->countrycode.$svc_phone->phonenum.'"',
102 GPRSLOCK=> $lockstate,
104 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
105 ref($err_or_queue) ? '' : $err_or_queue;
109 my( $self, $svc_phone ) = (shift, shift);
112 #IMSI => '"'.$svc_phone->sim_imsi.'"',
113 ISDN => '"'.$svc_phone->countrycode.$svc_phone->phonenum.'"',
115 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
116 ref($err_or_queue) ? '' : $err_or_queue;
120 my ($self, $svcnum, @command) = @_;
121 my $queue = FS::queue->new({
123 job => 'FS::part_export::huawei_hlr::run_command',
125 $queue->insert($self->exportnum, @command) || $queue;
129 my ($exportnum, @command) = @_;
130 my $self = FS::part_export->by_key($exportnum);
131 my $socket = $self->login;
132 my $result = $self->command($socket, @command);
133 $self->logout($socket);
135 die $result->{error} if $result->{error};
141 local $DEBUG = $self->option('debug') || 0;
142 # Send a command to the SMU.
143 # The caller is responsible for quoting string parameters.
145 PeerAddr => $self->machine,
148 Timeout => ($self->option('timeout') || 30),
150 warn "Connecting to ".$self->machine."...\n" if $DEBUG;
151 warn Dumper(\%socket_param) if $DEBUG;
152 my $socket = IO::Socket::INET->new(%socket_param)
153 or die "Failed to connect: $!\n";
155 warn 'Logging in as "'.$self->option('opname').".\"\n" if $DEBUG;
157 OPNAME => '"'.$self->option('opname').'"',
158 PWD => '"'.$self->option('pwd').'"',
160 if ($self->option('HLRSN')) {
161 unshift @login_param, 'HLRSN', $self->option('HLRSN');
163 my $login_result = $self->command($socket, 'LGI', @login_param);
164 die $login_result->{error} if $login_result->{error};
169 warn "Logging out.\n" if $DEBUG;
172 $self->command($socket, 'LGO');
178 my ($socket, $command, @param) = @_;
179 my $string = $command . ':';
181 $string .= shift(@param) . '=' . shift(@param);
182 $string .= ',' if @param;
187 local $SIG{ALRM} = sub { die "timeout\n" };
188 alarm ($self->option('timeout') || 120);
189 warn "Sending to server:\n$string\n\n" if $DEBUG;
190 $socket->print($string);
195 $line = $socket->getline();
196 warn $line if $DEBUG;
198 push @result, $line if length($line);
199 } until ( $line =~ /^---\s*END$/ or $socket->eof );
203 if ( $@ eq "timeout\n" ) {
204 return { error => 'request timed out' };
206 return { error => $@ };
208 #+++ HLR9820 <date> <time>\n
209 my $header = shift(@result);
210 $header =~ /(\+\+\+.*)/
211 or return { error => 'malformed response: '.$header };
212 $return{header} = $1;
213 #SMU #<serial number>\n
214 $return{smu} = shift(@result);
215 #%%<command string>%%\n
216 $return{echo} = shift(@result); # should match the input
217 #<message code>: <message description>\n
218 my $message = shift(@result);
219 if ($message =~ /^SUCCESS/) {
220 $return{success} = $message;
222 $return{error} = $message;
224 $return{trailer} = pop(@result);
225 $return{details} = join("\n",@result,'');