Skip to content

Instantly share code, notes, and snippets.

@westh

westh/README.md Secret

Last active July 31, 2020 13:03
Show Gist options
  • Select an option

  • Save westh/8a39a86bbd20089d867db8ed7a0c6adc to your computer and use it in GitHub Desktop.

Select an option

Save westh/8a39a86bbd20089d867db8ed7a0c6adc to your computer and use it in GitHub Desktop.
A little something something about AT commands πŸ¦„

AT commands

Table of stupid contents

(Unfortunately these types of links do not work in gists)

The what and the why

This blog post is all (or at least a bit) about AT commands. So first off let's start with the basics – the what and the why:

  • What is an AT command?

    • AT commands is another term for Hayes command set which is a command language.

      Hayes command set, also called the AT commands: "AT" meaning 'attention'. Each command string is prefixed with "AT", and a number of discrete command can be concatenated after the "AT".1

      Here's an example of an AT command which is used to check the network registration status on a modem: AT+CREG?.

  • Why should I care? To answer that let's answer another question, namely "what are AT commands used for?"

    • They are the way that we communicate with a modem2. So in case you need connectivity on your device, be it a phone or IoT thingy, then you'll need to interact with a modem via AT commands.

There is a fuck load (and yes I believe that is the technical term) of modems out there, and a bunch of manufacturers who produce said fuck load of modems. Here are some of those manufacturers:

  • SIMCom
  • Quectel
  • Gemalto
  • U-Blox
  • Telit

They all have a different set of AT commands you can use with their modem. They do however have a set of shared AT commands, which are specified in ITU's V.250 : Serial asynchronous automatic dialling and control3 and 3GPP's standard 3GPP TS 27.007 (...) AT command set for User Equipment (UE)4. "Why specifically these two standards?", you might ask – well that is due to the standardization structure of the telecommunication world. Just know this: ITU is the king of standards for telecom and 3GPP is the prince.

If you want to know more about the subject of telecommunication standardizations, and of course you do because it does not get any sexier than that, then take a look at this article.

There are different versions/releases of the 3GPP TS 27.007 document, so all the AT commands specified in the newest standard might not be available on older modems, whereas the V.250 document has not been updated since 20033 so that is pretty stable. Also, some of the AT commands in the 3GPP standard are optional, so they might not be present on all modems. As of the time of writing for this blog post [summer 2020] the newest release is release 16. Not that it matters in regards to what we are going to explore in this post, but now you know in case you want to explore the standards yourself.

AT command syntax

Alright so in order to use AT commands you have to know the syntax. So here it is:

Here's the syntax explained in detail:

  • AT commands always start with AT, and might be followed by a + and then the command
    • E.g. AT+CREG and ATZ
  • AT commands which are to be executed sequentially right after each other can be delimited with a ; and only the first command should include AT
    • E.g. AT+CREG?;+GGREG?
  • AT commands are not case sensitive
    • E.g. AT+CREG? = at+creg? = At+CrEg?
  • Arguments for an AT command are comma-separated
    • E.g. AT+CGDCONT=1,"IP","onomondo"
  • When an AT commands includes an = sign it is a setter, i.e. you are setting a value
    • E.g. AT+CGATT=1
  • When an AT commands ends with an ? sign and does not contain an = sign it is a getter, i.e. you are querying for data
    • E.g. AT+CREG?
  • When an AT commands includes =? it is an argument getter, i.e. you are getting the values/ranges for possible arguments
    • E.g. AT+CREG=?

The response of an AT command may be OK indicating success or ERROR indicating failure. In some modems, the command can be aborted, in which case it will respond back with ABORTED. There are also a few cases where these responses will not apply, but instead, it will be a prompt for more data5.

According to U-Blox5, before each transmitted AT command the device communicating with the modem should:

  • Wait 20 ms

  • Flush the buffer

This is so that the device can handle unsolicited result codes (URC), which the modem will send if enabled for various events, e.g. when the modem is registered it will send a URC. A typical URC would be the one coming from network registrations both data- and phone/SMS wise6, here's an example of a URC after having issued a command to register on the network:

