futomi / node-sms-pdu

The node-sms-pdu is a SMS-SUBMIT PDU (Packet Data Unit) generator and SMS-SUBMIT/DELIVER PDU parser. This module supports the GSM 7-bit default alphabet encoding and the UCS-2 16-bit alphabet encoding. Besides, it supports the Concatenated (or Multipart or Long) SMS.
MIT License
16 stars 6 forks source link

node-sms-pdu

The node-sms-pdu is a SMS-SUBMIT PDU (Packet Data Unit) generator and SMS-SUBMIT/DELIVER PDU parser. This module supports the GSM 7-bit default alphabet encoding and the UCS-2 16-bit alphabet encoding. Besides, it supports the Concatenated (or Multipart or Long) SMS.

Dependencies

Installation

$ cd ~
$ npm install node-sms-pdu

Table of Contents


Quick Start

Generating a SUBMIT-PDU for English text

The sample code below generates a list of PDUs.

const smsPdu = require('node-sms-pdu');

const number = '09012345678'; // Telephone number (in this case, national number)
const text = 'How are you doing?'; // Text

const pdu_list = smsPdu.generateSubmit(number, text);
console.log(pdu_list);

The code above will output the result as follows:

[
  {
    buffer: <Buffer 00 01 00 0b ...>,
    hex: '0001000B819010325476F8000012C8F71D14969741F9771D447EA7DDE71F',
    length: 29,
    encoding: 'gsm'
  }
]

Generating a SUBMIT-PDU for multi-byte characters

This module supports multi-byte characters. The code below, the text is Japanese "こんにちわ" which means "Hello":

const pdu_list = smsPdu.generateSubmit('09012345678', 'こんにちわ');
console.log(pdu_list);

The code above will output the result as follows:

[
  {
    buffer: <Buffer 00 01 00 0b ...>,
    hex: '0001000B819010325476F800080A30533093306B3061308F',
    length: 23,
    encoding: 'ucs2'
  }
]

Generating a SUBMIT-PDU for long text

Most of telecom carriers in the world supports long SMS messages. Technically, a long SMS message is divided into some short messages with an additional information in a packet.

This module supports a long SMS message.

// Long text
// - Quoted from Wikipedia (https://en.wikipedia.org/wiki/SMS)
const text = 'SMS (short message service) is a text messaging service component of most telephone, Internet, and mobile device systems. It uses standardized communication protocols to enable mobile devices to exchange short text messages. An intermediary service can facilitate a text-to-voice conversion to be sent to landlines.'

const pdu_list = smsPdu.generateSubmit('09012345678', text);
console.log(pdu_list);

The code above will output the result as follows:

[
  {
    buffer: <Buffer 00 41 00 0b ...>,
    hex: '0041000B819010325476F80000A0050003000301A6CD29083547BFE57450BB...',
    length: 153,
    encoding: 'gsm'
  },
  {
    buffer: <Buffer 00 41 00 0b ...>,
    hex: '0041000B819010325476F80000A0050003000302D26F37082E7FD3DFE3377B...',
    length: 153,
    encoding: 'gsm'
  },
  {
    buffer: <Buffer 00 41 00 0b ...>,
    hex: '0041000B819010325476F8000010050003000303C26E323BED2ECF5D',
    length: 27,
    encoding: 'gsm'
  }
]

SmsPdu object

Creating SmsPdu object

In order to use this module , you have to get the SmsPdu object loading this module as follows:

const smsPdu = require('node-sms-pdu');

In the code snippet above, the variable smsPdu is a SmsPdu object. For now, the SmsPdu object has only generateSubmit() method as described in sections below.

generateSubmit() method

The generateSubmit() method generates PDUs from the specified telephone number and message text. This method takes up to 3 arguments. The first one is a telephone number, the second one is a message text, the 3rd argument is an object containing option parameters.

const pdu_list = smsPdu.generateSubmit('09012345678', 'Howdy');
No. name Type Required Description
1 Telephone number String Required This module supports not only national number but also international number. If you want to specify an international number, the number must start with +. For example, if the national number is 09012345678, then the international number must be +819012345678. In this case, +81 is a country dial-in codes, which means Japan, 9012345678 is the national number.
2 Message Text String Required This module supports multi-byte characters.
3 Options Object Optional See the description below.

You can specify the encoding in the 3rd argument as follows:

const pdu_list = smsPdu.generateSubmit('09012345678', 'Howdy', { encoding: 'ucs2' });

The encoding must be "gsm" or "ucs2". Basically, you do not have to use this option because this module determines the proper encoding automatically.

This method returns an Array object containing generated PDU data as follows:

[
  {
    buffer: <Buffer 00 01 00 0b ...>,
    hex: '0001000B819010325476F8000012C8F71D14969741F9771D447EA7DDE71F',
    length: 29,
    encoding: 'gsm'
  }
]

Each element in the Array object consists of the properties as follows:

Property Type Description
buffer Buffer Buffer object of the generated PDU
hex String Hexadecimal string of the generated PDU
length Integer Byte length (see the description below in details)
encoding String "gsm" or "ucs2" (see the description below in details)

