View Javadoc
1   /*
2    * To change this template, choose Tools | Templates
3    * and open the template in the editor.
4    */
5   package net.sf.atmodem4j.core.gsm;
6   
7   /*
8    * #%L
9    * ATModem4J Core
10   * %%
11   * Copyright (C) 2009 - 2014 atmodem4j
12   * %%
13   * atmodem4j - Drivers for the AT modem - http://atmodem4j.sourceforge.net/
14   * Copyright (C) 2009-2014, atmodem4j.sf.net, and individual contributors as indicated
15   * by the @authors tag. See the copyright.txt in the distribution for a
16   * full listing of individual contributors.
17   * 
18   * This is free software; you can redistribute it and/or modify it
19   * under the terms of the GNU General Public License as
20   * published by the Free Software Foundation; either version 3 of
21   * the License, or (at your option) any later version.
22   * 
23   * This software is distributed in the hope that it will be useful,
24   * but WITHOUT ANY WARRANTY; without even the implied warranty of
25   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26   * Lesser General Public License for more details.
27   * 
28   * You should have received a copy of the GNU Lesser General Public
29   * License along with this software; if not, write to the Free
30   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
31   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
32   * #L%
33   */
34  
35  import java.util.ArrayList;
36  import java.util.List;
37  import net.sf.atmodem4j.core.gsm.Pdu.Encoding;
38  import net.sf.atmodem4j.core.gsm.Pdu.TimeToLife;
39  
40  /**
41   *
42   * @author aploese
43   */
44  public class PduEncoder {
45  
46      private final static int USER_DATA_HEADER_LENGTH = 6;
47      public static final int MAX_USER_PDU_SIZE = 140;
48  
49      private List<UserData> data = new ArrayList<UserData>();
50  
51      private String receiverPhonenumber;
52      private Encoding encoding;
53      private TimeToLife timeToLife;
54      private int refnumber;
55  
56      public PduEncoder() {
57          super();
58      }
59  
60      private String getSmscInformationOctet() {
61          return "00";
62      }
63  
64      public boolean isMultiSMS() {
65          return data.size() > 1;
66      }
67  
68      private String getSmsSubmittOctet() {
69          short result = 0x11;
70          result |= isMultiSMS() ? 0x40 : 0;
71          return UserData.formatOctet(result);
72      }
73  
74      private String getTpMessageReferenceOctet() {
75          return "00";
76      }
77  
78      private String getAdressOctets() {
79          StringBuilder sb = new StringBuilder();
80          String number = receiverPhonenumber.charAt(0) == '+' ? receiverPhonenumber.substring(1, receiverPhonenumber.length())
81                  : receiverPhonenumber;
82          sb.append(UserData.formatOctet(number.length()));
83          if (receiverPhonenumber.charAt(0) == '+') {
84              sb.append("91"); //  International address;
85          } else {
86              sb.append("91"); //  TODO address;
87          }
88          for (int i = 0; i < number.length() - 1; i += 2) {
89              sb.append(number.charAt(i + 1));
90              sb.append(number.charAt(i));
91          }
92          if (number.length() % 2 != 0) {
93              sb.append("F");
94              sb.append(number.charAt(number.length() - 1));
95          }
96          return sb.toString();
97      }
98  
99      private String getTpPidOctet() {
100         return "00";
101     }
102 
103     private String getTpDcsOctet() {
104         switch (encoding) {
105             case TEXT_7BIT:
106                 return "00";
107             case TEXT_16BIT:
108                 return "08";
109             case DATA_8BIT:
110                 return "04";
111             default:
112                 return "00";
113         }
114     }
115 
116     private String getTpValidityPeriodOctet() {
117         return "AA";
118     }
119 
120     private String getMultiSMSUserHeader(int length, int index) {
121         StringBuilder sb = new StringBuilder();
122         sb.append("05"); //Length of user data header
123         sb.append("00"); //Inicator: Concatentiated short message 8 Bit ref number
124         sb.append("03"); //length alway 3
125         sb.append(UserData.formatOctet(refnumber++)); // Concatenated short message reference number
126         if (refnumber > 255) {
127             refnumber = 0;
128         }
129         sb.append(UserData.formatOctet(length));
130         sb.append(UserData.formatOctet(index));
131         return sb.toString();
132     }
133 
134     public String[] encodePdus() {
135         StringBuilder sb = new StringBuilder();
136         if (isMultiSMS()) {
137 //Multi SMS
138             String[] result = new String[data.size()]; // subtract user header
139             for (int i = 0; i < result.length; i++) {
140                 sb.append(getSmscInformationOctet());
141                 sb.append(getSmsSubmittOctet());
142                 sb.append(getTpMessageReferenceOctet());
143                 sb.append(getAdressOctets());
144                 sb.append(getTpPidOctet());
145                 sb.append(getTpDcsOctet());
146                 sb.append(getTpValidityPeriodOctet());
147                 sb.append(UserData.formatOctet(data.get(i).getUserDataLength(USER_DATA_HEADER_LENGTH)));
148                 sb.append(getMultiSMSUserHeader(data.size(), i +1));
149                 sb.append(data.get(i).encodePduData(USER_DATA_HEADER_LENGTH));
150                 result[i] = sb.toString();
151                 sb.delete(0, sb.length());
152             }
153             return result;
154         } else {
155 //Single SMS
156             sb.append(getSmscInformationOctet());
157             sb.append(getSmsSubmittOctet());
158             sb.append(getTpMessageReferenceOctet());
159             sb.append(getAdressOctets());
160             sb.append(getTpPidOctet());
161             sb.append(getTpDcsOctet());
162             sb.append(getTpValidityPeriodOctet());
163             sb.append(UserData.formatOctet(data.get(0).getUserDataLength(0)));
164             sb.append(data.get(0).encodePduData(0));
165             return new String[]{sb.toString()};
166         }
167     }
168 
169     /**
170      * @return the messageText
171      */
172     public String getMessageText() {
173         return null;
174     }
175 
176     /**
177      * @param messageText the messageText to set
178      */
179     public void setMessageText(Encoding enc, String messageText) throws
180             Pdu.EncodingException {
181         this.encoding = enc;
182         switch (encoding) {
183             case TEXT_7BIT:
184                 int lastPos = 0;
185                 for (int pos : UserData.Text7Bit.getSplitPos(messageText)) {
186                     UserData.Text7Bit ud = new UserData.Text7Bit();
187                     ud.setText(messageText.substring(lastPos, pos));
188                     lastPos = pos;
189                     data.add(ud);
190                 }
191                 break;
192             case TEXT_16BIT:
193                 for (UserData ud : UserData.Text16Bit.split(messageText)) {
194                     data.add(ud);
195                 }
196                 break;
197             default:
198                 DATA_8BIT:
199                 throw new RuntimeException("Cant encode Data as String");
200         }
201     }
202 
203     /**
204      * @param messageText the messageText to set
205      */
206     public void setMessageText(String messageText) {
207         try {
208             setMessageText(Encoding.TEXT_7BIT, messageText);
209         } catch (Pdu.EncodingException ex) {
210             try {
211                 setMessageText(Encoding.TEXT_16BIT, messageText);
212             } catch (Pdu.EncodingException ex16) {
213                 throw new RuntimeException(ex16);
214             }
215         }
216     }
217 
218     /**
219      * @return the receiverPhonenumber
220      */
221     public String getReceiverPhonenumber() {
222         return receiverPhonenumber;
223     }
224 
225     /**
226      * @param receiverPhonenumber the receiverPhonenumber to set
227      */
228     public void setReceiverPhonenumber(String receiverPhonenumber) {
229         this.receiverPhonenumber = receiverPhonenumber;
230     }
231 
232     /**
233      * @return the refnumber
234      */
235     public int getRefnumber() {
236         return refnumber;
237     }
238 
239     /**
240      * @param refnumber the refnumber to set
241      */
242     public void setRefnumber(int refnumber) {
243         this.refnumber = refnumber;
244     }
245 }