Thales' cellular IoT products business is now part of Telit Cinterion, find out more.

You are here

Telit Cinterion IoT Developer Community

How to receive the SMS message

Tutorial, January 27, 2014 - 7:21pm, 26043 views

Experience Level:
Basic

Motivation/Description
Learn how to receive text messages with a Cinterion® Java Module.

Covered topics

•    SMS related commands
•    Text mode
•    PDU (Protocol Data Unit) mode
•    Sending AT commands
•    URC (Unsolicited Result Code) receiving

Keywords/Tags

sms, text message, short message, message, registration, at command, creg, cmgf, cmgd, cmgr, delete, remove, read, urc, cnmi, storage

Scenario

  • Create  an ATCcommand object
  • Check the network registration status
  • Switch to text mode
  • Create the ATCommandListener
  • Add the listener to an ATCommand object
  • Enable the SMS related URCS
  • Search for the CNMI in the URCs
  • Read the incoming text message
  • Delete old text messages

Prerequisites

  • IDE (this tutorial uses Eclipse as an IDE)
  • EHS5/EHS6/TC65i/EGS5/ConceptBoard
  • SIM card

Actual Tutorial

When talking about GSM modules, one of the first ideas was to control a device via text messages. There are already plenty of devices which provide such a feature. Banks are often building their security mechanisms on SMS (Short Message Service). People can control single power sockets at home, remotely via their mobiles, and the whole building alarm system as well.

See how you can receive text messages on a Gemalto Java Module and use it as an input to your application.

import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;

import com.cinterion.io.ATCommand;
import com.cinterion.io.ATCommandListener;

public class SmsReceiver extends MIDlet {

	private ATCommand atc;

	public SmsReceiver() {
		// TODO Auto-generated constructor stub
	}

	protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
		System.out.println("SmsReceiver stopped");
		notifyDestroyed();
	}

	protected void pauseApp() {
		// TODO Auto-generated method stub

	}

	protected void startApp() throws MIDletStateChangeException {
		System.out.println("SmsReceiver started");

		try {
			// create an instance of ATCommand
			atc = new ATCommand(false);

			// check the registration
			boolean registered = false;

			while (registered == false) {

				String registration_response = atc.send("AT+CREG?\r");

				int localy_registered = registration_response.indexOf(",1");
				int roaming_registered = registration_response.indexOf(",5");

				if ((localy_registered > -1) || (roaming_registered > -1)) {
					registered = true;
					System.out.println("Module registered to the network");
				} else {
					System.out.println("Module not registered to the network");
				}

				Thread.sleep(2000);
			}

			// create the AT command listener

			ATCommandListener listener = new ATCommandListener() {

				public void RINGChanged(boolean SignalState) {
				}

				public void DSRChanged(boolean SignalState) {
				}

				public void DCDChanged(boolean SignalState) {
				}

				public void CONNChanged(boolean SignalState) {
				}

				public void ATEvent(final String Event) {

					System.out.println("received URC: " + Event);

					// search for SMS related URCs
					if (Event.indexOf("+CMTI") > 0) {

						String content = getSmsContent(Event, false);
						System.out.println("Sms content: " + content);

					}

				}
			};

			// add (activate) the listener
			atc.addListener(listener);

			// switch to the text mode
			System.out.println(atc.send("at+cmgf=1\r"));
			
			// activate the SMS URCs
			System.out.println(atc.send("at+cnmi=2,1\r"));

		} catch (Exception e) {
			e.printStackTrace();
		}

		destroyApp(true);
	}

	private String getSmsContent(String arg0, boolean deleteSms) {

		// index of received SMS message in the memory
		int idx = arg0.indexOf(",");
		String sms_positionInMemory = arg0.substring(idx + 1, idx + 3);

		// get the SMS content
		String contentOfSms = "";
		try {

			// get the message from the index position
			String response = atc.send("AT+CMGR=" + sms_positionInMemory + "\r");

			System.out.println(response);

			// delete the SMS
			if (deleteSms){
				atc.send("AT+CMGD=" + sms_positionInMemory + "\r");
			}

		} catch (Exception e) {
			e.printStackTrace();
			contentOfSms = null;
		}

		return contentOfSms;
	}

}

Create an ATCommand object

Since text messages are sent via AT commands, you will need to create an ATCommand object. It will give you access to the module’s command interpreter.

Use one of the ATCommand constructors. Because we will not use the CSD (Circuit Switched Data) on this object, you should set the constructor parameter (csdSupport) to false.

 atc = new ATCommand(false); 

Make sure the module is registered to the network

To receive the text messages the module ***** to be registered to a network. You can simply check this using the AT+CREG? command. The response should contain “+CREG: 0,1” or, in case of roaming “+CREG: 0,5”. Other values indicate that the module is not registered.

To check the registration status withJava you need to send the +CREG? command and parse the response. More detailes about the AT+CREG command you can find in the AT command specification (Chapter 8.5).

String registration_response = atc.send("AT+CREG?\r");
	
int localy_registered = registration_response.indexOf(",1");
int roaming_registered = registration_response.indexOf(",5");
		
if((localy_registered >-1 ) || (roaming_registered >-1)){
	System.out.println("Module registered to the network");
}else{
	System.out.println("Module not registered to the network");
}

If you are not sure how to register to a network, or want to get more information regarding this procedure, please check our How to register to the network tutorial.

Switch to text mode

Now we will be able to make use of the SMS feature. First, you need to know, that there are two modes of receiving the Short Messages.