at+creg=1 // enable URC for circuit-switched network registrations
OK
at+cops=0 // register to GSM/UMTS/EPS network with automatic network operator selection
+CREG: 2

+CREG: 5

+CREG: 5

OK

Without URC this would look like so:

at+cops=0 // register to GSM/UMTS/EPS network with automatic network selection
OK
at+creg? // query for circuit-switched network status
+CREG: 0,5

Here we have to query for the circuit-switched network registration status, whereas with URC enabled for network registrations we get them – well unsolicited.

Examples

Okay enough chit-chat let's get on with some real-world examples of what you can use AT commands for. First, we will go through some useful stuff that you can do with standardized AT commands, namely:

  • Establishing a data connection
  • Establishing a PPP connection
  • Get information about the modem and SIM

Afterwards, we will go through some manufacturer-specific AT commands, specifically, we will look at the following with a SIMCom- and Quectel modem:

  • Ping a server
  • Send stuff using TCP and UDP
  • Host a TCP server

Common standardized AT commands usage

The examples shown in this section uses standardized AT commands, so these commands should be present in any modem. Note that the following AT commands are in regards to cellular network modems, and most likely won't be present in other WiFi modems or the likes, even though some of them also uses AT commands.

Establishing a data connection

In order to get a data connection we have to do the following:

  • AT - check the connection to the modem, should respond OK (this step is not strictly needed)
  • AT+COPS=0 - choose network operator and register on the circuit-switched network
    • Wait for AT+CREG to respond x,5
  • AT+CGDCONT=1,"IP","onomondo" - define PDP context (this step could come prior to AT+COPS=0)
  • AT+CGACT=1,1 - activate PDP context (will also call AT+CGATT=1, which is a network attach command if not already attached)
    • Wait for AT+CGREG to respond x,5

This procedure could be used to test whether or not there are any problems in terms of just getting a connection. If this works then most likely if there are connectivity issues it is not us [onomondo].

Here it is in action using the SIM808 modem:

establish-data-connection

Since the SIM has already been attached at some point to the network operator a new authentication is not needed. We first see new signalling when the modem actually attaches to the packet-switched network, i.e. when AT+CGACT=1,1 is issued.

Why a new GSM/circuit-switched connection, which provides phone/SMS services, is not established is a bit of a mystery. In theory, we should see a new GSM connection once the AT+CREG? command responds with x,5. If you want to dive a bit deeper into what we can see from the network side of things then take a look at the appendix, wherein a test with this procedure with a new network is discussed.

Anyhow here comes a more in-depth explanation for each of the used commands.

AT+COPS - choose network operator and register on circuit-switched network

This command is used to choose which network operator to use, also even though it is not documented in the standards this command also goes ahead and connects to the circuits-switched network of the chosen provider (phone/SMS connection, also called GSM connection in our network logs).

