Cellular::command, command, Cellular.command

Cellular.command() is a powerful API that allows users access to directly send AT commands to, and parse responses returned from, the Cellular module. Commands may be sent with and without printf style formatting. The API also includes the ability pass a callback function pointer which is used to parse the response returned from the cellular module.

Since 0.9.0: On the Boron, Cellular.command requires Device OS 0.9.0 or later; it is not supported on 0.8.0-rc versions.

Note: Obviously for this command to work the cellular module needs to be switched on, which is not automatically the case in SYSTEM_MODE(MANUAL) or SYSTEM_MODE(SEMI_AUTOMATIC). This can be achieved explicitly via Cellular.on() or implicitly by calling Cellular.connect() or Particle.connect().


The prototype definition is as follows:

int Cellular.command(_CALLBACKPTR_MDM cb, void* param, system_tick_t timeout, const char* format, ...);

Cellular.command() takes one or more arguments in 4 basic types of signatures.

// SYNTAX (4 basic signatures with/without printf style formatting)
int ret = Cellular.command(cb, param, timeout, format, ...);
int ret = Cellular.command(cb, param, timeout, format);
int ret = Cellular.command(cb, param, format, ...);
int ret = Cellular.command(cb, param, format);
int ret = Cellular.command(timeout, format, ...);
int ret = Cellular.command(timeout, format);
int ret = Cellular.command(format, ...)
int ret = Cellular.command(format);
  • cb: callback function pointer to a user specified function that parses the results of the AT command response.
  • param: (void*) a pointer to the variable that will be updated by the callback function.
  • timeout: (system_tick_t) the timeout value specified in milliseconds (default is 10000 milliseconds).
  • format: (const char*) contains your AT command and any desired format specifiers, followed by \r\n.
  • ...: additional arguments optionally required as input to their respective format string format specifiers.

Cellular.command() returns an int with one of the following 6 enumerated AT command responses:

  • NOT_FOUND = 0
  • WAIT = -1 // TIMEOUT
  • RESP_OK = -2
  • RESP_ERROR = -3
  • RESP_PROMPT = -4
// EXAMPLE - Get the ICCID number of the inserted SIM card
SerialLogHandler logHandler;

int callbackICCID(int type, const char* buf, int len, char* iccid)
  if ((type == TYPE_PLUS) && iccid) {
    if (sscanf(buf, "\r\n+CCID: %[^\r]\r\n", iccid) == 1)
  return WAIT;

void setup()
  char iccid[32] = "";
  if ((RESP_OK == Cellular.command(callbackICCID, iccid, 10000, "AT+CCID\r\n"))
    && (strcmp(iccid,"") != 0))
    Log.info("SIM ICCID = %s\r\n", iccid);
    Log.info("SIM ICCID NOT FOUND!");

void loop()
  // your loop code

The cb function prototype is defined as:

int callback(int type, const char* buf, int len, void* param);

The four Cellular.command() callback arguments are defined as follows:

  • type: (int) one of 13 different enumerated AT command response types.
  • buf: (const char*) a pointer to the character array containing the AT command response.
  • len: (int) length of the AT command response buf.
  • param: (void*) a pointer to the variable or structure being updated by the callback function.
  • returns an int - user specified callback return value, default is return WAIT; which keeps the system invoking the callback again as more of the AT command response is received. Optionally any one of the 6 enumerated AT command responses previously described can be used as a return type which will force the Cellular.command() to return the same value. AT commands typically end with an OK response, so even after a response is parsed, it is recommended to wait for the final OK response to be parsed and returned by the system. Then after testing if(Cellular.command() == RESP_OK) and any other optional qualifiers, should you act upon the results contained in the variable/structure passed into the callback.

There are 13 different enumerated AT command responses passed by the system into the Cellular.command() callback as type. These are used to help qualify which type of response has already been parsed by the system.

  • TYPE_UNKNOWN = 0x000000
  • TYPE_OK = 0x110000
  • TYPE_ERROR = 0x120000
  • TYPE_RING = 0x210000
  • TYPE_CONNECT = 0x220000
  • TYPE_NOCARRIER = 0x230000
  • TYPE_NODIALTONE = 0x240000
  • TYPE_BUSY = 0x250000
  • TYPE_NOANSWER = 0x260000
  • TYPE_PROMPT = 0x300000
  • TYPE_PLUS = 0x400000
  • TYPE_TEXT = 0x500000
  • TYPE_ABORTED = 0x600000

It is possible that the call will block for an indeterminate amount of time, possibly for as long as 10 minutes. This can occur if the system thread is busy trying to reconnect to cellular and is unable to do so. Doing operations that access the cellular modem or require access to the system thread from a separate worker thread is a good workaround.