Phreak — Wireless AT Command Reference
DeMon's wireless companion is an ESP32-C5 — a dual-band Wi-Fi 6 (2.4 GHz + 5 GHz) and Bluetooth LE 5 SoC, and the core of Phreak, the Ant64's wireless subsystem (Wi-Fi/BLE plus optional LoRa and GPS — see Communications). One way to drive it from DeMon (the CM5) is Espressif's ESP-AT firmware: the C5 runs a ready-made image that accepts text AT commands over a serial link and answers OK / ERROR, so DeMon gets networking and BLE without linking a wireless stack into AntOS. This document is a reference to that command set as shipped for the C5 in the latest firmware. (The alternative — running the C5 as an esp_hosted radio co-processor — is a separate integration path.)
Status: external reference. This summarises Espressif's ESP-AT command set for the ESP32-C5 at the latest release. The authoritative, parameter-level documentation is Espressif's (links at the end). Command availability depends on the firmware build — see §3.
Want to see what it's for? Phreak Fun collects creative and research projects built on these commands — RF cartography, LoRa mesh chat, CSI presence art, radio fox-hunts, CTF labs — all receive-only and ethically framed.
1. Firmware and versions
ESP-AT is Espressif's official AT-command firmware, maintained for the C5 alongside the C2 / C3 / C6 / ESP32 / S2 families. Espressif's prebuilt AT binary targets the 4 MB-flash, no-PSRAM part (ESP32-C5-4MB). The Ant64's C5 is a larger module, though — currently ESP32-C5-WROOM-1-N16R8 (16 MB flash + 8 MB PSRAM), moving to N32R8 (32 MB flash + 8 MB PSRAM) — so the Ant64's own AT build (needed anyway for §12–§15) has far more flash than the stock image and can lean on PSRAM for buffers.
- Latest released: v5.0.1.0 (recommended) and v5.0.0.0. The version string from
AT+GMRreads likeAT version:5.0.0.0(... ESP32C5 ...)on an ESP-IDF v5.5-class SDK. - Getting firmware: production binaries come from Espressif's AT Firmware Application form (per chip and version); test builds come from the project's GitHub Actions or a local compile. Self-compiled firmware cannot OTA-upgrade from Espressif's servers.
- Customising: the
at.pytool re-configures a released binary (UART pins, Wi-Fi defaults, certificates, GATTS database) without a full rebuild; a local ESP-AT build is what enables the compile-in command sets listed in §3.
2. Serial transport and DeMon wiring
The Ant64 build uses the C5's interfaces three ways:
| Interface | Role |
|---|---|
| UART0 | AT command / response — the DeMon control link (up to 5 Mbps, HW flow control); also the firmware-download port when the C5 needs reflashing |
| USB-Serial-JTAG | debug / log output, carried over USB to DeMon's USB-FS hub — kept off the AT stream |
| UART1 | optional GPS (NMEA) — see §13 |
The AT port (UART0) uses a custom pin map for DeMon's layout — TX IO11, RX IO12, CTS IO23, RTS IO24 — re-mappable via at.py ("How to Set AT Port Pins"); stock ESP-AT's default AT-port pins are TX23/RX24/CTS25/RTS26. Both the C5 and DeMon sustain up to 5 Mbps on this link (~0.5 MB/s practical), set at runtime with AT+UART_CUR (RAM) or AT+UART_DEF (saved to flash). At that rate hardware flow control is essential, not optional — the RX FIFO fills in microseconds, so the CTS/RTS pair (DeMon wires the match — see DeMon) is what stops dropped bytes when either side is briefly busy; give the RTS-deassert threshold headroom below the 128-byte FIFO. Putting the log on the USB-Serial-JTAG keeps it out of the AT byte-stream, so UART0 carries only AT traffic at runtime — and the download stream when flashing, which never overlaps.
Transport split — benchmark pending. The table above is the working default. The C5 also reaches DeMon over QSPI (the SPI2 slave), and its USB-Serial-JTAG is itself a usable data path, so the final AT transport is a measurement call rather than settled. Rough expectation: 5 Mbps UART (~0.5 MB/s, lowest latency, never contended) is enough for everyday AT; QSPI is the bulk accelerator (a few MB/s) when DeMon's SPI bus is free; USB-FS sits between them (~0.5–1 MB/s) for sustained transfers like OTA images or the §14 capture feed. If a benchmark favours it, AT could move to USB or QSPI with UART taking debug — but UART stays the always-available control and recovery path regardless.
Optional — LoRa Plus add-on. A Semtech LR2021 (Seeed Wio-LR2021) dual-band LoRa Plus transceiver can be added to the C5 (on its SPI bus). This stays transparent to the DeMon host: it surfaces as a handful of extra LoRa AT commands on the same serial link, alongside the Wi-Fi/BLE set. LoRa is not part of stock ESP-AT, so those commands are added as custom user-defined AT commands in a local build (see §12).
Optional — GPS add-on. A GNSS receiver (u-blox NEO-M10) hangs off the C5's UART1; the C5 parses its NMEA and exposes position to DeMon as extra AT commands — the same custom-bridge pattern as LoRa (see §13).
Every command line is terminated with CR LF (\r\n); the firmware replies with optional data lines followed by OK or ERROR. Confirm the link with AT (expect OK) and read the build with AT+GMR.
On DeMon (see DeMon for the authoritative pinout): the C5's BOOT strap (its GPIO28) is driven by DeMon's MCP23017 PA7 and the C5's EN (reset) by PA6, so DeMon can hold BOOT low and toggle EN to drop the C5 into download mode and reflash it over UART0; C5 pin 27 is tied high. DeMon also runs a QSPI link to the C5 (an SPI2 chip-select); DeMon is the source of truth for the wiring, and Firmware & Flashing covers the flash sequence end-to-end.
3. Command-set availability (C5-4MB firmware)
What the released C5-4MB binary ships by default, what needs a custom build, and the radio facts:
| Command set | C5-4MB default |
|---|---|
| Base / system, User | included |
| Wi-Fi | included |
| TCP-IP (incl. SSL, SNTP, ping, mDNS) | included |
| WPS, SmartConfig | included |
| MQTT | included |
| HTTP | included |
| Bluetooth LE | included |
| BluFi | included |
| OTA (network firmware upgrade) | included |
| FileSystem | compile-in |
| Web server | compile-in |
| WebSocket | compile-in |
| Driver (ADC / PWM / I2C / SPI) | compile-in |
WPA2-Enterprise (AT+CWJEAP) |
compile-in |
Radio: dual-band Wi-Fi 6 (2.4 + 5 GHz) and BLE 5, sharing one RF antenna between Wi-Fi and BLE. Anything not listed above is unsupported. AT+CMD enumerates exactly what the running firmware exposes.
The compile-in rows are absent only from Espressif's prebuilt binary; they are real ESP-AT command sets. The Ant64's larger module (§1) has the flash to enable them all, so on the Ant64 build they are present too — their commands are documented in §10.
4. Basic / system commands
| Command | Function |
|---|---|
AT |
link test; returns OK if AT is alive |
AT+RST |
restart the C5 |
AT+GMR |
firmware / SDK / bin version |
AT+CMD |
list every command the running firmware supports |
ATE |
command echo on / off |
AT+RESTORE |
restore factory defaults (clears NVS) |
AT+GSLP |
deep sleep for a set time |
AT+SLEEP |
set modem / light sleep mode |
AT+SLEEPWKCFG |
light-sleep wake source / GPIO |
AT+UART_CUR / AT+UART_DEF |
UART config, RAM-only / saved to flash |
AT+SYSRAM |
free-heap status |
AT+SYSMSG / AT+SYSMSGFILTER / AT+SYSMSGFILTERCFG |
system-prompt messages + filtering |
AT+SYSSTORE |
whether parameter changes persist to flash |
AT+SYSFLASH / AT+SYSMFG |
user flash partitions / manufacturing-NVS |
AT+SYSREG |
read / write a register |
AT+SYSTIMESTAMP |
local timestamp |
AT+SYSLOG |
verbose AT error codes on / off |
AT+RFPOWER |
RF TX power (Wi-Fi + BLE) |
AT+RFCAL |
force RF full calibration |
AT+SYSROLLBACK |
roll back to the previous firmware image |
AT+SAVETRANSLINK |
auto-enter passthrough (TCP/SSL/UDP or BLE) at boot |
AT+TRANSINTVL |
data-batching interval in passthrough mode |
5. Wi-Fi commands
Station, SoftAP, and the C5's dual-band controls.
| Command | Function |
|---|---|
AT+CWINIT |
initialise / de-initialise the Wi-Fi driver |
AT+CWMODE |
mode: station, SoftAP, or both |
AT+CWBANDMODE |
select 2.4 GHz / 5 GHz / dual band |
AT+CWBANDWIDTH |
channel bandwidth |
AT+CWSTATE |
current Wi-Fi state + connection info |
AT+CWCONFIG |
inactive time / listen interval |
AT+CWJAP |
connect station to an AP |
AT+CWRECONNCFG |
auto-reconnect policy |
AT+CWLAP / AT+CWLAPOPT |
scan for APs / configure scan output |
AT+CWQAP |
disconnect from the AP |
AT+CWSAP |
configure the SoftAP |
AT+CWLIF / AT+CWQIF |
list / disconnect SoftAP clients |
AT+CWDHCP / AT+CWDHCPS |
DHCP enable / SoftAP lease range |
AT+CWAUTOCONN |
auto-connect on power-up |
AT+CWSTAPROTO / AT+CWAPPROTO |
802.11 b/g/n/ax protocol for station / SoftAP |
AT+CIPSTA / AT+CIPAP |
station / SoftAP IP address |
AT+CIPSTAMAC / AT+CIPAPMAC |
station / SoftAP MAC address |
AT+CWHOSTNAME |
station hostname |
AT+CWCOUNTRY |
Wi-Fi country / regulatory code |
AT+CWSTARTSMART / AT+CWSTOPSMART |
SmartConfig provisioning |
AT+WPS |
WPS push-button provisioning |
AT+CWJEAP |
connect to a WPA2-Enterprise AP (compile-in) |
Dual-band note. AT+CWBANDMODE is the C5-specific lever — 2.4 GHz only, 5 GHz only, or both. AT+CWSTAPROTO / AT+CWAPPROTO extend the negotiated standard up to Wi-Fi 6 (ax). AT+CWCOUNTRY governs which 5 GHz channels are legal in the region, so it matters more here than on a 2.4 GHz-only part.
6. TCP/IP, SSL, SNTP, ping, mDNS, OTA
Sockets, secure sockets, time, name resolution, and network firmware upgrade.
| Command | Function |
|---|---|
AT+CIPV6 |
enable / disable IPv6 |
AT+CIPSTART / AT+CIPSTARTEX |
open TCP / UDP / SSL (fixed / auto-assigned link id) |
AT+CIPSEND / AT+CIPSENDEX / AT+CIPSENDL / AT+CIPSENDLCFG |
send data (normal / expanded / long-parallel + its config) |
AT+CIPCLOSE |
close a connection |
AT+CIPSTATE |
list active TCP / UDP / SSL connections |
AT+CIPMUX |
single vs multiple connections |
AT+CIPSERVER / AT+CIPSERVERMAXCONN |
run a TCP/SSL server / cap its clients |
AT+CIPMODE |
normal vs passthrough ("transparent") transmission |
+++ |
escape from passthrough back to command mode |
AT+CIPRECONNINTV |
passthrough reconnect interval |
AT+CIPCONNPERSIST |
keep a connection across resets |
AT+CIPSTO |
server idle timeout |
AT+CIPRECVTYPE / AT+CIPRECVDATA / AT+CIPRECVLEN |
passive-receive mode + read buffered data / length |
AT+CIPDINFO |
include peer IP/port in +IPD notifications |
AT+CIPTCPOPT |
per-socket options (keepalive, etc.) |
AT+CIFSR |
local IP + MAC |
AT+CIPDOMAIN |
resolve a hostname (DNS) |
AT+CIPDNS |
configure DNS servers |
AT+PING |
ICMP ping a host |
AT+MDNS |
advertise / query mDNS services |
AT+CIPSNTPCFG / AT+CIPSNTPTIME / AT+CIPSNTPINTV |
SNTP server + TZ / read time / sync interval |
AT+CIPSSLCCONF |
SSL client mode / CA validation |
AT+CIPSSLCCIPHER |
SSL cipher suite |
AT+CIPSSLCCN / AT+CIPSSLCSNI / AT+CIPSSLCALPN |
SSL common name / SNI / ALPN |
AT+CIPSSLCPSK / AT+CIPSSLCPSKHEX |
SSL pre-shared key (string / hex) |
AT+CIPFWVER |
AT firmware version available on Espressif's OTA server |
AT+CIUPDATE |
OTA-upgrade the AT firmware over the network |
7. Bluetooth LE commands
GAP (advertise / scan / connect), GATT server and client, serial passthrough, and pairing.
| Command | Function |
|---|---|
AT+BLEINIT |
initialise BLE (client / server role) |
AT+BLEADDR |
query / set the BLE address |
AT+BLENAME |
device name |
AT+BLESCANPARAM / AT+BLESCAN / AT+BLESCANRSPDATA |
scan parameters / run scan / scan-response data |
AT+BLEADVPARAM / AT+BLEADVDATA / AT+BLEADVDATAEX |
advertising parameters / raw advert / auto-built advert |
AT+BLEADVSTART / AT+BLEADVSTOP |
start / stop advertising |
AT+BLECONN / AT+BLEDISCONN |
open / close a connection |
AT+BLECONNPARAM |
query / update connection parameters |
AT+BLECFGMTU |
set ATT MTU |
AT+BLEGATTSSRV / AT+BLEGATTSCHAR |
(server) list services / characteristics |
AT+BLEGATTSNTFY / AT+BLEGATTSIND |
(server) notify / indicate a characteristic |
AT+BLEGATTSSETATTR |
(server) set a characteristic value |
AT+BLEGATTCPRIMSRV / AT+BLEGATTCINCLSRV / AT+BLEGATTCCHAR |
(client) discover primary / included services / characteristics |
AT+BLEGATTCRD / AT+BLEGATTCWR |
(client) read / write a characteristic |
AT+BLESPPCFG / AT+BLESPP |
configure / enter BLE serial-passthrough (SPP) |
AT+BLESECPARAM |
pairing / encryption parameters |
AT+BLEENC / AT+BLEENCRSP / AT+BLEKEYREPLY / AT+BLECONFREPLY |
start encryption / respond / supply passkey / confirm |
AT+BLEENCDEV / AT+BLEENCCLEAR |
list / clear bonded devices |
BLE security command names beyond the core set vary slightly by version; AT+CMD lists what the running build exposes.
8. MQTT commands
| Command | Function |
|---|---|
AT+MQTTUSERCFG |
scheme (TCP / TLS), client id, user, password, cert options |
AT+MQTTLONGCLIENTID / AT+MQTTLONGUSERNAME / AT+MQTTLONGPASSWORD |
set long client id / username / password |
AT+MQTTCONNCFG |
keep-alive, clean-session, last-will |
AT+MQTTALPN / AT+MQTTSNI |
TLS ALPN / SNI |
AT+MQTTCONN |
connect to a broker |
AT+MQTTPUB / AT+MQTTPUBRAW |
publish (string / long-raw) |
AT+MQTTSUB / AT+MQTTUNSUB |
subscribe / unsubscribe |
AT+MQTTCLEAN |
disconnect and free the MQTT client |
9. HTTP commands
| Command | Function |
|---|---|
AT+HTTPCLIENT |
one-shot HTTP request (GET / POST / PUT / HEAD…) |
AT+HTTPGETSIZE |
content length of a resource |
AT+HTTPCGET |
fetch a resource |
AT+HTTPCPOST / AT+HTTPCPUT |
POST / PUT a fixed-length body |
AT+HTTPURLCFG |
set a long URL out of band |
AT+HTTPCHEAD |
set / query custom request headers |
AT+HTTPCFG |
client options (content-type, transport, etc.) |
10. Other and configurable sets
- BluFi (default):
AT+BLUFI,AT+BLUFINAME,AT+BLUFISEND— Wi-Fi provisioning carried over BLE. - User (default):
AT+USERRAM,AT+USEROTA,AT+USERWKMCUCFG,AT+USERMCUSLEEPand similar hooks for user-defined RAM storage, user OTA, and a host-MCU wake/sleep handshake. - Compile-in only (need a custom ESP-AT build): see below — the Ant64 build enables all of these.
The sets below are absent from Espressif's prebuilt binary but are real ESP-AT commands a local build switches on. The Ant64's N16R8 / N32R8 flash (§1) has room to enable them all, so on the Ant64 build they are available.
FileSystem — a FAT partition in the C5's flash, driven by one multi-operation command:
| Command | Function |
|---|---|
AT+FS |
filesystem op on a flash FAT file — list, read, write, delete, or query size |
WebSocket — up to three client connections, over TCP or TLS:
| Command | Function |
|---|---|
AT+WSCFG |
per-link config: ping interval / timeout, buffer size, TLS auth |
AT+WSOPEN |
open (or query) a WebSocket connection |
AT+WSSEND |
send data on a connection |
AT+WSDATAFMT |
set the received-data format |
AT+WSCLOSE |
close a connection |
Web server — a browser-based config portal served from the C5:
| Command | Function |
|---|---|
AT+WEBSERVER |
start / stop a captive-portal web server for Wi-Fi provisioning and browser OTA (HTML from a FAT partition or embedded files; FATFS needs FileSystem above) |
Driver — lets the host drive the C5's own ADC / PWM / I2C / SPI peripherals over the AT link:
| Command | Function |
|---|---|
AT+DRVADC |
read an ADC channel |
AT+DRVPWMINIT / AT+DRVPWMDUTY / AT+DRVPWMFADE |
PWM init / set duty / fade |
AT+DRVI2CINIT |
initialise the I2C master |
AT+DRVI2CRD / AT+DRVI2CWRDATA / AT+DRVI2CWRBYTES |
I2C read / write data / write ≤ 4 bytes |
AT+DRVSPICONFGPIO / AT+DRVSPIINIT |
configure SPI pins / init the SPI master |
AT+DRVSPIRD / AT+DRVSPIWR |
SPI read / write |
WPA2-Enterprise — adds AT+CWJEAP to the Wi-Fi set (§5) for enterprise-AP association.
11. Using it from DeMon / AntOS
The natural pattern is a small AT-driver task in AntOS that owns the C5 link: bring-up (AT, AT+GMR, AT+CWINIT, AT+CWMODE), join (AT+CWJAP), then either raw sockets (AT+CIPSTART / AT+CIPSEND, with inbound data arriving as +IPD notifications) or a higher-level set (MQTT, HTTP). Two things worth designing around:
- Command vs passthrough. For bulk single-socket streaming,
AT+CIPMODE=1plusAT+CIPSENDputs the link in transparent passthrough so DeMon streams raw bytes with no per-packet framing;+++returns to command mode.AT+SAVETRANSLINKcan make the C5 enter passthrough automatically at boot. - Persistence and flash wear.
AT+SYSSTOREcontrols whether Wi-Fi / config changes are written to NVS. Turning it off keeps joins RAM-only — sensible if DeMon re-provisions the C5 from AntOS on every boot and wants to spare the C5's flash.
Because Wi-Fi and BLE share a single antenna, heavy simultaneous use of both contends for the radio; AT+RFPOWER tunes TX power to the enclosure and regulatory limits.
Conventions for the custom extensions (§12–§15)
Command grammar (§12–§15)
AT+<PREFIX><CMD>[=<param1>,<param2>,…]<CR><LF>
- Every command line is terminated with
\r\n. - Parameters are comma-separated (no spaces around commas unless inside a quoted string).
- Query (read) form:
AT+<PREFIX><CMD>?— returns current value(s) or configuration. - Execute / set form:
AT+<PREFIX><CMD>=<params>— performs an action or writes config. - Test form (where implemented):
AT+<PREFIX><CMD>=?— returns supported parameter ranges.
Parameter types
| Notation | Meaning | Example |
|---|---|---|
<uint> |
Unsigned decimal integer | 868, 22 |
<int> |
Signed decimal integer | -120 |
<hex> |
Hexadecimal string (no 0x prefix) |
1A2B3C |
<hex16> |
16-character hex string | A1B2C3D4E5F67890 |
<hex32> |
32-character hex string | 00112233445566778899AABBCCDDEEFF |
<string> |
Quoted if it contains commas, spaces, or control chars | "My Network" |
<addr> |
MAC address / BSSID format | A1:B2:C3:D4:E5:F6 |
<ipv4> |
IPv4 dotted decimal | 192.168.1.1 |
<freq> |
Frequency in Hz | 868000000 |
<dBm> |
Power in dBm | 14 |
<enum> |
One of a fixed set of values; listed per command | 0, 1, 2 |
[opt] |
Optional parameter |
Response grammar
Success:
<CR><LF>
[+PREFIX: <field1>,<field2>,...]<CR><LF>
...
OK<CR><LF>
Error:
<CR><LF>
ERROR<CR><LF>
Or, if AT+SYSLOG=1 is enabled:
<CR><LF>
+ERROR: <err_code>,<err_msg><CR><LF>
Unsolicited result codes (URCs):
<CR><LF>
+PREFIX: <field1>,<field2>,...<CR><LF>
- Fields are comma-separated.
- Strings containing commas, spaces, or quotes are enclosed in double quotes
". - Binary / raw data payloads are either hex-encoded or sent as length-prefixed blocks (noted per command).
- URCs always start with
+and end with\r\n.
Custom-extension error codes
| Code | Meaning |
|---|---|
600 |
Generic LoRa radio error |
601 |
LoRa not initialised / no response from LR2021 |
602 |
LoRa TX timeout |
603 |
LoRa invalid parameter combination |
610 |
GNSS not powered / no fix |
611 |
GNSS unsupported command / rate |
620 |
RF analysis: monitor mode not available (Wi-Fi station active) |
621 |
RF analysis: FATFS not available (capture storage) |
622 |
RF analysis: CSI not supported by current Wi-Fi config |
630 |
IoT stack: requested stack not compiled in |
631 |
IoT stack: mode change requires restart |
632 |
IoT stack: not joined / not provisioned |
640 |
Invalid argument count or type |
641 |
Command not available in current radio profile |
12. LoRa Plus (LR2021) Commands
Prefix: LORA
Radio: Semtech LR2021 (Seeed Wio-LR2021 module) on the C5 SPI bus — a 4th-generation LoRa Plus transceiver
Note: Not present in stock ESP-AT. Added as custom user commands, built on Semtech's LoRa USP / LR20xx radio driver ported to the C5 (replacing the older SX126x driver). LoRa and LoRaWAN share the same namespace; AT+LORANWM selects the mode.
The LR2021 is backward-compatible with LoRa / LoRaWAN, so the point-to-point and LoRaWAN commands in this section carry over unchanged from the SX1262 design. It adds capabilities the SX1262 lacked — dual-band operation (Sub-GHz 863–928 MHz and 2.4 GHz ISM), an S-band satellite / NTN path (≈1.9–2.5 GHz), and high-speed FLRC up to 2.6 Mbps (fast enough for image / audio / bulk-OTA over the link), plus LR-FHSS, (G)FSK and OQPSK. The AT surface for those newer modes is sketched in §12.6; its exact grammar is being finalised during EVK bring-up.
Radio namespacing. The Ant64 has two 2.4 GHz-capable radios — the C5 (Wi-Fi 6 + BLE) and the LR2021 (BLE / 802.15.4 / LoRa). Commands for the C5 keep their plain names (AT+BLESCAN, AT+CWLAP, …); commands that target the LR2021 for a capability the C5 also has are tagged AT+LR… (e.g. AT+LRBLESCAN = BLE scan on the LR2021). LoRa-only commands stay in the AT+LORA… namespace — only the LR2021 has LoRa, so there's no ambiguity. Keeping the literal AT+ prefix matters: the ESP-AT parser dispatches on AT, so an ATLR+ prefix would break it — the LR goes on the command name, not the prefix.
2.4 GHz coexistence. The two radios are independent chips on separate antennas, mounted ~30–40 cm apart (opposite edges of the board) — about 2.5–3 wavelengths at 2.4 GHz, so the isolation between them is substantial and concurrent 2.4 GHz operation is practical: dual-BLE (scan on one, advertise on the other), or the C5 on Wi-Fi while the LR2021 runs a separate 802.15.4 mesh. The LR2021's 2.4 GHz TX also caps at +12 dBm (vs +22 at Sub-GHz), making it a quiet neighbour. Only the worst case — the C5 running high-duty Wi-Fi while the LR2021 tries to receive on 2.4 GHz — benefits from a coexistence hand-off line between the two, extending the C5's existing internal Wi-Fi/BLE coex arbitration.
12.1 Power & initialisation
AT+LORAPWR
Power the LR2021 on or off (toggles GPIO enable line and performs reset sequence).
| Syntax | Response |
|---|---|
AT+LORAPWR? |
+LORAPWR: <state> |
AT+LORAPWR=<state> |
OK or ERROR |
Parameters:
<state>:0= power off,1= power on and reset
Errors: 600, 601
AT+LORARST
Soft-reset the LR2021 (digital reset via SPI command).
| Syntax | Response |
|---|---|
AT+LORARST |
OK or ERROR |
Errors: 600, 601
AT+LORAFACTORY
Restore LR2021 factory defaults (clears volatile config, not flash).
| Syntax | Response |
|---|---|
AT+LORAFACTORY |
OK or ERROR |
AT+LORAVER
Query the LR2021 firmware / chip version.
| Syntax | Response |
|---|---|
AT+LORAVER? |
+LORAVER: <chip_type>,<version_hex> |
Response fields:
<chip_type>:LR2021<version_hex>: 4-digit hex version code
AT+LORAUID
Query the LR2021 unique chip ID.
| Syntax | Response |
|---|---|
AT+LORAUID? |
+LORAUID: <hex16> |
12.2 Mode selection (P2P vs LoRaWAN)
AT+LORANWM
Select network work mode.
| Syntax | Response |
|---|---|
AT+LORANWM? |
+LORANWM: <mode> |
AT+LORANWM=<mode> |
OK or ERROR |
Parameters:
<mode>:0— Point-to-point (raw LoRa, default)1— LoRaWAN
Note: Changing mode resets the LoRa stack to default parameters for that mode.
12.3 Point-to-point (P2P) parameters
AT+LORABAND
Set the centre frequency.
| Syntax | Response |
|---|---|
AT+LORABAND? |
+LORABAND: <freq_hz> |
AT+LORABAND=<freq_hz> |
OK or ERROR |
Parameters:
<freq_hz>: Centre frequency in Hz. Common values:433000000(EU433)868000000(EU868)915000000(US915)923000000(AS923)
Range: 150000000 – 960000000 (hardware limited)
Default: 868000000
Errors: 603
AT+LORAPARAM
Set the modem parameters (spreading factor, bandwidth, coding rate, preamble).
| Syntax | Response |
|---|---|
AT+LORAPARAM? |
+LORAPARAM: <sf>,<bw>,<cr>,<preamble> |
AT+LORAPARAM=<sf>,<bw>,<cr>,<preamble> |
OK or ERROR |
Parameters:
<sf>: Spreading factor.7,8,9,10,11,12<bw>: Bandwidth in kHz.125,250<cr>: Coding rate denominator.5(4/5),6(4/6),7(4/7),8(4/8)<preamble>: Preamble length in symbols.8–65535
Default: 9,125,5,12
Errors: 603
AT+LORAADDR
Set this node's P2P address.
| Syntax | Response |
|---|---|
AT+LORAADDR? |
+LORAADDR: <addr> |
AT+LORAADDR=<addr> |
OK or ERROR |
Parameters:
<addr>: 16-bit unsigned address.0–65535
Default: 0
AT+LORANETID
Set the network / group ID (P2P filter).
| Syntax | Response |
|---|---|
AT+LORANETID? |
+LORANETID: <netid> |
AT+LORANETID=<netid> |
OK or ERROR |
Parameters:
<netid>: Network ID.0–65535
Default: 0
AT+LORATXPWR
Set RF output power.
| Syntax | Response |
|---|---|
AT+LORATXPWR? |
+LORATXPWR: <dBm> |
AT+LORATXPWR=<dBm> |
OK or ERROR |
Parameters:
<dBm>: TX power in dBm.-9–+22
Default: 14
Errors: 603
AT+LORAMODE
Set the transceiver work mode.
| Syntax | Response |
|---|---|
AT+LORAMODE? |
+LORAMODE: <mode> |
AT+LORAMODE=<mode> |
OK or ERROR |
Parameters:
<mode>:0— Transceiver (TX + RX, default)1— Sleep (low-power standby)2— RX duty-cycle (periodic receive for power saving)
12.4 P2P data transfer
AT+LORASEND
Transmit a payload to a destination address.
| Syntax | Response |
|---|---|
AT+LORASEND=<dest_addr>,<len>,<data_hex> |
OK or ERROR |
Overloaded command: this P2P signature applies when AT+LORANWM (§12.2) is in P2P mode; in LoRaWAN mode AT+LORASEND instead takes <port>,<confirm>,<len>,<data_hex> (§12.5). The firmware selects the parser from the active mode, not the argument count.
Parameters:
<dest_addr>: Destination 16-bit address.0–65535(65535= broadcast)<len>: Payload length in bytes.0–255<data_hex>: Hex-encoded payload. Length must equal<len>× 2 characters.
URC on TX complete:
+LORATX: <dest_addr>,<len>,<status>
<status>:0= success,1= timeout,2= CRC error (RX ack if implemented)
Errors: 600, 602, 640
+LORARCV (URC)
Unsolicited inbound packet.
+LORARCV: <src_addr>,<len>,<data_hex>,<rssi>,<snr>
Fields:
<src_addr>: Source 16-bit address<len>: Payload length in bytes<data_hex>: Hex-encoded payload<rssi>: Received signal strength indicator (dBm)<snr>: Signal-to-noise ratio (dB, signed integer)
12.5 LoRaWAN parameters
AT+LORADEVEUI
Set the device EUI (OTAA).
| Syntax | Response |
|---|---|
AT+LORADEVEUI? |
+LORADEVEUI: <hex16> |
AT+LORADEVEUI=<hex16> |
OK or ERROR |
AT+LORAAPPEUI
Set the application EUI (OTAA).
| Syntax | Response |
|---|---|
AT+LORAAPPEUI? |
+LORAAPPEUI: <hex16> |
AT+LORAAPPEUI=<hex16> |
OK or ERROR |
AT+LORAAPPKEY
Set the application key (OTAA).
| Syntax | Response |
|---|---|
AT+LORAAPPKEY? |
+LORAAPPKEY: <hex32> |
AT+LORAAPPKEY=<hex32> |
OK or ERROR |
AT+LORADEVADDR
Set the device address (ABP).
| Syntax | Response |
|---|---|
AT+LORADEVADDR? |
+LORADEVADDR: <hex8> |
AT+LORADEVADDR=<hex8> |
OK or ERROR |
AT+LORAJOIN
Join the LoRaWAN network (OTAA or ABP).
| Syntax | Response |
|---|---|
AT+LORAJOIN=<mode>[,<timeout_sec>] |
OK (async) or ERROR |
Parameters:
<mode>:0= OTAA,1= ABP<timeout_sec>: Join attempt timeout.30–600. Default300.
URC:
+LORAJOIN: <status> // 0=success, 1=fail, 2=no_free_channel
Errors: 632
AT+LORACLASS
Set the LoRaWAN device class.
| Syntax | Response |
|---|---|
AT+LORACLASS? |
+LORACLASS: <class> |
AT+LORACLASS=<class> |
OK or ERROR |
Parameters:
<class>:A,B, orC
AT+LORADR
Set the data rate.
| Syntax | Response |
|---|---|
AT+LORADR? |
+LORADR: <dr> |
AT+LORADR=<dr> |
OK or ERROR |
Parameters:
<dr>: Data rate index.0–7(region-dependent; see regional spec)
AT+LORABAND (LoRaWAN context)
In LoRaWAN mode, AT+LORABAND sets the regional band index rather than raw frequency.
| Syntax | Response |
|---|---|
AT+LORABAND? |
+LORABAND: <band> |
AT+LORABAND=<band> |
OK or ERROR |
Parameters:
<band>:0= EU8681= US9152= AU9153= AS9234= KR9205= IN8656= EU433
AT+LORASEND (LoRaWAN context)
Uplink data.
| Syntax | Response |
|---|---|
AT+LORASEND=<port>,<confirm>,<len>,<data_hex> |
OK (async) or ERROR |
Overloaded command: this LoRaWAN signature applies when AT+LORANWM (§12.2) is in LoRaWAN mode; in P2P mode AT+LORASEND instead takes <dest_addr>,<len>,<data_hex> (§12.4). The firmware selects the parser from the active mode, not the argument count.
Parameters:
<port>: LoRaWAN port.1–223<confirm>:0= unconfirmed,1= confirmed<len>: Payload length.0–242<data_hex>: Hex-encoded payload
URCs:
+LORATX: <port>,<len>,<status> // 0=success, 1=no_ack, 2=timeout
+LORARX: <port>,<len>,<data_hex>,<rssi>,<snr> // downlink received
AT+LORAUSEND
Confirmed uplink with retry control.
| Syntax | Response |
|---|---|
AT+LORAUSEND=<port>,<retries>,<len>,<data_hex> |
OK (async) or ERROR |
Parameters:
<retries>: Max retries if no ACK.0–8
AT+LORANJS
Query join status.
| Syntax | Response |
|---|---|
AT+LORANJS? |
+LORANJS: <status> |
Response:
<status>:0= not joined,1= joined,2= joining
12.6 New-radio capabilities (LR2021) — provisional
The LR2021 exposes capabilities beyond the SX1262. Everything below extends the existing LORA namespace and is driven through Semtech's LoRa USP driver. The specs are provisional — command and parameter names will be finalised during EVK bring-up; the stubs show the intended shape. The underlying operations map to documented LR2021 host commands (packet-type/modulation select, RTToF ranging, CAD, duty-cycled RX, sleep/standby, GetRandomNumber, GetRssiInst, GetTemp, SetTxTestMode) — see the LR2021 datasheet (Rev 1.1). Error codes 600 (general) and 601 (radio not responding) apply throughout; individual modes may add codes later.
AT+LORABAND
Select the operating RF band (provisional) — the LR2021 is multi-band, so this chooses the front-end port and default frequency plan.
| Syntax | Response |
|---|---|
AT+LORABAND? |
+LORABAND: <band> |
AT+LORABAND=<band> |
OK or ERROR |
Parameters:
<band>:SUBGHZ(the chip tunes 150–960 MHz; default LoRaWAN sub-GHz plan, backward-compatible) ·2G4(2.4 GHz ISM, global single-SKU) ·SBAND(S-band NTN / satellite, ≈1.9–2.5 GHz; licensed L-band ≈1.5–2.0 GHz is also supported)
AT+LORAMOD
Select the modulation (provisional). The P2P and LoRaWAN commands (§12.2–§12.5) then run over whichever modulation is active.
| Syntax | Response |
|---|---|
AT+LORAMOD? |
+LORAMOD: <mod> |
AT+LORAMOD=<mod> |
OK or ERROR |
Parameters:
<mod>:LORA(default, ≤200 kbps) ·FLRC(≤2.6 Mbps) ·LRFHSS·FSK·GFSK·OQPSK·OOK
AT+LORAFLRC
Configure FLRC parameters (active when AT+LORAMOD=FLRC) (provisional) — the high-speed mode for image / audio / bulk transfer.
| Syntax | Response |
|---|---|
AT+LORAFLRC? |
+LORAFLRC: <bitrate>,<cr>,<bt> |
AT+LORAFLRC=<bitrate>,<cr>,<bt> |
OK or ERROR |
Parameters:
<bitrate>: FLRC bitrate in kbps, up to2600<cr>: coding rate<bt>: Gaussian filter BT
AT+LORARANGE
Measure distance to a peer node by Round-Trip Time-of-Flight (RTToF) ranging (provisional).
| Syntax | Response |
|---|---|
AT+LORARANGE=<role>,<peer_addr> |
+LORARANGE: <distance_m>,<rssi>,<quality> then OK, or ERROR |
Parameters:
<role>:0= subordinate (responder) ·1= manager (initiator, reports the distance)<peer_addr>: address of the node to range against<distance_m>: measured distance in metres (from the RTToF exchange)<quality>: ranging confidence / status (from the radio's ranging stats)
AT+LORASCAN
Spectral scan — sweep a frequency range and report RSSI per step (provisional). Receive-only. Built on the radio's instantaneous-RSSI read (GetRssiInst): with no packet present, that value is the RF noise floor at each frequency, so the sweep is a firmware loop over GetRssiInst, not a single chip command.
| Syntax | Response |
|---|---|
AT+LORASCAN=<start_hz>,<stop_hz>,<step_hz> |
+LORASCAN: <freq_hz>,<rssi> per bin, then OK |
Parameters:
<start_hz>/<stop_hz>: sweep range (within the active band)<step_hz>: bin width
AT+LORACAD
Run the LR2021's enhanced Channel Activity Detection (provisional) — listen-before-talk / wake-on-radio. The radio also supports Multi-SF CAD (sensing several spreading factors at once) and Fast CAD (adaptive threshold, early termination).
| Syntax | Response |
|---|---|
AT+LORACAD=<symbols> |
+LORACAD: <result> then OK |
Parameters:
<symbols>: number of symbols to sense<result>:0= clear ·1= activity detected
AT+LORAPER
Packet-error-rate / ping-pong link test between two nodes (provisional) — for range and quality checks.
| Syntax | Response |
|---|---|
AT+LORAPER=<role>,<count> |
+LORAPER: <sent>,<recv>,<per_pct>,<avg_rssi> then OK |
Parameters:
<role>:0= receiver ·1= transmitter<count>: number of packets
AT+LORASLEEP
Put the radio into a low-power sleep or standby state (provisional) — distinct from AT+LORAPWR, which cuts the GPIO enable line. Maps to SetSleep / SetStandby.
| Syntax | Response |
|---|---|
AT+LORASLEEP=<mode> |
OK or ERROR |
Parameters:
<mode>:STANDBY(fast wake, config retained) ·SLEEP(deep, ~470 nA, wakes on timer / DIO)
AT+LORARXDC
Enter Rx Duty-Cycle mode (provisional) — the radio periodically wakes to listen, then drops back to sleep until a packet arrives (SetRxDutyCycle). Wake-on-radio for battery beacons and sensors.
| Syntax | Response |
|---|---|
AT+LORARXDC=<rx_ms>,<sleep_ms> |
OK or ERROR |
Parameters:
<rx_ms>: listen window per cycle<sleep_ms>: sleep interval between windows
AT+LORATEMP
Read the radio's on-chip temperature (provisional) — GetTemp.
| Syntax | Response |
|---|---|
AT+LORATEMP? |
+LORATEMP: <celsius> then OK |
AT+LORACW
Transmit a continuous-wave / test carrier (provisional) — SetTxTestMode. For antenna tuning, front-end / coexistence checks and certification during bring-up; TX, so mind the front-end limits.
| Syntax | Response |
|---|---|
AT+LORACW=<state> |
OK or ERROR |
Parameters:
<state>:0= stop ·1= start CW at the current band / frequency / power
AT+LORARAND
Read hardware random bytes from the radio's true RNG (provisional) — the LR2021 has an on-chip random-number generator (GetRandomNumber), handy for nonces, keys, seeds and games.
| Syntax | Response |
|---|---|
AT+LORARAND=<n> |
+LORARAND: <hex> then OK |
Parameters:
<n>: number of random bytes to return (hex-encoded in the response)
AT+LORASAT
Enable the S-band satellite / NTN uplink profile (provisional). Uses S-band + LR-FHSS through a licensed satellite-IoT service — not open transmission.
| Syntax | Response |
|---|---|
AT+LORASAT? |
+LORASAT: <state>,<profile> |
AT+LORASAT=<state>,<profile> |
OK or ERROR |
Parameters:
<state>:0= off ·1= on<profile>: satellite-service network profile (operator-specific)
AT+LORATXP
Set transmit power (provisional).
| Syntax | Response |
|---|---|
AT+LORATXP? |
+LORATXP: <dbm> |
AT+LORATXP=<dbm> |
OK or ERROR |
Parameters:
<dbm>: target output power — band-dependent max: up to +22 dBm at Sub-GHz, up to +12 dBm at 2.4 GHz; 32 dB range in 0.5 dB steps.
Front-end caution. The switchless PA/LNA share the RF node; transmitting above +6 dBm needs external front-end protection, and absolute-max input is +10 dBm.
Multi-protocol / second-radio headroom. The silicon has PHY-level hardware for Amazon Sidewalk, Meshtastic, Wi-SUN, Wireless M-Bus, Z-Wave, BLE 5 and 802.15.4. With the LR2021 ~30–40 cm from the C5 on its own antenna, its BLE and 802.15.4 are a genuine second 2.4 GHz radio, not dead weight — dual-BLE, or a separate 802.15.4 mesh running alongside the C5's Wi-Fi (see the coexistence note in the §12 intro). Each is exposed only when its stack is ported to the C5 — a real undertaking per protocol — and when exposed it's namespaced AT+LR… to distinguish it from the C5's own BLE / Thread / Zigbee. None are wired up today: a designed-in option, not a committed feature.
RF note. The switchless front end (§
AT+LORATXP) and the 2.4 GHz overlap with the C5's Wi-Fi / BLE are the two board-level RF concerns; the ~30–40 cm antenna separation and coexistence approach are covered in the §12 intro.
13. GPS / GNSS Commands
Prefix: GNSS
Receiver: u-blox NEO-M10 (marking NEO-M10 1612F-00-010) on C5 UART1
Note: Not present in stock ESP-AT. Added as custom user commands.
13.1 Power & control
AT+GNSSPWR
Power the GNSS receiver and start/stop NMEA parsing.
| Syntax | Response |
|---|---|
AT+GNSSPWR? |
+GNSSPWR: <state> |
AT+GNSSPWR=<state> |
OK or ERROR |
Parameters:
<state>:0= power off,1= power on and start parsing
Note: If the module has a hardware enable line wired to C5 GPIO, this toggles it.
Errors: 610
AT+GNSSCLR
Clear assistance / almanac data to force a cold start.
| Syntax | Response |
|---|---|
AT+GNSSCLR |
OK or ERROR |
AT+GNSSVER
Query receiver model and firmware version.
| Syntax | Response |
|---|---|
AT+GNSSVER? |
+GNSSVER: <model>,<fw_ver>,<hw_ver> |
Response fields:
<model>:NEO-M10N<fw_ver>: Firmware version string<hw_ver>: Hardware version string
13.2 Configuration
AT+GNSSCFG
Configure constellations, baud rate, and similar.
| Syntax | Response |
|---|---|
AT+GNSSCFG? |
+GNSSCFG: <constellations>,<baud>,<dyn_model> |
AT+GNSSCFG=<constellations>,<baud>,<dyn_model> |
OK or ERROR |
Parameters:
<constellations>: Bitmask of enabled constellations:1= GPS2= GLONASS4= Galileo8= BeiDou- Common combos:
1(GPS only),5(GPS+Galileo),15(all)
<baud>: UART baud rate for NEO-M10.9600,19200,38400,57600,115200. Default9600.<dyn_model>: Dynamic platform model:0= Portable (default)2= Stationary3= Pedestrian4= Automotive
Errors: 611
AT+GNSSRATE
Set position update rate.
| Syntax | Response |
|---|---|
AT+GNSSRATE? |
+GNSSRATE: <hz> |
AT+GNSSRATE=<hz> |
OK or ERROR |
Parameters:
<hz>: Update rate in Hz.1,2,5,10
Note: NEO-M10 supports up to 10 Hz in standard multi-constellation mode. Higher rates require GPS-only mode and are not guaranteed.
Default: 1
Errors: 611
AT+GNSSCMD
Pass a raw UBX or NMEA command to the receiver.
| Syntax | Response |
|---|---|
AT+GNSSCMD=<protocol>,<cmd_hex> |
OK or ERROR |
Parameters:
<protocol>:0= NMEA,1= UBX<cmd_hex>: Hex-encoded command string
Response: protocol-tagged, so the host can dispatch without inspecting the payload:
- NMEA reply (within 1 second):
+GNSSCMD: NMEA,<reply_string> - UBX reply:
+GNSSCMD: UBX,<reply_hex> - No reply: only
OKis returned.
Errors: 610
13.3 Position queries
AT+GNSSINF
One-shot fix summary.
| Syntax | Response |
|---|---|
AT+GNSSINF? |
+GNSSINF: <fix_status>,<utc_date>,<utc_time>,<lat>,<lon>,<alt>,<speed>,<course>,<fix_mode>,<hdop>,<pdop>,<vdop>,<sats_used>,<sats_in_view> |
Response fields:
<fix_status>:0= no fix,1= fix,2= differential fix<utc_date>:YYYYMMDD<utc_time>:HHMMSS.sss<lat>: Latitude in degrees, signed decimal (e.g.51.5074)<lon>: Longitude in degrees, signed decimal<alt>: Altitude above mean sea level in metres<speed>: Ground speed in km/h<course>: Course over ground in degrees<fix_mode>:1= no fix,2= 2D,3= 3D<hdop>/<pdop>/<vdop>: Dilution of precision<sats_used>: Satellites used for fix<sats_in_view>: Satellites in view
Note: If no fix, lat/lon/alt are 0 and fix_status is 0.
AT+GNSSLOC
Shorter location-only query.
| Syntax | Response |
|---|---|
AT+GNSSLOC? |
+GNSSLOC: <fix_quality>,<lat>,<lon>,<utc_time> |
Response fields:
<fix_quality>:0= invalid,1= GPS fix,2= DGPS fix<lat>/<lon>: Signed decimal degrees<utc_time>:HHMMSS.sss
AT+GNSSNMEA
Fetch a specific NMEA sentence on demand.
| Syntax | Response |
|---|---|
AT+GNSSNMEA=<sentence> |
$<sentence>,...*<cs><CR><LF>OK or ERROR |
Parameters:
<sentence>:GGA,RMC,GSV,GSA,VTG,GLL
Note: Returns the most recent cached sentence of that type. If none cached, waits up to 2 seconds for the receiver to emit one.
13.4 Unsolicited reporting
AT+GNSSURC
Enable/disable periodic position push.
| Syntax | Response |
|---|---|
AT+GNSSURC? |
+GNSSURC: <interval_sec> |
AT+GNSSURC=<interval_sec> |
OK or ERROR |
Parameters:
<interval_sec>: Report interval in seconds.0= disable URC.1–3600.
URC format:
+GNSS: <fix_status>,<utc_date>,<utc_time>,<lat>,<lon>,<alt>,<speed>,<course>,<sats_used>
13.5 Raw passthrough
AT+GNSSTST
Raw-NMEA passthrough mode.
| Syntax | Response |
|---|---|
AT+GNSSTST? |
+GNSSTST: <state> |
AT+GNSSTST=<state> |
OK or ERROR |
Parameters:
<state>:0= off (parsed mode, default),1= on (raw NMEA streamed to AT link)
Note: When enabled, every NMEA sentence received from the receiver is emitted on the AT link as raw text (not prefixed with +GNSS:). This lets AntOS parse NMEA itself. All other AT+GNSS… commands remain functional but may interleave with raw sentences.
14. RF Analysis and Link Diagnostics
Prefix: MON (passive monitors), WIFI (Wi-Fi tools), BLE (BLE tools), IPERF, LINKQ, LATTEST, ANTBENCH
Note: Not present in stock ESP-AT. Added as custom user commands.
Authorised use only: observation-only for your own networks and devices.
14.1 Channel & survey
AT+CHANNELSCORE
Recommend best operating channel.
| Syntax | Response |
|---|---|
AT+CHANNELSCORE? |
+CHANNELSCORE: <band>,<ch1>,<score1>,<ch2>,<score2>,... |
AT+CHANNELSCORE=<band> |
+CHANNELSCORE: <band>,<ch1>,<score1>,... |
Parameters:
<band>:0= 2.4 GHz,1= 5 GHz. If omitted in query, scores both bands.
Response fields:
<band>:0or1- Channel-score pairs:
<channel>,<score>where score is0–100(higher = cleaner)
AT+WIFIHEATMAP
Long-term channel-utilisation survey.
| Syntax | Response |
|---|---|
AT+WIFIHEATMAP=<action>[,<duration_sec>] |
OK or +WIFIHEATMAP: <data> or ERROR |
Parameters:
<action>:0= stop survey1= start survey2= query results
<duration_sec>: Survey duration if starting.10–3600. Default60.
Response (action=2):
+WIFIHEATMAP: <channel>,<busy_pct>,<ap_count>,<sta_count>,<noise_dbm>,<avg_rssi>
(Repeated per channel, terminated by OK)
Errors: 620
AT+WIFICHAN
Park the radio on a specific channel.
| Syntax | Response |
|---|---|
AT+WIFICHAN? |
+WIFICHAN: <channel>,<dwell_ms> |
AT+WIFICHAN=<channel>[,<dwell_ms>] |
OK or ERROR |
Parameters:
<channel>: Wi-Fi channel number.1–14(2.4 GHz),36–177(5 GHz)<dwell_ms>: Dwell time in milliseconds.50–10000. Default100.
Note: Requires Wi-Fi to be in monitor mode or disconnected. Returns ERROR if station is connected.
Errors: 620
14.2 Capture & CSI
AT+PCAPSTART
Start promiscuous monitor capture.
| Syntax | Response |
|---|---|
AT+PCAPSTART[=<filename>][,<mode>] |
OK or ERROR |
Parameters:
<filename>: Name for FATFS file. Max 31 chars. If omitted, stream mode.<mode>:0= stream to UART as+PCAP:URCs (see below) — the AT parser stays live, soAT+PCAPSTOPcan end the session at any time1= record to FATFS (default if filename given)
URC (mode 0):
+PCAP: <seq>,<hex>
<seq>: monotonic chunk counter<hex>: hex-encoded captured PCAP record (one frame per URC)
Note: Capture takes the radio off normal station/AP duty. Wi-Fi connectivity pauses. Mode 0 streams hex URCs rather than raw binary specifically so the AT parser is never suspended.
Errors: 620, 621
AT+PCAPSTOP
Stop capture.
| Syntax | Response |
|---|---|
AT+PCAPSTOP |
+PCAP: <records>,<bytes> then OK or ERROR |
Response fields:
<records>: Number of frames captured<bytes>: Total bytes captured
AT+WIFICAPCFG
Configure capture filter.
| Syntax | Response |
|---|---|
AT+WIFICAPCFG? |
+WIFICAPCFG: <frame_class>,<bssid_filter>,<max_records> |
AT+WIFICAPCFG=<frame_class>[,<bssid_filter>][,<max_records>] |
OK or ERROR |
Parameters:
<frame_class>: Bitmask:1= Management2= Control4= Data7= All (default)
<bssid_filter>: Optional BSSID to filter (AA:BB:CC:DD:EE:FForany). Defaultany.<max_records>: Max frames to capture.0= unlimited. Default0.
AT+CSISTREAM
Start continuous CSI capture.
| Syntax | Response |
|---|---|
AT+CSISTREAM=<action>[,<interval_ms>] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<interval_ms>: Sampling interval.10–1000. Default100.
URC:
+CSI: <timestamp>,<subcarrier_count>,<amplitude_hex>,<phase_hex>
Errors: 620, 622
AT+CSISTATS
Report CSI statistics.
| Syntax | Response |
|---|---|
AT+CSISTATS? |
+CSISTATS: <samples>,<avg_amp>,<std_amp>,<motion_detected> |
Response fields:
<samples>: Total CSI samples since start<avg_amp>: Average amplitude across subcarriers<std_amp>: Standard deviation of amplitude<motion_detected>:0or1
AT+PRESENCE
Occupancy / motion detection using CSI.
| Syntax | Response |
|---|---|
AT+PRESENCE? |
+PRESENCE: <state>,<confidence> |
AT+PRESENCE=<action> |
OK or ERROR |
Parameters:
<action>:0= disable,1= enable
Response / URC:
+PRESENCE: <state>,<confidence>
<state>:0= vacant,1= occupied,2= motion detected<confidence>:0–100
14.3 BLE tracking
AT+BLETRACK
Track BLE advertisers over time.
| Syntax | Response |
|---|---|
AT+BLETRACK=<action>[,<duration_sec>] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<duration_sec>:10–3600. Default60.
URC:
+BLETRACK: <addr>,<addr_type>,<rssi>,<name>,<last_seen_sec>
AT+BLEIBEACONSCAN
Decode iBeacon / Eddystone frames.
| Syntax | Response |
|---|---|
AT+BLEIBEACONSCAN=<action> |
OK or ERROR |
Parameters:
<action>:0= stop,1= start
URC:
+IBEACON: <type>,<uuid>,<major>,<minor>,<tx_power>,<rssi> // iBeacon
+EDDYSTONE: <type>,<namespace>,<instance>,<rssi> // Eddystone
14.4 Service discovery
AT+NETDISCOVER
Discover mDNS / SSDP services.
| Syntax | Response |
|---|---|
AT+NETDISCOVER=<protocol>,<service>[,<timeout_sec>] |
OK + URCs or ERROR |
Parameters:
<protocol>:0= mDNS,1= SSDP<service>: Service type string, e.g."_http._tcp"or"upnp:rootdevice"<timeout_sec>:1–30. Default5.
URC:
+NETDISCOVER: <ip>,<port>,<name>,<txt>
14.5 Logging & diagnostics
AT+RFLOGGER
Periodic RF environment logging.
| Syntax | Response |
|---|---|
AT+RFLOGGER=<action>[,<interval_sec>] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<interval_sec>:5–300. Default30.
URC:
+RFLOG: <timestamp>,<wifi_ch>,<wifi_rssi>,<ble_dev_count>,<noise_floor>
AT+WIFIDIAG
Complete RF health report.
| Syntax | Response |
|---|---|
AT+WIFIDIAG? |
+WIFIDIAG: <report> |
Response fields (multi-line):
+WIFIDIAG: <tx_packets>,<tx_retries>,<tx_failures>
+WIFIDIAG: <rx_packets>,<rx_crc_err>,<rx_drop>
+WIFIDIAG: <phy_rate>,<rssi>,<noise_floor>
AT+COEXSTAT
Wi-Fi / BLE coexistence statistics.
| Syntax | Response |
|---|---|
AT+COEXSTAT? |
+COEXSTAT: <wifi_state>,<ble_state>,<iot_state>,<lora_state>,<wifi_airtime_pct>,<ble_airtime_pct>,<last_conflict_reason> |
Response fields:
<wifi_state>:0= off,1= idle,2= STA connected,3= AP,4= monitor<ble_state>:0= off,1= idle,2= advertising,3= scanning,4= connected<iot_state>:0= off,1= thread,2= zigbee,3= matter,4= blemesh,5= meshlite<lora_state>:0= off,1= idle,2= TX,3= RX<wifi_airtime_pct>:0–100<ble_airtime_pct>:0–100<last_conflict_reason>:0= none,1= Wi-Fi priority,2= BLE priority,3= radio unavailable
14.6 Active link tests
AT+IPERF
TCP / UDP throughput test.
| Syntax | Response |
|---|---|
AT+IPERF=<role>,<proto>,<dir>,<host>,<port>,<duration_sec>[,<bw_mbps>] |
OK (async) or ERROR |
Parameters:
<role>:0= client,1= server<proto>:0= TCP,1= UDP<dir>:0= download (RX),1= upload (TX),2= bidirectional<host>: Target IP (client only).""or omitted for server.<port>: Port number.1–65535<duration_sec>: Test duration.1–600<bw_mbps>: UDP target bandwidth in Mbps (UDP only).0= unlimited.
URC:
+IPERF: <role>,<proto>,<dir>,<bytes>,<bps>,<jitter_ms>,<loss_pct>
Errors: 640
AT+LINKQ
One-shot link-quality snapshot.
| Syntax | Response |
|---|---|
AT+LINKQ? |
+LINKQ: <rssi>,<phy_rate>,<band>,<channel>,<tx_retries>,<rx_retries> |
Response fields:
<rssi>: dBm<phy_rate>: Mbps (e.g.72.2)<band>:0= 2.4 GHz,1= 5 GHz<channel>: Channel number<tx_retries>/<rx_retries>: Retry counts since connect
AT+LATTEST
Latency profile to a host.
| Syntax | Response |
|---|---|
AT+LATTEST=<host>,<count>,<interval_ms> |
OK (async) or ERROR |
Parameters:
<host>: IP address or hostname<count>: Number of probes.1–1000<interval_ms>: Interval between probes.10–10000
URC:
+LATTEST: <host>,<sent>,<received>,<min_ms>,<avg_ms>,<max_ms>,<jitter_ms>,<loss_pct>
AT+ANTBENCH
Antenna / placement comparison benchmark.
| Syntax | Response |
|---|---|
AT+ANTBENCH=<ant_sel>,<test_type>,<duration_sec> |
OK (async) or ERROR |
Parameters:
<ant_sel>: Antenna selection:0= onboard ceramic1= external port 12= external port 2
<test_type>:0= RSSI survey,1= throughput (needs peer),2= link quality<duration_sec>:5–300
URC:
+ANTBENCH: <ant_sel>,<test_type>,<score>,<rssi_avg>,<throughput_mbps>
Note: If the hardware has no RF switch, <ant_sel> is ignored and only onboard is tested.
14.7 Defensive security monitoring
The observation-only primitives above double as a home-network defence toolkit: the same monitor-mode capture that surveys RF also detects attacks against your own network, and the TCP/IP stack (§6) lets AntOS audit your own LAN. The guiding principle mirrors §14's stance and is worth stating plainly:
Defence is achieved by listening, not transmitting. Every capability here is receive-only or aimed inward at a network you own. There are deliberately no attack primitives – no deauthentication, no evil-twin AP, no beacon flood, no frame injection. You detect a deauth attack by hearing the flood, spot an evil twin by seeing the duplicate SSID, and find a stalking tracker by noticing the MAC that follows you. None of it requires transmitting, which is exactly what keeps the toolkit cleanly defensive. Two namespaces keep the split legible:
AT+MON…are passive monitors (no target, safe always-on);AT+SCAN…are active but require an explicit in-scope target (your own subnet) and refuse to run without one.
AT+WIFISNIFF
Enter monitor mode and stream frame metadata.
| Syntax | Response |
|---|---|
AT+WIFISNIFF=<action>,<channel>[,<filter_mask>] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<channel>: Channel to monitor<filter_mask>: Bitmask of frame types to report:1= Management (beacon, probe, auth, assoc)2= Control (RTS, CTS, ACK)4= Data8= Deauth / disassoc only- Combine by addition (e.g.
7= mgmt + ctrl + data). Default1(management only) — correct for the defensive deauth / rogue-AP use case; set7for general recon, or control and data frames won't be reported.
URC:
+SNIFF: <timestamp>,<type>,<src_addr>,<dst_addr>,<bssid>,<rssi>,<channel>
<type>:MGMT,CTRL,DATA,DEAUTH
Errors: 620
AT+MONDEAUTH
Watch for deauth / disassoc floods.
| Syntax | Response |
|---|---|
AT+MONDEAUTH=<action>[,<threshold>[,<window_sec>]] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<threshold>: Frames per window to alarm.10–1000. Default50.<window_sec>: Time window in seconds.1–60. Default10.
URC (alarm):
+MONDEAUTH: <timestamp>,<count>,<src_addr>,<dst_addr>,<channel>
AT+MONROGUECFG
Configure known-good BSSID database for rogue-AP detection.
| Syntax | Response |
|---|---|
AT+MONROGUECFG=<op>[,<ssid>,<bssid>] |
OK or +MONROGUECFG: <entries> or ERROR |
Parameters:
<op>:0= clear all1= add entry2= delete entry3= list entries
<ssid>: Network name (quoted if needed). Required for op 1 and 2.<bssid>: MAC address. Required for op 1 and 2.
Response (op=3):
+MONROGUECFG: <ssid>,<bssid>
(repeated, terminated by OK)
AT+MONROGUE
Detect evil-twin APs (SSIDs with unexpected BSSIDs).
| Syntax | Response |
|---|---|
AT+MONROGUE=<action> |
OK or ERROR |
Parameters:
<action>:0= stop,1= start
URC:
+MONROGUE: <timestamp>,<ssid>,<expected_bssid>,<rogue_bssid>,<channel>,<rssi>
Note: Requires entries in the AT+MONROGUECFG database, or auto-learns from past AT+CWJAP connections (documented behaviour).
AT+CLIENTWATCH
Inventory stations on your network.
| Syntax | Response |
|---|---|
AT+CLIENTWATCH=<action>[,<bssid>[,<channel>]] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start,2= dump current inventory<bssid>: Your AP's BSSID to filter against. Required for start.<channel>: Channel your AP is on. Required for start.
URC:
+CLIENTWATCH: <mac>,<first_seen>,<last_seen>,<rssi>,<pkts>
Note: Without <bssid>, the command returns ERROR (no default target).
AT+BEACONMON
Track all APs in range over time.
| Syntax | Response |
|---|---|
AT+BEACONMON=<action> |
OK or ERROR |
Parameters:
<action>:0= stop,1= start
URC:
+BEACONMON: <timestamp>,<bssid>,<ssid>,<channel>,<rssi>,<security>,<new_flag>
<new_flag>:0= seen before,1= new since start
AT+BLERECON
Continuous BLE scan logging.
| Syntax | Response |
|---|---|
AT+BLERECON=<action> |
OK or ERROR |
Parameters:
<action>:0= stop,1= start
URC:
+BLERECON: <timestamp>,<addr>,<addr_type>,<rssi>,<name>,<service_uuids>,<mfg_data_hex>
AT+MONBLETAG
Unwanted-tracker detector (AirTag-style stalking).
| Syntax | Response |
|---|---|
AT+MONBLETAG=<action>[,<threshold_min>] |
OK or ERROR |
Parameters:
<action>:0= stop,1= start<threshold_min>: Minutes a non-randomising MAC must follow you.5–120. Default15.
URC:
+MONBLETAG: <timestamp>,<addr>,<rssi_history_hex>,<duration_min>
AT+BLESPOOFDETECT
Detect duplicate advertised BLE identities.
| Syntax | Response |
|---|---|
AT+BLESPOOFDETECT=<action> |
OK or ERROR |
Parameters:
<action>:0= stop,1= start
URC:
+BLESPOOFDETECT: <timestamp>,<legitimate_addr>,<spoof_addr>,<rssi>,<name>
14.8 Example – scan.lua (LAN host + port audit, stock firmware)
A worked AntOS example of the active-but-inward pattern: sweep your own subnet for live hosts, then probe a short list of common ports on each. It uses only stock AT commands (AT+PING, AT+CIPSTART / AT+CIPCLOSE), so it runs on a bare ESP-AT flash with no custom at_ant64 build. Note the deliberate design: the subnet is a required argument – the tool will not run without an explicit in-scope target, which is what keeps an active scanner defensible.
-- scan.lua - audit YOUR OWN LAN: live-host sweep + common-port probe.
-- Active scanning: requires an explicit in-scope subnet (no default target).
-- Built entirely on stock ESP-AT (AT+PING, AT+CIPSTART) via the phreak lib.
local a, done = os.arguments{
name = "scan",
desc = "Audit your own LAN for live hosts and open ports",
long = "Pings every host in a /24 you specify, then probes common TCP "
.. "ports on the ones that answer. Point it ONLY at a network you "
.. "own or are authorised to test.",
{ "*Subnet", help = "in-scope /24 base, e.g. 192.168.1 (REQUIRED)" },
{ "-Ports", help = "comma list to probe (default: common set)" },
}
if done then return end
if not a.subnet then
print("scan: refusing to run without an explicit subnet (in-scope target).")
print("usage: scan 192.168.1 [-ports 22,80,443]")
return
end
local phreak = require("phreak") -- Phreak AT link (see wiki: phreak)
local base = a.subnet:gsub("%.%d+$", "") -- tolerate "192.168.1" or "192.168.1.0"
-- Common ports worth flagging on a home LAN (services that often shouldn't
-- be exposed). Override with -ports.
local ports = { 22, 23, 53, 80, 139, 443, 445, 554, 1900, 3389, 8080, 8443 }
if a.ports then
ports = {}
for p in a.ports:gmatch("%d+") do ports[#ports+1] = tonumber(p) end
end
print("scan: sweeping " .. base .. ".1-254 (in-scope: you own this) ...")
local live = {}
for host = 1, 254 do
local ip = base .. "." .. host
-- AT+PING <ip> -> round-trip ms, or timeout. phreak.ping wraps it.
local ok, ms = phreak.ping(ip, 300) -- 300 ms budget per host
if ok then
live[#live+1] = ip
print(string.format(" up %-15s %d ms", ip, ms))
end
end
if #live == 0 then
print("scan: no hosts answered - check the subnet and that Wi-Fi is joined.")
return
end
print(string.format("scan: %d live host(s); probing %d port(s) each ...",
#live, #ports))
for _, ip in ipairs(live) do
local openp = {}
for _, port in ipairs(ports) do
-- AT+CIPSTART="TCP",<ip>,<port> with a short timeout: a successful
-- connect => port open. phreak.tcpprobe wraps start+close.
if phreak.tcpprobe(ip, port, 400) then
openp[#openp+1] = port
end
end
if #openp > 0 then
print(string.format(" %-15s open: %s", ip,
table.concat(openp, ", ")))
end
end
print("scan: done. Review anything unexpected - unknown hosts, or ports "
.. "open that shouldn't be (e.g. 23/telnet, 3389/RDP, 445/SMB to the WAN).")
phreak.ping and phreak.tcpprobe are thin lib_phreak helpers over AT+PING and AT+CIPSTART/AT+CIPCLOSE – the same require-only pattern as the flasher verbs. The script never transmits anything but connection attempts to addresses you named, and refuses to start without a subnet: the active-but-inward rule in code.
15. IoT Radios — 802.15.4 and Mesh
Prefix: IOT, THREAD, ZB, MATTER, BMESH, MLITE
Note: Not present in stock ESP-AT. Added as custom user commands. The 802.15.4 radio runs one stack at a time.
15.1 Stack selection
AT+IOTMODE
Select the active 802.15.4 / IoT personality.
| Syntax | Response |
|---|---|
AT+IOTMODE? |
+IOTMODE: <mode> |
AT+IOTMODE=<mode> |
OK or ERROR |
Parameters:
<mode>:0= off1= Thread2= Zigbee3= Matter-over-Thread4= Matter-over-Wi-Fi5= BLE Mesh6= ESP-Mesh-Lite (Wi-Fi)
Note: Changing AT+IOTMODE requires AT+RST to unload the previous stack and initialise the new one. The command returns OK immediately but sets a pending flag; the switch happens on the next boot. Querying after OK but before restart returns the pending mode.
Errors: 630, 631
15.2 Thread
AT+THREADINIT
Initialise the Thread stack.
| Syntax | Response |
|---|---|
AT+THREADINIT |
OK or ERROR |
Note: Must be called after AT+IOTMODE=1 and restart.
AT+THREADDATASET
Get / set the active dataset.
| Syntax | Response |
|---|---|
AT+THREADDATASET? |
one +THREADDATASET: <field>,<value> line per field (see below), then OK |
AT+THREADDATASET=<field>,<value> |
OK or ERROR |
Parameters:
<field>:KEY,PANID,XPANID,NAME,CHAN<value>:KEY: 32-char hex network keyPANID: 4-char hex PAN IDXPANID: 16-char hex extended PAN IDNAME: Network name string (max 16 chars)CHAN: Channel.11–26
Query response — one field per line, so the host can parse incrementally with no comma/semicolon splitting:
+THREADDATASET: KEY,<hex32>
+THREADDATASET: PANID,<hex4>
+THREADDATASET: XPANID,<hex16>
+THREADDATASET: NAME,<string>
+THREADDATASET: CHAN,<uint>
OK
AT+THREADIF
Bring the Thread IPv6 interface up or down.
| Syntax | Response |
|---|---|
AT+THREADIF=<state> |
OK or ERROR |
Parameters:
<state>:0= down,1= up
AT+THREADSTART / AT+THREADSTOP
Start / stop the Thread protocol.
| Syntax | Response |
|---|---|
AT+THREADSTART |
OK or ERROR |
AT+THREADSTOP |
OK or ERROR |
AT+THREADSTATE
Query Thread role / state.
| Syntax | Response |
|---|---|
AT+THREADSTATE? |
+THREADSTATE: <state> |
Response:
<state>:disabled,detached,child,router,leader
AT+THREADSCAN
Active scan for nearby Thread networks.
| Syntax | Response |
|---|---|
AT+THREADSCAN |
OK + URCs or ERROR |
URC:
+THREAD: SCAN,<panid>,<name>,<channel>,<rssi>,<lqi>,<ext_addr>
AT+THREADJOIN
Join by commissioning (joiner start).
| Syntax | Response |
|---|---|
AT+THREADJOIN=<pskd>[,<timeout_sec>] |
OK (async) or ERROR |
Parameters:
<pskd>: Joiner passphrase.6–32chars.<timeout_sec>:30–600. Default120.
URC:
+THREAD: JOIN,<status> // 0=success, 1=timeout, 2=credentials_rejected
AT+THREADCOMM
Act as commissioner.
| Syntax | Response |
|---|---|
AT+THREADCOMM=<action>[,<eui64>,<pskd>] |
OK or ERROR |
Parameters:
<action>:0= stop commissioner,1= start commissioner,2= add joiner<eui64>: Joiner EUI-64 (16 hex chars). Required for action 2.<pskd>: Joiner passphrase. Required for action 2.
AT+THREADIPADDR
List / add IPv6 addresses.
| Syntax | Response |
|---|---|
AT+THREADIPADDR? |
+THREADIPADDR: <addr1>,<addr2>,... |
AT+THREADIPADDR=<action>[,<addr>] |
OK or ERROR |
Parameters:
<action>:0= list,1= add,2= remove
+THREAD (URC)
Thread state changes and inbound datagrams.
+THREAD: STATE,<old_state>,<new_state>
+THREAD: DATA,<src_addr>,<port>,<len>,<data_hex>
15.3 Zigbee
AT+ZBROLE
Set Zigbee role.
| Syntax | Response |
|---|---|
AT+ZBROLE? |
+ZBROLE: <role> |
AT+ZBROLE=<role> |
OK or ERROR |
Parameters:
<role>:0= coordinator,1= router,2= end-device
Note: Must be set before AT+ZBINIT.
AT+ZBINIT
Initialise the Zigbee stack.
| Syntax | Response |
|---|---|
AT+ZBINIT |
OK or ERROR |
AT+ZBPANID / AT+ZBCHAN
Set PAN ID and channel.
| Syntax | Response |
|---|---|
AT+ZBPANID=<panid> |
OK or ERROR |
AT+ZBCHAN=<channel> |
OK or ERROR |
Parameters:
<panid>: 16-bit hex PAN ID.0x0000–0xFFF7<channel>:11–26
AT+ZBFORM
Form a network (coordinator only).
| Syntax | Response |
|---|---|
AT+ZBFORM |
OK or ERROR |
AT+ZBSTEER
Join an existing network.
| Syntax | Response |
|---|---|
AT+ZBSTEER |
OK (async) or ERROR |
URC:
+ZB: STEER,<status> // 0=success, 1=fail, 2=no_network
AT+ZBPERMIT
Open / close the join window.
| Syntax | Response |
|---|---|
AT+ZBPERMIT=<seconds> |
OK or ERROR |
Parameters:
<seconds>:0= close,1–254= open for N seconds,255= always open
AT+ZBNODES
List joined nodes.
| Syntax | Response |
|---|---|
AT+ZBNODES? |
+ZBNODES: <short_addr>,<ieee_addr>,<role> (repeated) |
AT+ZBATTRRD / AT+ZBATTRWR
Read / write ZCL attribute.
| Syntax | Response |
|---|---|
AT+ZBATTRRD=<short_addr>,<endpoint>,<cluster_hex>,<attr_hex> |
+ZBATTR: <status>,<data_type>,<data_hex> |
AT+ZBATTRWR=<short_addr>,<endpoint>,<cluster_hex>,<attr_hex>,<data_type>,<data_hex> |
OK or ERROR |
Parameters:
<short_addr>: 16-bit hex network address<endpoint>:1–240<cluster_hex>: 4-char hex cluster ID<attr_hex>: 4-char hex attribute ID<data_type>: ZCL data type enum (e.g.0x10= bool,0x21= uint16)
AT+ZBCMD
Send a ZCL cluster command.
| Syntax | Response |
|---|---|
AT+ZBCMD=<short_addr>,<endpoint>,<cluster_hex>,<cmd_hex>[,<data_hex>] |
OK or ERROR |
AT+ZBREPORT
Configure attribute reporting.
| Syntax | Response |
|---|---|
AT+ZBREPORT=<short_addr>,<endpoint>,<cluster_hex>,<attr_hex>,<min_int>,<max_int>[,<delta>] |
OK or ERROR |
AT+ZBBIND
Bind clusters between endpoints.
| Syntax | Response |
|---|---|
AT+ZBBIND=<src_addr>,<src_ep>,<cluster_hex>,<dst_addr>,<dst_ep> |
OK or ERROR |
+ZB (URC)
Zigbee events.
+ZB: JOIN,<short_addr>,<ieee_addr>,<role>
+ZB: REPORT,<short_addr>,<endpoint>,<cluster_hex>,<attr_hex>,<data_hex>
+ZB: CMD,<short_addr>,<endpoint>,<cluster_hex>,<cmd_hex>,<data_hex>
15.4 Matter
AT+MATTERINIT
Initialise Matter on the chosen transport.
| Syntax | Response |
|---|---|
AT+MATTERINIT |
OK or ERROR |
Note: Transport is determined by AT+IOTMODE (3 = Thread, 4 = Wi-Fi).
AT+MATTERCOMM
Commission a device.
| Syntax | Response |
|---|---|
AT+MATTERCOMM=<type>,<payload> |
OK (async) or ERROR |
Parameters:
<type>:0= manual pairing code,1= QR code payload<payload>: String payload
URC:
+MATTER: COMM,<status>,<node_id> // 0=success
AT+MATTERFABRIC
List / remove commissioned fabrics.
| Syntax | Response |
|---|---|
AT+MATTERFABRIC=<action>[,<fabric_index>] |
OK or +MATTERFABRIC: <index>,<label> or ERROR |
Parameters:
<action>:0= list,1= remove by index
AT+MATTERINVOKE
Invoke a cluster command.
| Syntax | Response |
|---|---|
AT+MATTERINVOKE=<node_id>,<endpoint>,<cluster_hex>,<command_hex>[,<arg_tlv_hex>] |
OK or ERROR |
Parameters:
<node_id>: 64-bit hex node ID<endpoint>:0–65535<cluster_hex>: 8-char hex cluster ID<command_hex>: 4-char hex command ID<arg_tlv_hex>: Optional hex-encoded Matter TLV arguments
Note: For simple types, use AT+MATTERCONV first (see below).
AT+MATTERREAD / AT+MATTERSUB
Read / subscribe to an attribute.
| Syntax | Response |
|---|---|
AT+MATTERREAD=<node_id>,<endpoint>,<cluster_hex>,<attr_hex> |
+MATTER: READ,<data_tlv_hex> |
AT+MATTERSUB=<node_id>,<endpoint>,<cluster_hex>,<attr_hex>[,<min_int>[,<max_int>]] |
OK or ERROR |
AT+MATTERCONV
Helper: convert simple value to Matter TLV hex.
| Syntax | Response |
|---|---|
AT+MATTERCONV=<type>,<value> |
+MATTERCONV: <tlv_hex> |
Parameters:
<type>:0= bool (0or1)1= uint82= uint163= uint324= int85= int166= int327= string (quoted)
AT+MATTERONOFF
Shortcut for On/Off cluster.
| Syntax | Response |
|---|---|
AT+MATTERONOFF=<node_id>,<endpoint>,<state> |
OK or ERROR |
Parameters:
<state>:0= off,1= on,2= toggle
+MATTER (URC)
Matter events.
+MATTER: COMM,<status>,<node_id>
+MATTER: REPORT,<node_id>,<endpoint>,<cluster_hex>,<attr_hex>,<data_tlv_hex>
15.5 Bluetooth LE Mesh
AT+BMESHROLE
Set BLE Mesh role.
| Syntax | Response |
|---|---|
AT+BMESHROLE? |
+BMESHROLE: <role> |
AT+BMESHROLE=<role> |
OK or ERROR |
Parameters:
<role>:0= provisioner,1= node
AT+BMESHPROV
Provision or emit unprovisioned beacon.
| Syntax | Response |
|---|---|
AT+BMESHPROV=<action>[,<uuid>] |
OK (async) or ERROR |
Parameters:
<action>:0= stop1= start beaconing (node)2= start scanning + provisioning (provisioner)
<uuid>: 32-char hex device UUID (provisioner action 2, optional filter)
URC:
+BMESH: PROV,<status>,<uuid>,<addr> // status: 0=success
AT+BMESHKEY
Set network / application keys.
| Syntax | Response |
|---|---|
AT+BMESHKEY=<type>,<index>,<hex_key> |
OK or ERROR |
Parameters:
<type>:0= net key,1= app key<index>: Key index.0–4095<hex_key>: 32-char hex (128-bit)
AT+BMESHBIND
Bind a model to an app key.
| Syntax | Response |
|---|---|
AT+BMESHBIND=<elem_addr>,<model_id>,<appkey_index> |
OK or ERROR |
AT+BMESHPUB / AT+BMESHSUB
Model publish address / subscription.
| Syntax | Response |
|---|---|
AT+BMESHPUB=<elem_addr>,<model_id>,<pub_addr>[,<ttl>[,<period>]] |
OK or ERROR |
AT+BMESHSUB=<elem_addr>,<model_id>,<sub_addr> |
OK or ERROR |
AT+BMESHONOFF
Generic OnOff model get / set.
| Syntax | Response |
|---|---|
AT+BMESHONOFF=<addr>,<state> |
OK or ERROR |
AT+BMESHONOFF=<addr>,? |
+BMESHONOFF: <addr>,<state> |
Parameters:
<addr>: Destination unicast or group address<state>:0= off,1= on,?= get
+BMESH (URC)
BLE Mesh events.
+BMESH: PROV,<status>,<uuid>,<addr>
+BMESH: MSG,<src_addr>,<model_id>,<opcode>,<data_hex>
15.6 ESP-Mesh-Lite (Wi-Fi)
AT+MLITEEN
Enable / disable Wi-Fi mesh.
| Syntax | Response |
|---|---|
AT+MLITEEN? |
+MLITEEN: <state> |
AT+MLITEEN=<state> |
OK or ERROR |
Parameters:
<state>:0= disable,1= enable
AT+MLITEID
Set mesh ID / configuration.
| Syntax | Response |
|---|---|
AT+MLITEID? |
+MLITEID: <mesh_id>,<channel>,<password> |
AT+MLITEID=<mesh_id>[,<channel>[,<password>]] |
OK or ERROR |
Parameters:
<mesh_id>: Mesh network identifier string (max 32 chars)<channel>: Wi-Fi channel.1–14<password>: WPA2 passphrase (quoted, max 64 chars)
AT+MLITELEVEL
Query or pin node level.
| Syntax | Response |
|---|---|
AT+MLITELEVEL? |
+MLITELEVEL: <level>,<is_root> |
AT+MLITELEVEL=<pin>[,<desired_level>] |
OK or ERROR |
Parameters:
<pin>:0= automatic,1= pin as root,2= pin as leaf<desired_level>: Only used if pin=1 (force root level).0–6.
AT+MLITETOPO
Query topology.
| Syntax | Response |
|---|---|
AT+MLITETOPO? |
+MLITETOPO: <parent_mac>,<parent_rssi>,<level>,<child_count> |
Response fields:
<parent_mac>: Parent node MAC or00:00:00:00:00:00if root<parent_rssi>: dBm to parent<level>: Current tree level<child_count>: Number of children
AT+MLITESEND
Send data in the mesh.
| Syntax | Response |
|---|---|
AT+MLITESEND=<dest_type>,<dest>[,<len>,<data_hex>] |
OK or ERROR |
Parameters:
<dest_type>:0= root,1= parent,2= broadcast downward,3= unicast MAC<dest>: MAC address if dest_type=3, else omitted or0<len>: Payload length.0–1460<data_hex>: Hex-encoded payload
+MLITE (URC)
Mesh events and inbound messages.
+MLITE: TOPO,<parent_mac>,<level>
+MLITE: DATA,<src_mac>,<len>,<data_hex>
16. Bridging & gateway commands
Prefix: BRIDGE
Note: Not present in stock ESP-AT. Added as custom user commands. A bridge spans both radios, so it's its own namespace — not under AT+LORA… or the AT+LR… tag.
The C5 hosts both the LR2021 (over SPI) and its own Wi-Fi / BLE, so both packet streams already live inside one chip. That makes the Ant64 a gateway: it can sit between two otherwise-incompatible networks and translate. The bridge runs in the C5 firmware — DeMon configures a few rules over AT and then stays out of the data path; the C5 forwards autonomously. DeMon sets policy, the C5 moves the bytes.
These are provisional (like §12.6) and gated by the stacks underneath: a bridge can only connect protocols the C5 actually speaks. LoRa ↔ BLE is near-term (both largely present); anything involving Zigbee / Wi-SUN / Z-Wave waits on that stack being ported to the LR2021. The command set can be documented before every endpoint it could name is live. Bridge errors use 660 (unknown rule id) and 661 (endpoint protocol / stack not available).
Endpoints name a radio + protocol: LORA · LRBLE (LR2021 BLE) · LR154 (LR2021 802.15.4) · BLE (C5) · WIFI (C5, e.g. an MQTT topic) · THREAD / ZB (C5 802.15.4). A rule forwards <from> → <to>.
AT+BRIDGEADD
Create a bridging rule (provisional) — returns a rule <id>.
| Syntax | Response |
|---|---|
AT+BRIDGEADD=<from>,<to>,<filter> |
+BRIDGEADD: <id> then OK, or ERROR |
Parameters:
<from>/<to>: source and destination endpoints (see above)<filter>: optional match — address / type / topic; empty = forward everything
Errors: 661 (endpoint not available)
AT+BRIDGEMAP
Set how a rule translates payloads (provisional).
| Syntax | Response |
|---|---|
AT+BRIDGEMAP=<id>,<rule> |
OK or ERROR |
Parameters:
<id>: rule fromAT+BRIDGEADD<rule>:PASS(identity passthrough) ·REMAP:<spec>(field remap) · a named codec
Errors: 660 (unknown id)
AT+BRIDGE
Start or stop a rule (provisional).
| Syntax | Response |
|---|---|
AT+BRIDGE=<id>,<state> |
OK or ERROR |
Parameters:
<id>: rule id<state>:0= stop ·1= start
Errors: 660
AT+BRIDGE? / AT+BRIDGESTAT
List rules, or read a rule's counters (provisional).
| Syntax | Response |
|---|---|
AT+BRIDGE? |
one +BRIDGE: <id>,<from>,<to>,<state> per rule, then OK |
AT+BRIDGESTAT=<id> |
+BRIDGESTAT: <forwarded>,<dropped>,<errors> then OK |
AT+BRIDGEDEL
Remove a rule (provisional).
| Syntax | Response |
|---|---|
AT+BRIDGEDEL=<id> |
OK or ERROR |
Errors: 660
URC — +BRIDGE: (provisional). When enabled on a rule, the C5 emits a notification each time a packet crosses, so DeMon can log or intervene without sitting in the fast path:
+BRIDGE: <id>,<from>,<to>,<len>
Store-and-forward. Buffering is C5-local — the C5's PSRAM holds the queue, so DeMon is not in the data path. A rule runs in one of three tiers:
- Pass-through — no buffering; the C5 forwards live.
- PSRAM buffered (C5) — absorb bursts, hold a short queue while the far side is briefly unreachable, or rate-match a fast LoRa-FLRC feed into slower BLE advertisements. Entirely C5-side; covers the large majority of gateway needs. Queue depth is bounded by free PSRAM after the radio stacks take their share (an EVK bring-up measurement — TBD).
- DBFS staged (DeMon) — only for what PSRAM can't be: persistence across reboot / power-loss, very large backlogs, or hold-for-hours windows. This tier is about durability and capacity, not smoothing; crossings are handed to DeMon / DBFS.
Appendix A. Quick-reference: Prefix-to-domain mapping
| Prefix | Domain | Section |
|---|---|---|
LORA |
LoRa / LoRaWAN / FLRC (LR2021) | §12 |
GNSS |
GPS / GNSS (NEO-M10) | §13 |
MON |
Passive security monitors | §14.7 |
WIFI |
Wi-Fi analysis tools | §14.1–14.3 |
BLE |
BLE tracking | §14.3 |
IPERF / LINKQ / LATTEST / ANTBENCH |
Active link tests | §14.6 |
IOT |
IoT stack selection | §15.1 |
THREAD |
Thread (802.15.4) | §15.2 |
ZB |
Zigbee (802.15.4) | §15.3 |
MATTER |
Matter | §15.4 |
BMESH |
BLE Mesh | §15.5 |
MLITE |
ESP-Mesh-Lite (Wi-Fi) | §15.6 |
BRIDGE |
Cross-radio bridging / gateway | §16 |
Sources
Espressif ESP-AT User Guide for the ESP32-C5 (latest) is the authoritative reference:
- Command-set index — https://docs.espressif.com/projects/esp-at/en/latest/esp32c5/AT_Command_Set/index.html
- Released firmware and support matrix — https://docs.espressif.com/projects/esp-at/en/latest/esp32c5/AT_Binary_Lists/esp_at_binaries.html
- Get Started (hardware connection, flashing) — https://docs.espressif.com/projects/esp-at/en/latest/esp32c5/Get_Started/index.html
The §12 radio is the Semtech LR2021 (Seeed Wio-LR2021 module), driven by Semtech's LoRa USP; the AT naming conventions for the backward-compatible LoRa / LoRaWAN modes are drawn from off-the-shelf LoRa AT modules:
- Semtech LoRa Plus LR2021 transceiver — 4th-gen; Sub-GHz (150–960 MHz) + 2.4 GHz + S/L-band; FLRC up to 2.6 Mbps — https://www.mouser.com/new/semtech/semtech-lr2021-transceiver
- Semtech LR2021 datasheet (Rev 1.1) — host command set: packet-type/modulation select, RTToF ranging, CAD,
GetRandomNumber,GetRssiInst, PA control — https://www.mouser.com/pdfDocs/61979758LR2021_V1_1_datasheet.pdf - Seeed Wio-LR2021 module + Semtech LoRa USP /
usp_zephyr(the LR20xx radio driver, ported to the C5) — https://wiki.seeedstudio.com/wio_lr2021_introduction/ - Reyax RYLR998 / RYLR498 LoRa AT Command Guide — point-to-point command set (
AT+ADDRESS,AT+BAND,AT+PARAMETER,AT+SEND,+RCV, …) - RAKwireless RUI3 AT Command Manual — P2P + LoRaWAN set (
AT+NWM,AT+PSEND/AT+PRECV,AT+JOIN,AT+CLASS, …) — https://docs.rakwireless.com/product-categories/software-apis-and-libraries/rui3/at-command-manual/
For the GPS/GNSS command vocabulary (§13), the conventions follow GNSS-over-AT modems:
- SIMCom SIM868 / SIM7000 GNSS Application Note —
AT+CGNSPWR,AT+CGNSINF,AT+CGNSURC,AT+CGNSTST - Quectel GNSS AT Commands Manual (EC25 / BG96) —
AT+QGPS,AT+QGPSLOC,AT+QGPSGNMEA,AT+QGPSCFG
The RF analysis and link diagnostics (§14) sit on standard ESP-IDF features plus ESP-CSI — the Wi-Fi driver's promiscuous (monitor) mode for capture, ESP-CSI for channel-state / presence, NimBLE for BLE, and the Wi-Fi iperf example for the active throughput tests:
- ESP-IDF (Wi-Fi driver: promiscuous mode, channel control, scan; NimBLE; mDNS; FATFS) — https://github.com/espressif/esp-idf
- ESP-IDF Wi-Fi driver guide (promiscuous mode, channel-state information) — https://docs.espressif.com/projects/esp-idf/
- ESP-CSI (channel-state-information capture, presence / motion sensing) — https://github.com/espressif/esp-csi
- ESP-IDF Wi-Fi
iperfexample (basis forAT+IPERF; throughput between two ESP targets or an ESP and a PC running iPerf) — https://github.com/espressif/esp-idf/tree/master/examples/wifi/iperf - Espressif
iperf-cmdcomponent (ESP Component Registry) — https://components.espressif.com/components/espressif/iperf-cmd
The IoT radios (§15) bridge these stacks, whose CLI/SDK vocabularies the proposed commands follow:
- OpenThread CLI reference (Thread) — https://openthread.io/reference/cli/commands
- ESP Zigbee SDK programming guide (Zigbee / ZCL) — https://docs.espressif.com/projects/esp-zigbee-sdk/
- ESP-Matter, ESP-BLE-MESH, and ESP-Mesh-Lite SDKs (Matter / BLE Mesh / Wi-Fi mesh) — https://www.espressif.com/