Setting syntax: AT+COPS=[<mode>[,<format>[,<oper>[,<AcT>]]]

Test command syntax: AT+COPS=?'s response will be a list (denoted with [element_1, element_2, ..., element_n]) of elements containing:

  • <stat>

  • long alphanumeric version of <oper>

  • short alphanumeric version of <oper>

  • numeric version of <oper>

  • [ <AcT>] (list of supported access technologies, e.g. GSM, NB-IoT, etc.)

  • [<modes>] (list of supported modes)

  • [<format>] (list of supported modes)

All fields will be comma-delimited. The fields in square brackets [] are optional.

For both syntaxes the values are:

<mode>: integer type
  0 automatic (<oper> field is ignored)
  1 manual (<oper> field shall be present, and <AcT> optionally)
  2 deregister from network
  3 set only <format> (for read command +COPS?), do not attempt registration/deregistration (<oper> and <AcT>       fields are ignored); this value is not applicable in read command response
  4 manual/automatic (<oper> field shall be present); if manual selection fails, automatic mode (<mode>=0) is       entered

<format>: integer type
  0 long format alphanumeric <oper>
  1 short format alphanumeric <oper>
  2 numeric <oper>
 
<oper>: string type; <format> indicates if the format is alphanumeric or numeric (for more information consult           the standard, or use AT+COPS=? to figure it out)

<stat>: integer type
  0 unknown
  1 available
  2 current
  3 forbidden
  
<AcT>: integer type; access technology selected
  0  GSM
  1  GSM Compact
  2  UTRAN
  3  GSM w/EGPRS
  4  UTRAN w/HSDPA
  5  UTRAN w/HSUPA
  6  UTRAN w/HSDPA and HSUPA
  7  E-UTRAN
  8  EC-GSM-IoT (A/Gb mode)
  9  E-UTRAN (NB-S1 mode)
  10 E-UTRA connected to a 5GCN
  11 NR connected to a 5GCN
  12 NG-RAN
  13 E-UTRA-NR dual connectivity

According to 3GPP TS 27.0074.

So when we in the procedure send AT+COPS=0 we are instructing the modem to automatically choose the network operator.

AT+CREG - cirtcuit-switched network registration status

This command is used to get the circuit-switched network status, that is the connection that provides the phone/SMS service.

Setting syntax: AT+CREG=<n>

Read syntax: AT+CREG?'s response will be:

+CREG: <n>,<stat>[,[<lac>],[<ci>],[<AcT>][,<cause_type>,<reject_cause>]]

For both syntaxes the values are:

<n>: integer type
  0 disable network registration unsolicited result code
  1 enable network registration unsolicited result code +CREG: <stat>
  2 enable network registration and location information unsolicited result code
    +CREG: <stat>[,[<lac>],[<ci>],[<AcT>]]
  3 enable network registration, location information and cause value information unsolicited result code
    +CREG: <stat>[,[<lac>],[<ci>],[<AcT>][,<cause_type>,<reject_cause>]]

<stat>: integer type; circuit mode registration status.
  0  not registered, MT is not currently searching a new operator to register to
  1  registered, home network
  2  not registered, but MT is currently searching a new operator to register to
  3  registration denied
  4  unknown (e.g. out of GERAN/UTRAN/E-UTRAN coverage)
  5  registered, roaming
  6  registered for "SMS only", home network (applicable only when <AcT> indicates E-UTRAN)
  7  registered for "SMS only", roaming (applicable only when <AcT> indicates E-UTRAN)
  8  attached for emergency bearer services only (see NOTE 2) (not applicable)
  9  registered for "CSFB not preferred", home network (applicable only when <AcT> indicates E-UTRAN)
  10 registered for "CSFB not preferred", roaming (applicable only when <AcT> indicates E-UTRAN)
  11 attached for access to RLOS (see NOTE 2a) (applicable only when <AcT> indicates E-UTRAN)

<lac>: string type; two byte location area code (when <AcT> indicates value 0 to 6), or tracking area code (when
        <AcT> indicates value 7). In hexadecimal format (e.g. "00C3" equals 195 in decimal).

<ci>: string type; four byte GERAN/UTRAN/E-UTRAN cell ID in hexadecimal format.

<AcT>: same as for AT+COPS

In the procedure, we are looking for the response x,5, as this is indicating that the modem is connected and is roaming (which the device will always be with onomondo).

AT+CGDCONT - define packet data protocol (PDP) context

This command is used to define the PDP context. So what the hell is a PDP context?

3.2. GTP Signaling. Tunnels state is held in the SGSN and GGSN as Packet Data Protocol (PDP) Context data structures. These contain various information, such as the device IP address, International Mobile Subscriber Identity (IMSI), and a tunnel identifier. The concept is used to isolate user traffic from core network control plane signaling and to provide certain Quality of Service (QoS) guarantees to the user traffic.7

What this jargon means is that a PDP context is a piece of information that is needed inside the mobile core in order for it to set up data session. From the device point of view, this is where the access point name (APN) is set. The command in of itself does not activate any signalling.

Actually, it is not always the PDP context that is being set. For evolved packet systems (EPS) and 5G systems (5GS), this command instead sets the PDN connection and PDU session respectively (what those acronyms stand for is up to you to find out...).

For this command, there are a whole lot of settings, and the following is therefore not a complete syntax of what can be configured with the command, but here goes.

Setting syntax: AT+CGDCONT=<cid>,<PDP_TYPE>,<APN>

Read syntax: AT+CGDCONT=<cid>,<PDP_TYPE>,<APN>,<PDP_addr>

For both syntaxes the values are:

<cid>: integer type; specifies a particular PDP context definition (you can multiple PDP context)

<PDP_type>: string type; specifies the type of packet data protocol. The default value is manufacturer-specific.
  X.25          ITU-T/CCITT X.25 layer 3 (Obsolete)
  IP            Internet Protocol (IETF STD 5 [103])
  IPV6          Internet Protocol, version 6 (see RFC 2460 [106])
  IPV4V6        Virtual <PDP_type> introduced to handle dual IP stack UE capability. (See 3GPP TS 24.301 [83])
  OSPIH         Internet Hosted Octect Stream Protocol (Obsolete)
  PPP           Point to Point Protocol (IETF STD 51 [104])
  Non-IP        Transfer of Non-IP data to external packet data network (see 3GPP TS 23.401 [82]) Ethernet     
  Ethernet      protocol (IEEE 802.3)
  Unstructured  Transfer of Unstructured data to the Data Network via N6 (see 3GPP TS 23.501 [165])

<APN>: string type; a logical name that is used to select the GGSN or the external packet data network.

<PDP_addr>: string type; identifies the MT in the address space applicable to the PDP.

So in our case, we most of the time want it to be set to AT+CGDCONT=1,"IP","onomondo".

AT+CGACT - activate/deactivate PDP context

This command is used to activate or deactivate the PDP context. If an activation of a PDP context is issued and the modem is not connected to the packet-switched (PS) network then it will first attach to the PS network, this is equivalent to running AT+CGATT=1.

Before the syntax of AT+CGACT is explained we will quickly explore what AT+CGATT does – AT+CGATT=<state> attaches or detaches to the PS network depending on the <state>, which is 1 for attaching and 0 for detaching.

Setting syntax: AT+CGACT=<state>,<cid>

Setting syntax: (list of) <state>,<cid>

For both syntaxes the values are:

<state>: integer type; indicates the state of PDP context activation.
  0 deactivated
  1 activated

<cid>: integer type; specifies a particular PDP context definition (see the +CGDCONT and +CGDSCONT commands).
AT+CGREG - packet-switched network registration status

Identical to AT+CREG but for the packet-switched network instead, i.e. data connection.


Establishing a PPP connection

In order to get a PPP connection we have to do the following:

  • AT+COPS=0 - choose network operator and register on network
    • Wait for AT+CREG and AT+CEREG to respond x,5
  • AT+CGDCONT=1,"IP","onomondo" - define PDP context
  • AT+CGACT=1,1 - activate PDP context (will also call AT+CGATT=1, which is a network attach command if not already attached)
  • ATD*99# - dial up provider
  • Start PPP protocol

This procedure is the only generic way of getting a usable connection from a device. The only issue with this approach is that the device has to support the PPP-, TCP- and UDP protocols – this is not viable for teeny tiny devices, but most microcontrollers which can run Mongoose OS, FreeRTOS, or the likes will be able to use it.

This procedure is actually what is being carried out by Linux's PPP daemon, pppd, on the deveyes and watchdogs.

The only new command in regards to establishing a data connection is the ATD command, so let's explore it. Also as a side note then some modems might require that the baud rate used with the serial connection be fixed to a specific value10.

ATD - dial command

This command dials the given number. The syntax is ATD<number>.

In the case of establishing a PPP connection, we are dialling up the operator [onomondo] with the number *99#. This number is not documented in ITU's or 3GPP's standards but seem to be the standard number to dial up the operator11.


Get information about the modem and SIM

This section goes through some AT commands that can be used to get information about the state of the modem and the SIM. It is not really that important, but more of a nice to know – so if you do not feel up for it then just skip it ✌️

ATZ[value] and AT&F[value] - resetting the modem profile

So the standard says the following about ATZ:

This command instructs the DCE to set all parameters to their factory defaults as specified by the manufacturer. This may include taking into consideration the settings of hardware configuration switches or non-volatile parameter storage (if implemented). If the DCE is connected to the line, it is disconnected from the line, terminating any call in progress.

And the following to say about AT&F:

This command instructs the DCE to set all parameters to default values specified by the manufacturer, which may take into consideration hardware configuration switches and other manufacturer-defined criteria.

So yeah... It appears that there are two ways of getting the modem into a factory setting, but if we take a closer look at it ATZ allows for taking some other non-volatile parameter storage into account. This has been interpreted by manufacturers as that AT&F is for factory resetting the modem, and that ATZ is for resetting the modem into a user-specified profile10,11.

Summary:

  • AT&F or AT&F0 will factory reset the modem
  • ATZ[value] will reset the modem to the user profile (there might be multiple defaults, which is the reason for the value)
  • The reset will never trigger a change in the baud rate

The settings that will change are not clearly stated in the standard, but for the SIM808 modem the following settings are changed upon issuing an ATZ or AT&F.

DEFAULT PROFILE
S0: 0
S3: 13
S4: 10
S5: 8
S6: 2
S7: 60
S8: 2
S10: 15
+CBST: 7,0,1
+CRLP: 61,61,48,6
V: 1
E: 1
Q: 0
X: 4
&C: 1
&D: 1
+CLTS: 0
+CREG: 0
+CGREG: 0
+CMEE: 0
+CIURC: 1
+CFGRI: 2
+CMTE: 0
+CANT: 0,0,10
+STKPCIS: 0
+CMGF: 0
+CNMI: 2,1,0,0,0
+CSCS: "IRA"
+VTD: 1
+CALS: 1
+CHF: 0
+CAAS: 1
+CBUZZERRING: 0
+DDET: 0
+MORING: 0
+SVR: 16
+CCPD: 1
+CSNS: 0
+CSGS: 1
+CNETLIGHT: 1
+SLEDS: 64,64,64,800,3000,300
+CSDT: 0
+CSMINS: 0
+EXUNSOL: 0
+SDMODE: 0
+ECHARGE: 0
+FSHEX: 0
+FSEXT: 0
+IPR: 0
+IFC: 0,0
+ICF: 3,3
+CSCLK: 0
ATI[value] - get modem information (but in a bad way)

This command is dumb. First off the standard says:

This command causes the DCE to transmit one or more lines of information text, determined by the manufacturer, followed by a final result code.

Then:

NOTE – The responses to this command may not be reliably used to determine the DCE manufacturer, revision level, feature set, or other information, and should not be relied upon for software operation.

So what in the damn hell is it good? Absolutely nothing (uuuh say it again y'all). But here's an example:

ATI
SIM808 R14.18

OK
AT+GMI - get manufacturer identifaction

Is used to determine the identity of the manufacturer of the modem. Here's an example:

AT+GMI
SIMCOM_Ltd

OK
AT+GMM - get modem information

Is used to determine the modem model, for example:

AT+GMM
SIMCOM_SIM808

OK
AT+GMR - get modem version

Is used to determine the modem's version, for example:

AT+GMR
Revision:1418B03SIM808M32

OK
AT+CIMI - get the International Mobile Subscriber Identity (IMSI)

As the title says:

AT+CIMI
234500021055844

OK

Which corresponds to Jersey Telecom's mobile country code (MCC) and mobile network code (MNC) combination, which can be seen from the first five numbers, i.e. 23450 where the first three numbers are the MCC and the last two the MNC.

The IMSI uniquely identifies the user, unfortunately we cannot/are not using this, and are instead relying on the Integrated Circuit Card Identifier (ICCID), which there are no standardized AT commands for retrieving. For the SIM800's series the command to extract the ICCID is AT+CCID, which yields:

AT+CCID
89457387300000019441

OK

Here we see that the last 9 digits, excluding the very last one, constitutes the SIM ID, i.e. 000001944.

AT+CGSN - get the International Mobile station Equipment Identity (IMEI)

This uniquely identifies the modem.

AT+CGSN
865067026412521

OK

Manufacturer-specific AT commands

To make it easier for developers a lot of manufacturers have implemented their own AT commands which usually supports the whole IP stack. This means that they have their own custom AT commands to do a ping, send a TCP- or UDP packet, and so on.

SIMCom: Pinging

The following, and the subsequent two sections, has been tested on a SIM808. These commands might not work on all series of SIMCom's modems, but should at least work on modems from the 800 series.

In order to use any of the subsequent SIMCom's AT commands an active PDP context is needed, but it has to be established using SIMCom's own special AT commands12. Here's the procedure:

  • AT+CSTT="onomondo" – start "task" with specified APN (basically equivalent to AT+CGDCONT)
  • AT+CIICR – activate the "task" / bring up a wireless connection (basically equivalent to AT+CGACT)
  • AT+CIFSR – get the local IP address (this step is mandatory for reasons only SIMCom knows)

Here it is in action:

simcom-attach-procedure

Once this is done it is as simple as using the AT+CIPPING command13.

AT+CIPPING - ping a remote server

Setting syntax: AT+CIPPING=<host>[,<retryNum>[,<dataLen>[,<timeout>[,<ttl>]]]]

The values for the syntax are14:

<host> Address of the remote host, string type. This parameter  can  be  either: 
  - IP address in the format:”xxx.xxx.xxx.xxx”
  - Host name solved by a DNS query

<retryNum> The number of Ping Echo Requset to send
  1-100 Default: 4

<dataLen> The length of Ping Echo Request data
  0-1024 Default: 32

<timeout> The timeout, in units of 100 ms, waiting for a single Echo Reply
  1-600 Default: 100(10  seconds)

<ttl>  Time to live
  1-255 Default:  64

And here it is in action:

simcom-ping

Remember to carry out the special SIMCom attach procedure beforehand.

SIMCom: Send stuff using TCP and UDP

simcom-tcp-client

AT+CIPMODE - set transparent or non-transparent mode

This command is used to select whether the connection should be transparent or non-transparent. Transparent mode means that the data coming and going in the connection is printed to the screen in the same manner as if you did a dial, meaning that you can tab in and out of the connection. In order to use the transparent mode, multi-connections must be disabled.

Setting syntax14: AT+CIPMODE=<mode>

<mode>
  0 Non-transparent mode
  1 Transparent mode

In the example above AT+CIPMODE was set to 0, so that the text would just be printed without having to tab into the connection.

AT+CIPSTART - start TCP or UDP connection

This command is used to start a TCP or UDP connection, it essentially creates a socket on the modem – this means that when the command is issued via TCP the handshake will occur.

Setting syntax: AT+CIPSTART=[n,]<mode>,<host>,<port>

Possible variables14:

<n> 0..5 A numeric parameter which indicates the connection number (used in case of multiple connections)

<mode> A string parameter which indicates the connection type
  "TCP" Establish a TCP connection
  "UDP" Establish a UDP connection

<host> A string parameter which indicates remote server IP address 

<port> Remote server port
AT+CIPSEND - send data through TCP or UDP connection

As the subtitle says: This command is used to send data through a TCP or UDP connection. It is possible to messages of a fixed length or simply send data without specifying the length.

Setting syntax: AT+CIPSEND[=<length>|] (in case of multiple connections a <n> variable also need to be set, see the documentation for more information on that)

In the case where the length is not specified the end of the message is marked with a CTRL+Z character in ASCII. There is no usable variables section for this command, so we will skip it.

SIMCom: Host a TCP server

simcom-tcp-server

AT+CIPSERVER - set up TCP server

As the title says. When opening the server the port variable is needed, but when closing it the port is not needed.

Setting syntax: AT+CIPSERVER=<mode>[,<port>]

Variables14:

<mode>
  0 Close server
  1 Open server
 
<port>
  1..65535 Listening port

Quectel: Pinging

The following, and the subsequent two sections, has been tested on an EC25-E. These commands might not work on all series of Quectel's modems, but should at least work on modems from the EC2x series.

In order to use any of the subsequent Quectel specific AT commands, an activate PDP context is needed, i.e. an active data session. To obtain such a session you can simply follow the generic procedure to get a data connection, which was discussed earlier.

After that, it is simply a matter of running AT+QPING.

AT+QPING - ping a remote server

This command is used to ping a remote server.

Setting syntax: AT+QPING=<contextID>,<host>[,<timeout>[,<pingnum>]]

The values for this syntax are15:

<contextID> Integer type. The context ID. The range is 1-16.

<host> The host address in string type. The format is a domain name or a dotted decimal IP address.

<timeout> Integer type. Set the maximum time to wait for the response of each ping request. The range is 1-255, and the default value is 4. Unit:second.

<pingnum>Integer type. Set the maximum number of time for sending ping request. The range is 1-10, and the default value is 4.

Here we see the command in action (prior to this an active PDP context was obtained, with cid = 1, using the generic procedure):

quectel-ping

Quectel: Send stuff using TCP and UDP

quectel-tcp-client

AT+QIOPEN - open a socket service

This command basically just creates a socket. When using a client style service type a connection is established, whereas the server styles create a socket and opens it up for the outside to connect to.

Setting syntax: AT+QIOPEN=<contextID>,<connectID>,<service_type>,<host>,<remote_port>[,<local_port>][,<access_mode>]

variables15:

<contextID> Integer type. The context ID. The range is 1-16. (the PDP context ID)

<connectID> Integer type. The socket service index. The range is 0-11.

<service_type> String type. The socket servicetype.
  β€œTCP” Start a TCP connection as a client
  β€œUDP” Start a UDP connection as a client
  β€œTCP LISTENER” Start a TCP server to listen to TCP connection
  β€œUDP SERVICE” Start a UDP service

<host> String type. If <service_type> is TCP or UDP, it indicates the IP address (could also be a domain name) of remote server, such as β€œ220.180.239.212”. If <service_type> is TCP LISTENER or UDP SERVICE, please enter β€œ127.0.0.1”..

<remote_port> The  port  of  the  remote  server,  only  valid  when  <service_type> is β€œTCP” or β€œUDP”. The range is 0-65535.

<local_port> The local port. The range is 0-65535. If <service_type> is β€œTCP LISTENER” or β€œUDP SERVICE”, this parameter must be specified. If <service_type> is β€œTCP” or β€œUDP”, if <local_port> is 0, then the local port will be assigned automatically. Otherwise the local port is assigned as specified.

<access_mode> Integer type. The data access mode of the socket service.
  0 Buffer access mode
  1 Direct push mode
  2 Transparent access mode

Quectel: Host a TCP server

quectel-tcp-server

AT+QIRD - retrieve the received data from a socket

So when receiving something from a socket the module will buffer the incoming data and report with the URC β€œ+QIURC: β€œrecv”, given that the socket is set in buffer access mode (which is the default). To read from that buffer you use AT+QIRD.

Setting syntax: AT+QIRD=<connectID>[,<read_length>]

variables15:

<connectID> Integer type. The socket service index. The range is 0-11.

<read_length> The maximum length of data to be retrieved. The range is 0-1500. Unit: byte.

In the example above the command was used to read 1500 bytes from the buffer, with the connection ID that had been randomly assigned to the connection.

What is next?

Well, in general, it seems like there are no good go-to places to really understand AT commands, so it could be nice to make such a place. I'm thinking a GitHub wiki could do just that. And here are some other ideas of how to take the next step on this AT-command-hell-journey:

  • Make a Google Sheet with all AT commands (with this knowledge an AT command parser could be made somewhat easily)
    • One sheet for standardized AT commands
    • A sheet for each big manufacturer
  • Make some basic procedures for each manufacturer to help customers get started
    • For instance, it could be cool to put up the general procedure to get a data connection up on help.onomondo.com
  • Review TinyGSM, and see if it is good enough – otherwise, we could do a fork or make our own library

References and footnotes

1: https://en.wikipedia.org/wiki/Hayes_command_set

2: also called a mobile terminal (MT)

3: https://www.itu.int/rec/T-REC-V.250/en

4: https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=1515

5: https://www.u-blox.com/sites/default/files/AT-CommandsExamples_AppNote_(UBX-13001820).pdf

6: data connections are packet-switched (PS) and phone/SMS connections are circuit-switched (CS), unsolicited response codes (URC) for each can be enabled and disabled using AT+CGREG and AT+CREG, respectively – data connections also appear as evolved packet system (EPS) connection in newer modems, and URC for this can be configured using the AT+CEREG command [AT+CGREG and AT+CGREG will however often be completely identical in their URC and so on]

7: Exploratory Analysis of a GGSN’s PDP Context Signaling Load, http://downloads.hindawi.com/journals/jcnc/2014/526231.pdf

8: https://www.cika.com/soporte/Information/GSMmodules/Quectel/AppNotes/Quectel_GSM_PPP_Application_Note.pdf

9: https://zoomtel.zendesk.com/hc/en-us/articles/212403243-Mobile-broadband-service-provider-settings

10: https://simcom.ee/documents/SIM7100E/SIM7100_AT%20Command%20Manual_V1.01.pdf

11: https://www.telit.com/wp-content/uploads/2018/03/Telit-LN940-SERIES-AT-Command-User-Guide-REV1.4.pdf

12: http://www.python-exemplary.com/download/sim800_series_tcpip_application_note_v1.00.pdf

13: ttps://simcom.ee/documents/SIM900/SIM900_PING_AT%20Command%20Manual_V1.00.pdf (even though it is for the SIM900's series it still works for the SIM800 series)

14: https://www.elecrow.com/wiki/images/2/20/SIM800_Series_AT_Command_Manual_V1.09.pdf

15: https://sixfab.com/wp-content/uploads/2018/09/Quectel_EC2xEG9xEM05_TCPIP_AT_Commands_Manual_V1.0.pdf

Appendix

Establish a connection to the network: Signalling investigation

In order to understand what is going on with each AT commands the generic procedure for establishing a data connection, as discussed earlier, was carried out on Quectel's EC25-E modem. The test was done with a new network operator so that the authorization signalling and so on would show:

AT+COPS=? // check for available network operators
+COPS: (2,"TDC","TDC","23801",2),(1,"TDC","TDC","23801",0),(1,"3 DK","3 DK","23806",2),(1,"Telenor DK","TelenoDK","23802",2),(1,"Telia DK","Telia","23820",2),()

OK

AT+COPS=1,0,"3 DK" // manually select 3 DK network
OK

AT+CGDCONT? // check PDP contexts
+CGDCONT: 1,"IP","","0.0.0.0",0,0,0,0 // nothing, this means the device does not have a data connection

OK

AT+CGACT? // check defined PDP contexts' status
+CGACT: 1,0 // PDP context 1 is not activated

OK

AT+CGATT? // check packet-switched (PS) network status
+CGATT: 0 // the modem is not connected to the PS network

OK

AT+CREG? // check circuit-switched (CS) network status
+CREG: 0,5 // URC disabled, roaming on CS network

OK

AT+CGREG? // check packet-switched (PS) network status
+CGREG: 0,2 // URC disabled, searching

OK

Here's what the network logs showed:

Then the following was executed:

AT+CGDCONT=1,"IP","onomondo" // define PDP context
OK

AT+CGACT=1,1 // activate PDP context (will also do a AT+CGATT=1)
OK

AT+CGREG? // check packet-switched network status
+CGREG: 0,5 // URC disabled, roaming (this is good we are connected)

OK

Which resulted in the following new network logs:

Why the GSM connection is redone I do not know, the other stuff makes sense – maybe we are just parsing it wrong? Here's a recap of what happened during this procedure:

Send an SMS

So in order to send an SMS you have to set the SMS center (SMSC) number, which specifies where the SMS's should go to, which should be +447797704848 when using Onomondo. To set the SMSC number using AT commands you can use AT+CSCA, e.g.:

AT+CSCA="+447797704848"

In order to save the SMSC number to the SIM, so that you won't have to do this each time you reboot the modem, you need to issue the AT command AT+CSAS. This command saves the SMS settings, which includes the SMSC number, to the SIM.

Now, you can try it out using the AT+CMGS=<number> command, e.g.:

AT+CMGS="1234"
> saying hello from modem!
+CMGS: 11

OK

This will then appear in your webhook, which is the only method of retrieving SMS's sent from your devices in the Onomondo eco-system.

Weird side note: In order to actually be able to send an SMS you will need to be attached to the PS network. You don't need to have an active PDP context, but apparently for some reason you need to be connected to the PS network, even though SMS's should be handled by the CS part of the network. This makes zero sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment