0

i am using c# API called EasySMPP, it is pretty great in sending single SMS, it is also good in send large SMS, but the recipient get the messages separately, which is not meaningful, what i am looking is how to modify the PDU so that i can append the UDH info.

How can i achieve adding a UHD info, here is the SubmitSM method from the API,

public int SubmitSM
(
byte sourceAddressTon, 
byte sourceAddressNpi, 
string sourceAddress,
byte destinationAddressTon,
byte destinationAddressNpi, 
destinationAddress, 
byte esmClass, 
byte protocolId,
byte priorityFlag, 
DateTime sheduleDeliveryTime, 
DateTime validityPeriod, 
byte registeredDelivery,
byte replaceIfPresentFlag,
byte dataCoding,
byte smDefaultMsgId,
byte[] message)

 {
 try
 {

                byte[] _destination_addr;
                byte[] _source_addr;
                byte[] _SUBMIT_SM_PDU;
                byte[] _shedule_delivery_time;
                byte[] _validity_period;
                int _sequence_number;
                int pos;
                byte _sm_length;

                _SUBMIT_SM_PDU = new byte[KernelParameters.MaxPduSize];

                ////////////////////////////////////////////////////////////////////////////////////////////////
                /// Start filling PDU                       

                Tools.CopyIntToArray(0x00000004, _SUBMIT_SM_PDU, 4);
                _sequence_number = smscArray.currentSMSC.SequenceNumber;
                Tools.CopyIntToArray(_sequence_number, _SUBMIT_SM_PDU, 12);


                pos = 16;
                _SUBMIT_SM_PDU[pos] = 0x00; //service_type
                pos += 1;
                _SUBMIT_SM_PDU[pos] = sourceAddressTon;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = sourceAddressNpi;
                pos += 1;
                _source_addr = Tools.ConvertStringToByteArray(Tools.GetString(sourceAddress, 20, ""));
                Array.Copy(_source_addr, 0, _SUBMIT_SM_PDU, pos, _source_addr.Length);
                pos += _source_addr.Length;
                _SUBMIT_SM_PDU[pos] = 0x00;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = destinationAddressTon;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = destinationAddressNpi;
                pos += 1;
                _destination_addr = Tools.ConvertStringToByteArray(Tools.GetString(destinationAddress, 20, ""));
                Array.Copy(_destination_addr, 0, _SUBMIT_SM_PDU, pos, _destination_addr.Length);
                pos += _destination_addr.Length;
                _SUBMIT_SM_PDU[pos] = 0x00;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = esmClass;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = protocolId;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = priorityFlag;
                pos += 1;
                _shedule_delivery_time = Tools.ConvertStringToByteArray(Tools.GetDateString(sheduleDeliveryTime));
                Array.Copy(_shedule_delivery_time, 0, _SUBMIT_SM_PDU, pos, _shedule_delivery_time.Length);
                pos += _shedule_delivery_time.Length;
                _SUBMIT_SM_PDU[pos] = 0x00;
                pos += 1;
                _validity_period = Tools.ConvertStringToByteArray(Tools.GetDateString(validityPeriod));
                Array.Copy(_validity_period, 0, _SUBMIT_SM_PDU, pos, _validity_period.Length);
                pos += _validity_period.Length;
                _SUBMIT_SM_PDU[pos] = 0x00;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = registeredDelivery;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = replaceIfPresentFlag;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = dataCoding;
                pos += 1;
                _SUBMIT_SM_PDU[pos] = smDefaultMsgId;
                pos += 1;

                _sm_length = message.Length > 254 ? (byte)254 : (byte)message.Length;

                _SUBMIT_SM_PDU[pos] = _sm_length;
                pos += 1;
                Array.Copy(message, 0, _SUBMIT_SM_PDU, pos, _sm_length);
                pos += _sm_length;

                Tools.CopyIntToArray(pos, _SUBMIT_SM_PDU, 0);

                Send(_SUBMIT_SM_PDU, pos);

                undeliveredMessages++;
                return _sequence_number;
            }
            catch (Exception ex)
            {
                logMessage(LogLevels.LogExceptions, "SubmitSM | " + ex.ToString());
            }
            return -1;

        }  

Thanks a lot!!!!

2 Answers2

0

As I can see, EasySMPP has option to split long text.

public int SendSms(String from, String to, bool splitLongText, String text, byte askDeliveryReceipt, byte esmClass, byte dataCoding)

Otherwise, smpp protocol has ability to do manually also. Either in SAR parameters:

SAR_MSG_REF_NUM - reference, unique to all sms parts
SAR_SEGMENT_SEQNUM - sequence number (1,2,3...)
SAR_TOTAL_SEGMENTS - number of all sequences

or you can encapsulate in the beggining of the message with UDHI set to 64

or you can set message in MESSAGE_PAYLOAD TLV and SMSC will do it for you.

Hope it helps

Marvin
  • 598
  • 5
  • 14
  • Thanks Marvin, the splitLongText parameter work in such a way that it only send the parts one by one, without merging them at destination. – henoke molla Mar 23 '18 at 12:09
  • How can i add the MESSAGE_PAYLOAD in PDU – henoke molla Mar 23 '18 at 12:11
  • This lib uses strange approach (like putting data in array) as SMPP protocol is TLV based (tag-length-value), which can be mandatory and optional, in any order and I doubt it support's it. Unfortunately I'm not much in C# to "patch" it. I would suggest you to google for better lib (e.g. smpp client c#) – Marvin Mar 23 '18 at 23:24
  • Thanks a lot Marvin, actually i managed to add the UDH data with the user data concatenated and set the esm_class to 0x40, and it works. – henoke molla Mar 24 '18 at 08:24
  • Cool, can you add solution here for the others :) – Marvin Mar 24 '18 at 10:29
  • Off course, just two things, first set ems_class=0x40, then set the first six bytes arrays with UDH data, for instance, 05-00-03-03-02-01. 05= length of the UDH, 00=concatination, 03=sequence no,02=No Of Parts, finally 01=first part no, this will become 02 for the second message, if you want the code please refer the next answer. – henoke molla Mar 26 '18 at 07:13
0

Here is the method where UDH is added.

