:pserver:anonymous@intra.tektonica.com:/opt/cvs - gsmperl - Fri Dec 21 07:37 CET...
[gsmperl.git] / GSM / SMS / NBS.pm
1 package GSM::SMS::NBS;
2
3 use vars qw($VERSION);
4
5 $VERSION = '0.142';
6
7 use GSM::SMS::NBS::Message;
8 use GSM::SMS::NBS::Stack;
9 use GSM::SMS::OTA::RTTTL;
10 use GSM::SMS::OTA::CLIicon;
11 use GSM::SMS::OTA::Operatorlogo;
12 use GSM::SMS::OTA::VCard;
13 use GSM::SMS::OTA::Config;
14 use GSM::SMS::Transport;
15 use MIME::Base64;
16
17
18 #
19 # Constructor
20 #
21 sub new {
22         my $proto = shift;
23         my $class = ref($proto) || $proto;
24         my $self = {};
25         bless($self, $class);
26
27         $self->{'__CONFIG_FILE__'} = shift;
28         return undef unless $self->{'__TRANSPORT__'} = GSM::SMS::Transport->new( $self->{'__CONFIG_FILE__'});
29         $self->{'__STACK__'} = GSM::SMS::NBS::Stack->new( -transport => $self->{'__TRANSPORT__'} );     
30         return $self;
31 }
32
33 #
34 # Send  message
35 #
36 sub sendto {
37         my ($self, $msisdn, $message, $dport, $sport, $dcs ) = @_;
38         my $ret = 0;
39
40         my $transport = $self->{'__TRANSPORT__'};
41
42         my $nbs_message = GSM::SMS::NBS::Message->new();
43         $nbs_message->create($msisdn, $message, $dport, $sport, $dcs);
44         foreach my $frame ( @{$nbs_message->get_frames()} ) {
45                 # transport->send returns -1 on failure.
46                 $ret = -1 if $transport->send($msisdn, $frame);
47         }
48         return $ret;    
49 }
50
51 #
52 # send ringing tone 
53 #
54 sub sendRTTTL {
55         my ($self, $msisdn, $rtttlstring) = @_;
56
57         if ( my $error = OTARTTTL_check($rtttlstring) ) {
58                 return $error;
59         }
60
61         my $music = OTARTTTL_makestream($rtttlstring);
62         return $self->sendto( $msisdn, $music, OTARTTTL_PORT);
63 }
64
65 #
66 # send operator logo
67 #
68 sub sendOperatorLogo_b64 {
69         my ($self, $msisdn, $country, $operator, $b64, $format) = @_;
70         
71         my $ol = OTAOperatorlogo_fromb64( $country, $operator, $b64, $format );
72         return $self->sendto( $msisdn, $ol, OTAOperatorlogo_PORT);
73 }
74
75 #
76 # send operator logo
77 #
78 sub sendOperatorLogo_file {
79         my ($self, $msisdn, $country, $operator, $file ) = @_;
80
81         my $ol = OTAOperatorlogo_fromfile( $country, $operator, $file );
82         return $self->sendto($msisdn, $ol, OTAOperatorlogo_PORT);
83 }
84
85 #
86 # send group graphic
87 #
88 sub sendGroupGraphic_b64 {
89         my ($self, $msisdn, $b64, $format) = @_;
90
91         my $gg = OTACLIicon_fromb64( $b64, $format );
92         return $self->sendto($msisdn, $gg, OTACLIicon_PORT);
93 }
94
95 #
96 # send group graphic
97 #
98 sub sendGroupGraphic_file {
99         my ($self, $msisdn, $file) = @_;
100
101         my $gg = OTACLIicon_fromfile( $file );
102         
103         return $self->sendto($msisdn, $gg, OTACLIicon_PORT);
104 }
105
106 #
107 # send VCard
108 #
109 sub sendVCard {
110         my ($self, $msisdn, $lname, $fname, $phone) = @_;
111
112         my $vcard = OTAVcard_makestream( $last, $first, $phone );
113         return $self->sendto( $msisdn, $vcard, OTAVcard_PORT);
114 }
115
116 #
117 # send OTA
118 #
119 sub sendConfig {
120         my ($self, $msisdn, $bearer, $connection, $auth, $type, $speed, $proxy, $home, $uid, $pwd, $phone, $name) = @_;
121
122         my $ret = -1;
123         my $ota = OTAConfig_makestream(  $bearer, $connection, $auth, $type, $speed, $proxy, $home, $uid, $pwd, $phone, $name);
124         if ( $ota ) {
125                 $ret = $self->sendto( $msisdn, $ota, OTAConfig_PORT, 9200);
126         }
127         return $ret;
128 }
129
130 #
131 # send SMS text message
132 #
133 sub sendSMSTextMessage {
134         my ($self, $msisdn, $msg, $multipart) = @_;
135         my $cnt = 0;    
136         my $ret = 0;
137         if ( $multipart ) {
138                 while (length($msg) > 0) {
139                         my $xmsg = substr($msg, 0, (length($msg)<160)?length($msg):160 );
140                         $msg = substr($msg, 160, length($msg) - 160);
141                         $ret = -1 if $self->sendto( $msisdn, $xmsg, undef, undef, '7bit');
142                         $cnt++;
143                 }
144         } else {
145                 $msg = substr($msg, 0, (length($msg)<160)?length($msg):160 );
146                 $ret = $self->sendto( $msisdn, $msg, undef , undef , '7bit');
147         }
148         return ($ret==-1)?$ret:$cnt;
149 }
150
151 #
152 # receive SMS message from stack
153 #
154 sub receive {
155         my ($self, $ref_originatingaddress, $ref_message, $ref_timestamp, $ref_transportname, $ref_port, $blocking) = @_;       
156
157         my $stack = $self->{'__STACK__'};
158         return $stack->receive($ref_originatingaddress, $ref_message, $ref_timestamp, $ref_transportname, $ref_port, $blocking);
159 }
160
161 1;
162
163 =head1 NAME
164
165 GSM::SMS::NBS - API for sending and receiving SMS messages.
166
167 =head1 SYNOPSIS
168
169         use GSM::SMS::NBS;
170
171         my $nbs = GSM::SMS::NBS->new( $transportconfigfile );
172         
173         ...     
174
175         $nbs->sendRTTTL( '+32475000000', $rtttl_string );
176         $nbs->sendOperatorLogo_b64( $msisdn, $countrycode, $operator, $b64, 'gif' );
177         $nbs->sendOperatorLogo_file( $msisdn, $countrycode, $operatorcode, $file );
178         $nbs->sendGroupGraphic_b64( $msisdn, $b64, 'png' );
179         $nbs->sendGroupGraphic_file( $msisdn, $file );
180         $nbs->sendVCard( $msisdn, $lastname, $firstname, $phonenumber );
181         $nbs->sendConfig( .... );
182         $nbs->sendSMSTextMessage( $msisdn, $message, $multipart );
183
184         ...
185         
186         my $originatingaddress;
187         my $message;
188         my $timestamp;
189         my $transportname;
190         my $port;
191         my $blocking = 1;
192
193         $nbs->receive(  \$originatingaddress,
194                                         \$message,
195                                         \$timestamp,
196                                         \$transportname,
197                                         \$port,
198                                         $blocking
199                                 );
200
201         print "I got a message from $originatingaddress\n";
202                 
203
204 =head1 DESCRIPTION
205
206 This module is the API you would normally use to send and receive sms messages.
207 It exports all the important  methods and hides some of the more complex things.
208 It needs a configuration file in it's constructor. The  configuration is transport specific but looks like:
209
210         [transportname]
211                 name = parameter
212             ...
213         [othertransport]
214                 name = parameter
215                 ...
216
217 Look into the transport.cfg files in the examples on how to set it up.
218
219 =head1 METHODS
220
221 =head2 new
222
223         my $nbs = GSM::SMS::NBS->new( $configfile );
224
225 This is the constructor, it expects a file name of a transport configuration as an argument.
226 All functions return -1 on failure, 0 on success.
227
228 =head2 sendSMSTextMessage
229
230         $nbs->sendSMSTextMessage( $msisdn, $msg, $multipart );
231
232 Send a text message ( $msg ) to the gsm number ( $msisdn ). If you set $multipart to true (!=0) the message will be split automatically in 160 char blocks. When $multipart is set to false it will be truncated at 160 characters.
233
234 =head2 sendRTTTL
235
236         $nbs->sendRTTTL( $msisdn, $rtttlstring );
237
238 Send a ringing tone ( $rtttlstring ) to the specified telephone number ( $msisdn ). The RTTTL ( Ringing Tone Tagged Text Language ) format is specified as described in the file rtttlsyntax.txt.
239
240 You can find a lot of information about RTTTL ( and a lot of ringing tones ) on the internet. Just point your favourite browser to your favourite searchengine and look for ringing tones.
241
242 =head2 sendGroupGraphic_b64
243
244         $nbs->sendGroupGraphic_b64( $msisdn, $b64, $format);
245
246 Send a group graphic, also called a Caller Line Identification icon ( CLIicon ),to the recipient indicated by the telephone number $msisdn. It expects a base 64 encoded image and the format the image is in, like 'gif', 'png'. To find out which image formats are supported, look at the superb package Image::Magick. The base 64 encoded image is just a serialisation of an image file, not of the image bitarray. The image is limited in size, it needs to be 71x14 pixels.
247 The base 64 encoding is used here because you maybe want to build a HTTP (XMLRPC ) gateway to send images. Without the _b64 method you would need to save the image file to disk and use the _file method, this is cumbersome ...
248 A group graphic is used to visually identify the group the caller belongs to. If you have a friend who calls you and his number is in the group 'friends', you probably would want to picture a pint of beer.
249
250 =head2 sendGroupGraphic_file
251
252         $nbs->sendGroupGraphic_file( $msisdn, $file);
253
254 Send a group graphic to $msisdn, use the image in file $file. The image must be 71x14 pixels. 
255
256 =head2 sendOperatorLogo_b64
257
258         $nbs->sendOperatorLogo_b64( $msisdn, $country, $operator, $b64, $format);
259
260 An operator logo indicates the operator you are connected to for the moment. This is used to have a nice logo on your telephone all of the time. I have also heard the term 'branding' overhere.
261 You also need to provide a country code and operator code. I have assembled some of these and you can find them in the file codes.txt. These files will move into a seperate package, because you can find the operator and country codes programatically by using the first n numbers of the msisdn.
262 The method expects a base64 serialised image and the format of the image, 'gif', 'png', next to the receiving telephone number ( $msisdn ) and the country and operator code.
263 The image needs to be 71x14 pixels.
264
265 =head2 sendOperatorLogo_file
266
267         $nbs->sendOperatorLogo_file( $msisdn, $country, $operator, $file );
268
269 Send an operator logo to $msisdn, using the image in file $file.
270
271 =head2 sendVCard
272
273         $nbs->sendVCard( $msisdn, $lastname, $firstname, $telephone );
274
275 A VCard is a small business card, containing information about a person. It is not a GSM only standard, netscape uses vcards to identify the mail sender ( attach vcard option ). You can look at the complete VCard MIME specification in RFC 2425 and RFC 2426.
276
277 =head2 sendConfig
278
279         $nbs->sendConfig( $msisdn, $bearer, $connection, $auth, $type, $speed, $proxy, $home, $uid, $pwd, $phone, $name);
280
281 Send a WAP configuration to a WAP capable handset. It expects the following parameters:
282
283         The parameters in UPPERCASE are exported constants by the GSM::SMS::OTA::COnfig.
284
285         $msisdn         Phonenumber recipient
286
287         $bearer         OTA_BEARER_CSD | OTA_BEARER_SMS
288
289                                 The carrier used ( circuit switched data or sms ), WAP is
290                                 independent of the underlying connectivity layer.
291
292         $connection     OTA_CONNECTIONTYPE_TEMPORARY
293                                 OTA_CONNECTIONTYPE_CONTINUOUS
294
295                                 You have to use continuous for CSD type of calls.
296
297         $auth           OTA_CSD_AUTHTYPE_PAP
298                                 OTA_CSD_AUTHTYPE_CHAP
299
300                                 Use PAP or CHAP as authentication type. A CSD call is just
301                                 a data call, and as such can use a normal dial-in point.
302
303         $type           OTA_CSD_CALLTYPE_ISDN
304                                 OTA_CSD_CALLTYPE_ANALOGUE
305                         
306         $speed          OTA_CSD_CALLSPEED_9600
307                                 OTA_CSD_CALLSPEED_14400
308                                 OTA_CSD_CALLSPEED_AUTO
309
310         $proxy          IP address of the WAP gateway to use.
311
312         $home           URL of the homepage for this setting. e.g.
313                                 http://wap.domain.com
314
315         $uid            Dial-up userid
316
317         $pwd            Dial-up password
318
319         $phone          Dial-up telephone number
320
321         $name           Nick name for this connection.                  
322                 
323         This feature has been tested on a Nokia 7110, but other Nokia
324         handsets are also supported.    
325
326 =head2 receive
327
328         $nbs->receive(  \$originatingaddress,
329                                         \$message,
330                                         \$timestamp,
331                                         \$transportname,
332                                         \$port,
333                                         $blocking
334                                 );
335
336 This method is used for implementing bidirectional SMS. With you can receive incoming messages. The only transport ( for the moment ) that can receive SMS messages is the Serial transport. 
337
338 The originatingaddress contains the sender msisdn number. 
339
340 The message contains the ( concatenated ) message. A NBS message can be larger than 140 bytes, so a UDP like format is used to send fragements. The lower layers of the GSM::SMS package take care of the SAR ( Segmentation And Reassembly ). 
341
342 The timestamp has the following format:
343
344         YYMMDDHHMMSSTZ
345
346         YY      :=      2 digits for the year ( 01 = 2001 )
347         MM      :=      2 digits for the month
348         DD      :=      2 digits for the day
349         HH      :=      2 digits for the hour
350         MM      :=      2 ditits for the minutes
351         SS      :=      2 digits for the seconds
352         TZ      :=  timezone 
353
354 Transportname contains the name of the transport as defined in the config file.
355
356 Port is the port number used to denote a specified service in the NBS stack.
357
358         my $originatingaddress;
359         my $message;
360         my $timestamp;
361         my $transportname;
362         my $port;
363         my $blocking = 1;
364
365         $nbs->receive(  \$originatingaddress,
366                                         \$message,
367                                         \$timestamp,
368                                         \$transportname,
369                                         \$port,
370                                         $blocking
371                                 );
372
373         print "I got a message from $originatingaddress\n";
374         
375 =head1 BUGS
376
377 Probably a lot. I hope to get some bug reports ...
378 One odd behaviour is that the CSCA is not always set correctly.
379 If receiving works, but sending not ( on the serial transport ),
380 then issue the next command to the modem in e.g. minicom.
381
382         AT+CSCA="+32475161616"
383         ( For belgian proximus ... look at your operator
384           for correct csca address ).
385
386 =head1 AUTHOR
387
388 Johan Van den Brande <johan@vandenbrande.com>