GSM 03.38 support

Smpp v3.4 client

Moderator: alt

Locked
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

GSM 03.38 support

Post by BenEllis » Tue Nov 10, 2009 3:14 pm

Is there support for GSM 03.38 encoding or do I need to write my own?
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

GSM 03.38 / ASCII Support

Post by BenEllis » Wed Nov 11, 2009 12:53 pm

Nevermind, wrote my own. Works a charm :)
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

Post by BenEllis » Wed Nov 11, 2009 1:00 pm

Use the below function to generate your ShortMessageBytes and change the DataEncoding to ASCII (GSM03.3.)

[Edit: Added § to the encoding algorithm as it was missing.]

i.e.

Code: Select all

req.ShortMessageBytes = GSMEncode("!£$%^&*()€"); 

        public static byte[] GSMEncode(string PlainText)
        {
            // ` is not a conversion, just a untranslatable letter.
            // x0D should be CR but this causes double linefeed on
            // some phones so has been removed.
            const string strGSMTable =
            "@£$¥èéùìòÇ\nØø`Åå" +
            "Δ_ΦΓΛΩΠΨΣΘΞ`ÆæßÉ" +
            " !\"#¤%&'()*+,-./" +
            "0123456789:;<=>?" +
            "¡ABCDEFGHIJKLMNO" +
            "PQRSTUVWXYZÄÖÑܧ" +
            "¿abcdefghijklmno" +
            "pqrstuvwxyzäöñüà";

            const string strExtendedTable =
            "````````````````" +
            "````^```````````" +
            "````````{}`````\\" +
            "````````````[~]`" +
            "|```````````````" +
            "````````````````" +
            "`````€``````````" +
            "````````````````";

            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                foreach (char cPlainText in PlainText.ToCharArray())
                {
                    if (cPlainText != '`')  // Ignore `
                    {
                        int intGSMTable = strGSMTable.IndexOf(cPlainText);
                        if (intGSMTable != -1)
                        {
                            ms.WriteByte((byte)intGSMTable);
                            continue;
                        }
                        int intExtendedTable = strExtendedTable.IndexOf(cPlainText);
                        if (intExtendedTable != -1)
                        {
                            ms.WriteByte(27);
                            ms.WriteByte((byte)intExtendedTable);
                        }
                    }
                }

                ms.Close();
                return ms.ToArray();
            }
        }
Last edited by BenEllis on Thu Dec 10, 2009 9:20 am, edited 1 time in total.
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

Post by BenEllis » Wed Nov 11, 2009 3:30 pm

To use in concatenate messages,

// Encode as GSM 03.38
byte[] data = GsmEncode(/* Plain Text */);

List<SubmitSm> reqs = new List<SubmitSm>();

// If message needs to be concatenated (140 bytes (160 Gsm characters))
if (data.Length > 160)
{
byte concatMsgRef = // Generate new unique concatMsgRef here (0/1-255) for each long message you send. Once the operation is complete you can re-use the same id again.
byte seqNum = 0;
const int concatPartLength = 153;
int bytes = data.Length;
while (bytes > 0)
{
// Create Message
SubmitSm req = new SubmitSm(/* Service Type */, /* Source TON */, /* Source NPI */, /* Source Address*/, /* Dest TON */, /* Dest NPI */, /* Dest Addr */);

// Load Data
req.DataCoding = DataCodings.ASCII;
int bytesLeft = data.Length - bytes;
byte[] toSend = new byte[concatPartLength < bytes ? concatPartLength : bytes];
for (int i = 0; i < toSend.Length; i++)
toSend = data[bytesLeft + i];
req.UserDataPdu.Headers.AddConcatenatedShortMessages8bit(concatMsgRef, (byte)((data.Length / concatPartLength) + 1), ++seqNum);
int r = req.UserDataPdu.Headers[0].Length;
req.UserDataPdu.ShortMessage = toSend;
reqs.Add(req);

bytes = bytes - concatPartLength;
}
}
else
{
SubmitSm req = new SubmitSm(/* Service Type */, /* Source TON */, /* Source NPI */, /* Source Address*/, /* Dest TON */, /* Dest NPI */, /* Dest Addr */);
req.DataCoding = DataCodings.ASCII;
req.ShortMessageBytes = data;
reqs.Add(req);
}