public int SendSms(String from, String to,
bool splitLongText, String text,       
byte askDeliveryReceipt, 
 byte esmClass, byte dataCoding)
        {
 int messageId = -1;
            byte sourceAddressTon;
            byte sourceAddressNpi;
            string sourceAddress;
            byte destinationAddressTon;
            byte destinationAddressNpi;
            string destinationAddress;
            byte registeredDelivery;
            byte maxLength;

            sourceAddress = Tools.GetString(from, 20, "");
            sourceAddressTon = getAddrTon(sourceAddress);
            sourceAddressNpi = getAddrNpi(sourceAddress);

            destinationAddress = Tools.GetString(to, 20, "");
            destinationAddressTon = getAddrTon(destinationAddress);
            destinationAddressNpi = getAddrNpi(destinationAddress);

            registeredDelivery = askDeliveryReceipt;

            if (dataCoding == 8)
            {
               // text = Tools.Endian2UTF(text);
                maxLength = 70;
            }
            else
                maxLength = 160;

            if ((text.Length <= maxLength) || (splitLongText))
            {
                byte protocolId;
                byte priorityFlag;
                DateTime sheduleDeliveryTime;
                DateTime validityPeriod;
                byte replaceIfPresentFlag;
                byte smDefaultMsgId;
              //  byte[] message = new byte[146];
                byte[] udh = new byte[6];
                string smsText = text;
                byte[] message;
                protocolId = 0;
                priorityFlag = PriorityFlags.VeryUrgent;
                sheduleDeliveryTime = DateTime.MinValue;
                validityPeriod = DateTime.MinValue;
                replaceIfPresentFlag =   
               ReplaceIfPresentFlags.DoNotReplace;
                 smDefaultMsgId = 0;
                if (dataCoding == 8)
                {
                    message = new byte[70];
                }
                else
                {
                     message = new byte[146];
                }

                string[] lists = dataCoding == 8 ?                             
                 split_message_unicode(text) : 
                 split_message_asci(text);


                int count = 1;
                foreach (string s in lists)
                {
                    Array.Clear(message, 0, message.Length);
                  //  while (smsText.Length > 0)
                   // {
                        int pos = 0;
                       // byte desc = Convert.ToByte('c');

                        byte headerLen = Convert.ToByte(05);
                        byte concat = Convert.ToByte(00);
                        byte refNo = Convert.ToByte(03);
                        byte sequenceNo = Convert.ToByte(03);
                        byte NoOfMessages = Convert.ToByte(lists.Length);
                        byte partNo = Convert.ToByte(count);
                        count++;


                        udh[pos] = headerLen;
                        pos++;
                        udh[pos] = concat;
                        pos++;
                        udh[pos] = refNo;
                        pos++;
                        udh[pos] = sequenceNo;
                        pos++;
                        udh[pos] = NoOfMessages;
                        pos++;
                        udh[pos] = partNo;
                        pos++;

                        Array.Copy(udh, 0, message, 0, pos);

                        if (dataCoding == 8)
                        {
                            int len = Tools.GetEthiopic(s).Length;
                            Array.Copy(Tools.GetEthiopic(s), 0, message,  
       pos, len);
                            //message = 
          Tools.GetEthiopic(smsText.Substring(0, smsText.Length > 
        maxLength ? maxLength : smsText.Length));
                            //message = 
       Encoding.UTF8.GetBytes(smsText.Substring(0, smsText.Length > 
         maxLength ? maxLength : smsText.Length));
                        }
                        else{
                           // message = Encoding.ASCII.GetBytes(s);
                            Array.Copy(Encoding.ASCII.GetBytes(s), 0, 
           message, pos, Encoding.ASCII.GetBytes(s).Length);
                        }
                        smsText = smsText.Remove(0, smsText.Length > 
             maxLength ? maxLength : smsText.Length);


                        messageId = SubmitSM(sourceAddressTon, 
       sourceAddressNpi, sourceAddress,
                                            destinationAddressTon, 
         destinationAddressNpi, destinationAddress,
                                            esmClass, protocolId, 
        priorityFlag,
                                            sheduleDeliveryTime, 
       validityPeriod, registeredDelivery, replaceIfPresentFlag,
                                            dataCoding, smDefaultMsgId, 
             message);


                  //  }
                }

            }
            else
            {
                byte[] data;

                if (dataCoding == 8)
                    data = Tools.GetEthiopic(text);
                    //data = Encoding.UTF8.GetBytes(text);
                else
                    data = Encoding.ASCII.GetBytes(text);
                messageId = DataSM(sourceAddressTon, sourceAddressNpi, 
         sourceAddress,
                                    destinationAddressTon, 
         destinationAddressNpi, destinationAddress,
                                    esmClass, registeredDelivery, 
           dataCoding, data);
            }
            return messageId;
             }

pass ems_class as 0x40, what you need to to is just to split your message in to parts, here is splitting method,

       private string[] split_message_asci(string message)
        {
            int message_len = message.Length;
            decimal val=(message.Length / 140m);
            decimal parts = Math.Ceiling(val);
            string[] strs = new string[(int)parts];
            string str = string.Empty;
            int interval=140;
            int i =0;
            int Count= 0;
            while (i < message_len)
            {
                if (Count < (int)parts-1)
                {
                    str = message.Substring(i, interval);
                    strs[Count] = str;
                    i += interval ;
                }
                else
                {
                    str = message.Substring(i, message_len-i);
                    strs[Count] = str;
                    i += interval + 1;
                }

                Count++;
            }

            return strs;
        }