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 'debug' => { label=>'Enable debugging', type=>'checkbox' },
26 'desc' => 'Provision mobile phone service to Huawei HLR9820',
27 'options' => \%options,
29 Connects to a Huawei Subscriber Management Unit via TCP and configures mobile
30 phone services according to a template. The <i>sim_imsi</i> field must be
31 set on the service, and the template must exist.
36 my( $self, $svc_phone ) = (shift, shift);
37 # svc_phone::check should ensure phonenum and sim_imsi are numeric
40 IMSI => '"'.$svc_phone->sim_imsi.'"',
41 ISDN => '"'.$svc_phone->phonenum.'"',
42 TPLID => $self->option('tplid'),
44 unshift @command, 'HLRSN', $self->option('hlrsn')
45 if $self->option('hlrsn');
46 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
47 ref($err_or_queue) ? '' : $err_or_queue;
51 my( $self, $new, $old ) = @_;
53 if ( $new->sim_imsi ne $old->sim_imsi ) {
56 ISDN => '"'.$old->phonenum.'"',
57 IMSI => '"'.$old->sim_imsi.'"',
58 NEWIMSI => '"'.$new->sim_imsi.'"',
60 my $err_or_queue = $self->queue_command($new->svcnum, @command);
61 return $err_or_queue unless ref $err_or_queue;
62 $depend_jobnum = $err_or_queue->jobnum;
64 if ( $new->phonenum ne $old->phonenum ) {
67 ISDN => '"'.$old->phonenum.'"',
68 NEWISDN => '"'.$new->phonenum.'"',
70 my $err_or_queue = $self->queue_command($new->svcnum, @command);
71 return $err_or_queue unless ref $err_or_queue;
72 if ( $depend_jobnum ) {
73 my $error = $err_or_queue->depend_insert($depend_jobnum);
74 return $error if $error;
77 # no other svc_phone changes need to be exported
82 my( $self, $svc_phone ) = (shift, shift);
83 $self->_export_lock($svc_phone, 'TRUE');
86 sub _export_unsuspend {
87 my( $self, $svc_phone ) = (shift, shift);
88 $self->_export_lock($svc_phone, 'FALSE');
92 my ($self, $svc_phone, $lockstate) = @_;
93 # XXX I'm not sure this actually suspends. Need to test it.
96 IMSI => '"'.$svc_phone->sim_imsi.'"',
97 ISDN => '"'.$svc_phone->phonenum.'"',
100 GPRSLOCK=> $lockstate,
102 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
103 ref($err_or_queue) ? '' : $err_or_queue;
107 my( $self, $svc_phone ) = (shift, shift);
110 IMSI => '"'.$svc_phone->sim_imsi.'"',
111 ISDN => '"'.$svc_phone->phonenum.'"',
113 my $err_or_queue = $self->queue_command($svc_phone->svcnum, @command);
114 ref($err_or_queue) ? '' : $err_or_queue;
118 my ($self, $svcnum, @command) = @_;
119 my $queue = FS::queue->new({
121 job => 'FS::part_export::huawei_hlr::run_command',
123 $queue->insert($self->exportnum, @command) || $queue;
127 my ($exportnum, @command) = @_;
128 my $self = FS::part_export->by_key($exportnum);
129 my $socket = $self->login;
130 my $result = $self->command($socket, @command);
131 $self->logout($socket);
133 die $result->{error} if $result->{error};
139 local $DEBUG = $self->option('debug') || 0;
140 # Send a command to the SMU.
141 # The caller is responsible for quoting string parameters.
143 PeerAddr => $self->machine,
146 Timeout => ($self->option('timeout') || 30),
148 warn "Connecting to ".$self->machine."...\n" if $DEBUG;
149 warn Dumper(\%socket_param) if $DEBUG;
150 my $socket = IO::Socket::INET->new(%socket_param)
151 or die "Failed to connect: $!\n";
153 warn 'Logging in as "'.$self->option('opname').".\"\n" if $DEBUG;
155 OPNAME => '"'.$self->option('opname').'"',
156 PWD => '"'.$self->option('pwd').'"',
158 if ($self->option('HLRSN')) {
159 unshift @login_param, 'HLRSN', $self->option('HLRSN');
161 my $login_result = $self->command($socket, 'LGI', @login_param);
162 die $login_result->{error} if $login_result->{error};
167 warn "Logging out.\n" if $DEBUG;
170 $self->command($socket, 'LGO');
176 my ($socket, $command, @param) = @_;
177 my $string = $command . ':';
179 $string .= shift(@param) . '=' . shift(@param);
180 $string .= ',' if @param;
185 local $SIG{ALRM} = sub { die "timeout\n" };
186 alarm ($self->option('timeout') || 30);
187 warn "Sending to server:\n$string\n\n" if $DEBUG;
188 $socket->print($string);
192 $line = $socket->getline();
193 warn $line if $DEBUG;
195 push @result, $line if length($line);
196 } until ( $line =~ /^---\s*END$/ or $socket->eof );
200 if ( $@ eq "timeout\n" ) {
201 return { error => 'request timed out' };
203 return { error => $@ };
205 #+++ HLR9820 <date> <time>\n
207 my $header = shift(@result);
208 return { error => 'malformed response: '.$header }
209 unless $header =~ /^\+\+\+/;
210 $return{header} = $header;
211 #SMU #<serial number>\n
212 $return{smu} = shift(@result);
213 #%%<command string>%%\n
214 $return{echo} = shift(@result); # should match the input
215 #<message code>: <message description>\n
216 my $message = shift(@result);
217 if ($message =~ /^SUCCESS/) {
218 $return{success} = $message;
220 $return{error} = $message;
222 $return{trailer} = pop(@result);
223 $return{details} = join("\n",@result,'');