Text    displays the text message as simple string

PDU    for advanced usage; displays the SMS in the hexadecimal octets

Since the PDU mode, comparing to the text mode, is really complex– we will present the text mode.

The module by default is in PDU mode. To change this you need to send the AT+CMGF=1 command.

 String at_cmd_response = atc.send("AT+CMGF=1\r"); 

The value ´1´ stands for text mode. You may verify if the command was executed properly, by checking if it‘s response contains „OK“.

If the command was invoked properly the current AT command interpreter will be in text mode. It means that now when you receive a text message you will be able read its body message by a single command. In PDU mode you would need to decode it from the hexadecimal octets.

But before you can read the text message from the module’s storage, you need to wait for the indication that the text message was received.

Create the ATCommandListener

Thanks to the, so called, URCs we can listen into the AT command interface for any event on the module, also for the received text message indicators.

To do so in Java, we need the ATCommandListener. It is a Java interface. It provides the set of methods to react to the events, which are thrown by the AT command interpreter.

ATCommandListener listener = new ATCommandListener() {

	public void RINGChanged(boolean SignalState) {
	}

	public void DSRChanged(boolean SignalState) {
	}

	public void DCDChanged(boolean SignalState) {
	}

	public void CONNChanged(boolean SignalState) {
	}

	public void ATEvent(final String Event) {
		System.out.println("received URC: " + Event);
}
};

Because it is an interface you also need to implement the methods which you don’t plan to use. You can leave them empty though. To receive the SMS notifications you need only the ATEvent() method.

Such a created listener you may add to the previously created ATCommand object.

 atc.addListener(listener); 

Now you will see all the AT events (e.g. RING indicator) on the System.out.

Enable the SMS related URCS

You will not receive any SMS related URCs yet. Surprised?! There are thousands of events happening inside the module. Network events, services events, power events… etc. If module would give out all the events by default it would be a continuous stream of text, containing lot of currently useless information. That is why most of the URCs are disabled by default.

If you want to receive SMS related URCs, you need to enable them. You can do it by using the AT+CNMI=2,1 command.

Value ‘2’ means that all SMS related URCs are forwarded to the modules terminal (so also to the AT command interpreter). Value ‘1’ means that only the URCs for ‘normal’ text messages will be forwarded. If you would like to receive also some special text messages (e.g. class 3) check the AT+CNMI command description in AT command specification and select the other value of the second parameter.

Search for the CNMI in the URCs

Now you will finally receive the information about an incoming text message. It will look like this:

 +CMTI: "SM",1 

CMTI means this is a text message related URC. SM means the message was stored on the SIM card. ‘1’ means it was saved on the 1st record of the storage.

You just need to parse this URC to get the index of the message in the storage. You can do it like this:

int index = arg0.indexOf(",");
String sms_positionInMemory = arg0.substring(index + 1, index + 3);
 

Now you know where the text message is stored and are able to read it Use the AT+CMGR command. The response will contain the text message.

 String response = atc.send("AT+CMGR=" + sms_posisionInMemory + "\r"); 

You have read the message! In fact we could finish this tutorial here. But to be able to receive short messages for a longer time, you need to implement one little procedure at the end of your application. 

Delete old text messages

If you receive a lot of texts, suddenly you will not be able to receive any more messages. If this happens, most likely the module storage for short messages is full. To continuously receive text messages you need to delete some of them from time to time (e.g. after parsing the required values from it). You can delete each text message by using the AT+CMGD command.

 atc.send("AT+CMGD=" + sms_posisionInMemory + "\r"); 

Done!

Outlook: Suggested next steps (for further training)

You have learnt how to receive incoming text messages. Now you may take further steps with this topic. E.g. you may consider using the ATStringConverter class to send special characters like:

”$€@_

You may also check our further tutorials like:

  • How to send text messages
  • Coding standards and conventions
  • How to use the buttons on the Cinterion® Concept Board
  • How to use LEDs on the Cinterion® Concept Board
  • And many others…

Resources

Software:

  • Gemalto M2M Ehs5 Install CD

Documentation:

  • wm02_java_users_guide_v04.pdf
  • module AT command specification

Code:

  • SmsReceiver.java

Other:

  • SmsReceiver.zip – Archive with the full eclipse project ready to be imported
  • SmsReceiver.jad
  • SmsReceiver.jar
This tutorial includes the very important features to handle the URC's, including the network registration, which many people miss. Using any kind of radio link differs heavily from copper or fiber. The signal and connection has to be monitored and URC's notified!

Antero Markkula
Communication and Mechatronics

Enkom Active Oy – www.enkom-active.fi
Upseerinkatu 3 A, 02600 Espoo, Finland
Mobile: +358 400 411368
Office: +358 10 204 0000
Fax: +358 10 204 0010
E-mail: antero.markkula@enkom-active.fi

Hello,

I cannot find the download links, can anybody help me?

Thanks

Carmen

How works the Listener? if i call my concept board, nothing happens

The Listener wont 'work' if you don't have Userware/Autostart enabled in ^SCFG.

The JRC is needed to generate the URCS for the listener.

Hi, how is Listener supposed to work if we need to enabled Autostart for our Midlet App on the EHS6T.

Thanks,

Nick.

Ben's picture
Ben

Hello, i tried this example on the EHS6.

After i delete the old messages in the SIM-Storage it works fine.

There are no download links... 

Author

Mani Gemalto Moderator's picture
Mani Gemalto Moderator