If the specified message text cannot be encoded into one packet (i.e., it cannot be encoded to within 140 bytes), this method automatically divides the message into some PDUs.

The length is the byte length of the generated PDU excluding the SMSC (Short Message Service Center) field. Note that this value is not the byte length of the generated PDU itself. The SMSC field is always 0x00 (1 byte). Therefore, the value of the length is always the length of the generated PDU minus 1. The value of the length is used in AT commands to control LTE/3G modems.

The encoding indicates the character encoding. The value can be "gsm" or "ucs2". The "gsm" means "GSM 7-bit default alphabet and extension". The "ucs2" means "16-bit alphabet (UCS-2)". Though 3GPP TS 23.041 (GSM 03.41) specification allows 8-bit alphabet, this module does not support it for now.

This method automatically determines the appropriate encoding. If you want to force your preferred encoding, you can specify the encoding to this method. If the message text cannot be encoded to the specified encoding, this method throws an exception.

parse() method

This method parses the specified SMS-SUBMIT/DELIVER PDU data. The PDU data must be a HEX string or a Buffer object.

const data = smsPdu.parse('0001000B818080674523F1000005C8F79D9C07');
console.log(JSON.stringify(data, null, ' '));

The code above parses a SMS-SUBMIT PDU. It will output the result as follows:

{
  "smsc": null,
  "type": "SMS-SUBMIT",
  "reference": 0,
  "destination": "08087654321",
  "period": null,
  "concat": null,
  "text": "Howdy"
}

Let's see another example:

const data = smsPdu.parse('0891180978563412F0040B809010325476F80008022031611463630A30533093306B3061306F');
console.log(JSON.stringify(data, null, ' '));

The code above parses a SMS-DELIVER PDU. It will output the result as follows. (In this case, the SMS message is Japanese text which means "Hello".)

{
  "smsc": "+8190876543210",
  "type": "SMS-DELIVER",
  "origination": "09012345678",
  "timestamp": "2020-02-13T16:41:36+09:00",
  "concat": null,
  "text": "こんにちは"
}

As you can see the above examples, the items in the results are different depending on the message type.

Common items

Property Type Description
smsc String SMSC address. In the case of SMS-SUBMIT, this value is always null.
type String Message type. The value is "SMS-SUBMIT" or "SMS-DELIVER".
concat Object Concatenated SMS (CSMS) information. If no infomation exists in the PDU, this value will be null.
    reference Integer CSMS reference number.
    total Integer Total number of parts.
    sequence Integer This part's number in the sequence.
text String SMS text.

SMS-SUBMIT specific items

Property Type Description
reference Integer Message reference Number
destination String Destination address (phone number).
period String Validity period. If the value is "4d", it means 4 days. The unit could be "m" (minutes), "d" (days), "w" (weeks). If no validity period information exists in the PDU, this value will be null.

SMS-DELIVER specific items

Property Type Description
origination String Origination address (phone number).
timestamp String Time stamp.

Parse error

If the PDU data passed to this method is invalid or this method fails to parse the PDU data, this method returns an object containing the error property. The value of the error property is an Error object. Note that this method does not throw an exception.

const data = smsPdu.parse('0002000B818080674523F1000005C8F79D9C07');
if(data.error) {
  console.log(error.message);
} else {
  console.log(JSON.stringify(data, null, ' '));
}

The code above will output an error message as follows:

The message type is not supported: MTI=2

Technical Note

Character encodings and packet size

This module supports "GSM 7-bit default alphabet and extension" and "16-bit alphabet (UCS-2)" as an character encoding. These encodings are specified in the GSM 03.38.

The "GSM 7-bit default alphabet and extension" can express ASCII characters and some Greek alphabets. Each character is encoded to a 7-bit chunk which is called "septet". Therefore, a SMS message can carry up to 160 characters in theory (7 bits * 160 characters = 1,120 bits = 140 bytes). But some characters consume 2 septets each, which are defined as the extension. For example, {, }, [, ], |, ^ are defined as the extension. If these characters are used in the message text, a SMS message can carry less than 160 characters.

On the other hand, text messages including multi-byte characters, such as Japanese and Chinese and so on, are encoded to UCS-2. All characters are encoded to 2 bytes each. Therefore, a SMS message can carry up to 70 characters. Note that even ASCII characters are encoded to 2 bytes each.

Concatenated SMS

In recent years, many telecom carriers in the world supports Concatenated SMS (a.k.a. Multipart SMS, Long SMS).

The mechanism of the Concatenated SMS is simple. A long message are divided into some SMS messages so that the byte length of each message is less than 140 bytes. 3GPP specification allows up to 255 segmentations. But the limit depends on each telecom carrier and terminal device.

When a long message are divided into some segments, each segment requires 6 bytes for segmentation information in a message data payload, which is called UDH (User Data Header). That is, in the case of GSM 7-bit encoding, 7 septets (characters) are lost in each SMS message due to UDH. Each SMS message can carry up to 153 characters. In the case of UCS-2 16-bit encoding, 3 characters are lost in each SMS message due to UDH, each SMS message can carry up to 67 characters.


Release Note


References


License

The MIT License (MIT)

Copyright (c) 2020 Futomi Hatano

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.