Quectel EP06 AT Command Reference (cellular network testing)
Reference for the Test Devices modem console. Targets the Quectel EP06
(firmware EP06ELAR04A05M4G, IMEI 868186042000040) on the lab container, but
applies to the EC25 / EG06 / EG06 / EM06 family. Every command below was tested
against the live EP06; example responses are the real responses captured from
that modem (it was in a NO SERVICE / SEARCH state at the time, so signal
fields read empty — the parsers must handle that).
The relay is request/response: sendModemAt(serial, command, readMs, timeoutMs)
→ backend modem_at → agent modem.run_at(serial, command, min_read, timeout).
min_read keeps reading the port for at least that long so async URCs are
captured before the call returns. There is no persistent URC stream — see
"Event logging" below.
Device / SIM info
| Command | Purpose | Live response |
|---|---|---|
ATI | Manufacturer / model / firmware | Quectel / EP06 / Revision: EP06ELAR04A05M4G |
AT+CGMM | Model | EP06 |
AT+CGMR | Firmware revision | EP06ELAR04A05M4G |
AT+CGSN | IMEI | 868186042000040 |
AT+CIMI | IMSI | (SIM IMSI) |
AT+QCCID | ICCID | (SIM ICCID) |
AT+CPIN? | SIM PIN state | +CPIN: READY |
Signal / measurement
| Command | Purpose | Live response |
|---|---|---|
AT+CSQ | RSSI/BER (legacy) | +CSQ: 99,99 (99 = no signal). dBm = -113 + 2*rssi. |
AT+QCSQ | Per-RAT signal | +QCSQ: "NOSERVICE". When attached: +QCSQ: "LTE",<rssi>,<rsrp>,<sinr>,<rsrq>. |
AT+QNWINFO | Current RAT / band / channel | +QNWINFO: No Service. When attached: +QNWINFO: "FDD LTE","<mccmnc>","LTE BAND 3",1850. |
AT+QENG="servingcell" | Full serving-cell measurements | +QENG: "servingcell","SEARCH" (idle). See format below. |
AT+QENG="neighbourcell" | Neighbour cells | OK (none when not camped). |
AT+QENG="servingcell" LTE format
+QENG: "servingcell",<state>,"LTE",<is_tdd>,<MCC>,<MNC>,<cellID>,<PCI>,
<EARFCN>,<band>,<UL_BW>,<DL_BW>,<TAC>,<RSRP>,<RSRQ>,<RSSI>,<SINR>,<srxlev>
RSRPdBm,RSRQdB,RSSIdBm (all signed integers).SINRis a converted value: actual dB =(1/5)*SINR - 20(range 0..250 → -20..+30 dB).cellID/PCI/EARFCNare usually hex/decimal per field;bandis the LTE band indicator.
AT+QENG="neighbourcell" LTE format
+QENG: "neighbourcell intra","LTE",<EARFCN>,<PCI>,<RSRQ>,<RSRP>,<RSSI>,<SINR>,<srxlev>,...
+QENG: "neighbourcell inter","LTE",<EARFCN>,...
Registration / attach
| Command | Purpose | Live response |
|---|---|---|
AT+CFUN? | Radio functionality | +CFUN: 1 (full). 0 = minimum/airplane. |
AT+CEREG? | EPS registration | +CEREG: 2,2 (2 = searching). |
AT+CEREG=2 | Enable registration URC with location (TAC/cellID) | OK |
AT+CGATT? / AT+CGATT=1 / =0 | PS attach state / attach / detach | +CGATT: 0 |
AT+COPS? | Current operator selection | +COPS: 0 (auto, not registered). |
AT+COPS=? | Network scan (operator search, slow) | list of (stat,"long","short","numeric",AcT) tuples. |
AT+COPS=0 | Automatic operator selection | OK |
AT+COPS=1,2,"<mccmnc>"[,<AcT>] | Manual select by numeric ID | OK |
Cell / band / RAT locking
| Command | Purpose | Live response |
|---|---|---|
AT+QNWLOCK=? | Capabilities | +QNWLOCK: "common/4g",<num of cells>,[[<freq>,<pci>],...] and +QNWLOCK: "common/lte"[,<action>[,<EARFCN>,<PCI>[,<status>]]] |
AT+QNWLOCK="common/4g" | Query cell lock | +QNWLOCK: "common/4g",0 (0 cells = no lock); after lock +QNWLOCK: "common/4g",1,1850,0. |
AT+QNWLOCK="common/4g",<n>,<EARFCN>,<PCI>[,<EARFCN>,<PCI>...] | Lock to n cells (works on this firmware) | OK |
AT+QNWLOCK="common/4g",0 | Unlock | OK (clears the lock). |
AT+QNWLOCK="common/lte" | Query single-cell LTE lock (read only) | +QNWLOCK: "common/lte",0,0,0,0. |
Firmware behavior (verified live on
EP06ELAR04A05M4G): thecommon/4gform is the one that accepts a lock action on this unit —AT+QNWLOCK="common/4g",1,<EARFCN>,<PCI>locks (returnsOK, lock persists) andAT+QNWLOCK="common/4g",0clears it. Thecommon/lteset forms (...,1,<EARFCN>,<PCI>and...,0) all returnERRORon this firmware —common/lteis query-only here. The UI therefore usescommon/4gfor both lock and unlock. |AT+QCFG="band"| Query band mask |+QCFG: "band",0x8d0,0x1a0880800d5,0x0= (GSM mask, LTE mask, TDS mask). | |AT+QCFG="band",0,<lte_hex_mask>,0| Band lock (LTE).0x0LTE mask = all bands. |OK| |AT+QCFG="nwscanmode"| RAT scan mode |+QCFG: "nwscanmode",0(0 = auto, 1 = GSM, 2 = WCDMA, 3 = LTE). | |AT+QCFG="nwscanmode",<m>[,1]| Set RAT preference (,1= effective immediately) |OK| |AT+QCAINFO| Carrier-aggregation info |OK(none aggregated when idle). |
LTE band mask: bit (band-1), i.e. band N → 1 << (N-1). e.g. B3 = 0x4,
B7 = 0x40, B28 = 0x8000000. 0x0 (or all-ones) = all bands enabled.
Firmware note:
AT+QCFG="nwscanseq"returnsERRORon this EP06 firmware (EP06ELAR04A05M4G) — it is not surfaced in the UI.AT+QSCANis also not supported on this EP06 firmware (it is an RG/RM 5G-series command); the network scan usesAT+COPS=?plusAT+QENGinstead.
Voice calls (VoLTE / IMS)
EP06 voice is VoLTE-only — it needs IMS registered over LTE. AT+QCFG="ims"
on this unit returns +QCFG: "ims",1,0 (IMS enabled by config, current status 0).
| Command | Purpose |
|---|---|
AT+QCFG="ims" | Query/enable IMS. AT+QCFG="ims",1 to force-enable. |
ATD<number>; | Dial a voice call (trailing ; = voice, not data). |
ATA | Answer an incoming call. |
ATH / AT+CHUP | Hang up. |
AT+CLCC | List current calls: +CLCC: <id>,<dir>,<state>,<mode>,<mpty>,"<number>",<type>. Empty OK = no calls. |
AT+CLIP=1 | Enable calling-line ID URC (+CLIP:) on RING. |
AT+CLCC call states: 0 active, 1 held, 2 dialing, 3 alerting, 4 incoming, 5 waiting.
SMS (text mode)
| Command | Purpose | Live response |
|---|---|---|
AT+CMGF=1 | Text mode (vs PDU) | OK |
AT+CPMS? | Storage areas / counts | +CPMS: "ME",0,255,"ME",0,255,"ME",0,255 |
AT+CMGL="ALL" | List messages (text mode) | per message: +CMGL: <index>,"<stat>","<sender>",,"<timestamp>" then body line. |
AT+CMGR=<index> | Read one message | +CMGR: "<stat>","<sender>",,"<timestamp>" + body. |
AT+CMGS="<number>" then body + Ctrl-Z | Send (handled by agent send_sms). | +CMGS: <mr> |
AT+CMGD=<index>[,<delflag>] | Delete message (delflag 4 = all). | OK |
AT+CNMI? / AT+CNMI=2,1,0,0,0 | New-message indication config | +CNMI: 2,1,0,0,0 |
PDP / data
| Command | Purpose | Live response |
|---|---|---|
AT+CGDCONT? | List PDP contexts (APNs) | +CGDCONT: 1,"IPV4V6","ims",... |
AT+CGDCONT=<cid>,"<type>","<apn>" | Set context. types: IP, IPV6, IPV4V6, Non-IP. | OK |
AT+CGACT=1,<cid> / =0,<cid> | Activate / deactivate context. | OK |
AT+CGPADDR[=<cid>] | Show assigned IP. | +CGPADDR: 1,"<ip>" |
AT+CGCONTRDP=<cid> | DNS / gateway / PCO. | +CGCONTRDP: ... |
AT+QPING=1,"<host>" | Ping from the modem (URC replies; needs min_read). | +QPING: ... |
Event logging (URCs) — and the relay limitation
The agent relay is request/response with a per-call port open — it opens the
serial port, sends one command, reads until OK/ERROR (or min_read elapses),
then closes. It does not hold the port open to stream unsolicited result
codes (URCs) back to the browser. So a true live event feed is not possible
through this path without agent changes.
URCs worth enabling (each is a one-shot OK command):
| Command | Enables URC |
|---|---|
AT+CEREG=2 | +CEREG: registration changes (with TAC/cellID). |
AT+CGEREP=2,1 | +CGEV: PS/bearer events. |
AT+CLIP=1 | +CLIP: caller ID on incoming RING. |
AT+CNMI=2,1,0,0,0 | +CMTI: new SMS indication. |
AT+QINDCFG="all",1 | +QIND: Quectel indications. |
Pragmatic approach used in the UI: the Events tab enables the URCs above,
then polls the modem on an interval (AT+CEREG?, AT+CLCC, AT+QENG,
AT+CSQ, AT+CMGL) and renders state changes into a timestamped log. Each poll
also uses a short min_read window so any URC that happens to arrive during the
read is captured opportunistically. This catches state transitions (registration
gained/lost, call started/ended, new SMS, signal change) at the polling cadence,
which is sufficient for lab testing. The limitation is documented in the UI.