SubmitSmResp[] resps = client.Submit(reqs.ToArray());
rudolfix
Posts: 2
Joined: Wed Dec 09, 2009 3:46 pm

Post by rudolfix » Wed Dec 09, 2009 3:57 pm

Hi

I also had to write my own GSM encoding. It is a shame it is not implemented int the library.
Unfortunately incoming SMSes are not decoded properly as well. Plain ASCII.GetBytes() is used.
Do you maybe have a decoder part ready and can share the code?
Thank you!

r.
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

Post by BenEllis » Wed Dec 09, 2009 4:11 pm

Is this what you need?

I've not tested it, but it's just the reverse of the encoder algorithm.

[Edit: Changed second line feed to carrier return.]
[Edit: § was not decoding, added § at 97 (0x5F)]

Code: Select all

public static string GsmDecode(byte[] encodedData)
        {
            // ? is not a conversion, just a untranslatable letter.
            const string gsmTable =
            "@£$¥èéùìòÇ\nØø\rÅå" +
            "Δ_ΦΓΛΩΠΨΣΘΞ`ÆæßÉ" +
            " !\"#¤%&'()*+,-./" +
            "0123456789:;<=>?" +
            "¡ABCDEFGHIJKLMNO" +
            "PQRSTUVWXYZÄÖÑܧ" +
            "¿abcdefghijklmno" +
            "pqrstuvwxyzäöñüà";

            const string extendedTable =
            "????????????????" +
            "????^???????????" +
            "????????{}?????\\" +
            "????????????[~]?" +
            "|???????????????" +
            "????????????????" +
            "?????€??????????" +
            "????????????????";

            StringBuilder retVal = new StringBuilder();

            for (int i = 0; i < encodedData.Length; i++)
            {
                // if escape code,
                if (encodedData[i] == 27)
                {
                    retVal.Append(extendedTable[encodedData[++i]]);
                }
                else
                {
                    retVal.Append(gsmTable[encodedData[i]]);
                }
            }

            return retVal.ToString();
        }
Last edited by BenEllis on Thu Dec 10, 2009 9:19 am, edited 1 time in total.
rudolfix
Posts: 2
Joined: Wed Dec 09, 2009 3:46 pm

Post by rudolfix » Wed Dec 09, 2009 5:26 pm

Hi

It works perfectly, I was able to encode to whole gsm alphabet with my encoder and decode with yours.

The only thing I've found is most probably an effect of copy and paste of source code: the gsm character with code 95 (§ - paragraph sign) appears in your gsmTable as `.

so line
"PQRSTUVWXYZÄÖÑÜ`" +
should be
"PQRSTUVWXYZÄÖÑܧ" +

But as I said - it is most probably an copy-paste error

Thanks!
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

Post by BenEllis » Thu Dec 10, 2009 9:17 am

Not a copy and paste error. It's missing in my encode code too. I'll edit the code, thanks for spotting it.
alt
Site Admin
Posts: 988
Joined: Tue Apr 25, 2006 9:45 am

Post by alt » Wed Dec 16, 2009 4:03 pm

In version 2.8 I'm going to implement GSMEncoding class.

But problem that several SMSC work in different ways.

For Default SMSC coding (0x0) i know three ways
- plain ASCII
- unpacked GSM 03.38
- packed 7bit GSM 03.38

Would be good if all readers post here information about a way which their SMSC use for default coding and what vendor name SMSC has.
BenEllis
Posts: 21
Joined: Mon Nov 09, 2009 4:30 pm
Location: Leicester, United Kingdom
Contact:

Default Encodings for mBlox and Sybase

Post by BenEllis » Thu Dec 17, 2009 9:11 am

We use mBlox and Sybase as SMSC.

mBlox uses default of Latin-1 encoding, but if you set encoding to ASCII/GSM they expect unpacked GSM 03.38 encoded data.

I'm unsure what default Sybase use, but for ASCII/GSM encoding they again expect unpacked GSM 03.38 encoded data.

This confused me for a long time because I wrote some code to pack the 7bit data and they weren't decoding it correctly. Eventually I realized they wanted unpacked :P
Locked