The Bluetooth Classic Accessory Interface Specification defines how a mobile device (such as Android phone) communicates with a BlueParrott headset using Bluetooth Classic through an AT‑command–based interface. At the core of the interface is a structured set of AT commands exchanged over the Classic Bluetooth link. This design uses standardized and vendor‑specific AT command prefixes to organize functional areas, with each command representing a specific feature or data channel. AT commands define what the headset exposes such as button events, mode changes, logs, sensor values, or model information, and specify whether the application can query, configure, or receive event notifications through the Bluetooth Classic connection.
| Command | Description | Command Definition | Response Definition |
|---|---|---|---|
| INIT | Sent to headset to request Init Response | AT+ANDROID: BP, INIT |
AT+ANDROID=BP, MODE, modeAT+ANDROID=BP, BONDABLE, bondableAT+ANDROID=BP, SPEEDDIAL, speed dial #AT+ANDROID=BP, APPNAME, app nameAT+ANDROID=BP, APPKEY, app keyAT+ANDROID=BP, MODEL, modelAT+ANDROID=BP, PBVERSION, pb versionAT+ANDROID=BP, FWVERSION, fw versionAT+ANDROID=BP, CMFBVERSION, cmfb versionAT+ANDROID=BP, S1STATE, sensor stateAT+ANDROID=BP, S2STATE, sensor stateAT+ANDROID=BP, S3STATE, sensor stateAT+ANDROID=BP, VERBOSITY, verbosityAT+ANDROID=BP, TXNR, tx noise reduction modeAT+ANDROID=BP, TXGAIN, tx gain modeAT+ANDROID=BP, TEMPERATURE, temperature value in °CAT+ANDROID=BP, ENDINIT AT+ANDROID=BP, ENTKEY1, Enterprise Key 1AT+ANDROID=BP, ENTKEY2, Enterprise Key 2AT+ANDROID=BP, ENTKEY3, Enterprise Key 3AT+ANDROID=BP, ENDENTINIT |
| STATE | Sent to headset to request State Response | AT+ANDROID: BP, STATE |
AT+ANDROID=BP, MODE, modeAT+ANDROID=BP, BONDABLE, bondableAT+ANDROID=BP, SPEEDDIAL, speed dial #AT+ANDROID=BP, APPNAME, app nameAT+ANDROID=BP, APPKEY, app keyAT+ANDROID=BP, MODEL, modelAT+ANDROID=BP, PBVERSION, pb versionAT+ANDROID=BP, FWVERSION, fw versionAT+ANDROID=BP, CMFBVERSION, cmfb versionAT+ANDROID=BP, S1STATE, sensor stateAT+ANDROID=BP, S2STATE, sensor stateAT+ANDROID=BP, S3STATE, sensor stateAT+ANDROID=BP, VERBOSITY, verbosityAT+ANDROID=BP, TXNR, tx noise reduction modeAT+ANDROID=BP, TXGAIN, tx gain modeAT+ANDROID=BP, TEMPERATURE, temperature value in °CAT+ANDROID=BP, ENDSTATE AT+ANDROID=BP, ENTKEY1, Enterprise Key 1AT+ANDROID=BP, ENTKEY2, Enterprise Key 2AT+ANDROID=BP, ENTKEY3, Enterprise Key 3AT+ANDROID=BP, ENDENTSTATE |
| Command | Description | Values | Command Definition |
|---|---|---|---|
| MODE | Sent to headset to write the button Mode key, see VXI_BUTTON_MODE, mode is the string representation of a decimal number |
0: Mute 2: SDK Mode 7: Voice Control 12: Check Battery 41: Second MFB 46: Answer/End Calls |
AT+ANDROID: BP, MODE, mode |
| BONDABLE | Sent to headset to write the Bondable key, see VXI_BONDABLE, bondable is the string representation of a decimal number |
0: not bondable 1: bondable |
AT+ANDROID: BP, BONDABLE, bondable |
| SPEEDDIAL | deprecated |
deprecated |
deprecated |
| APPNAME | Sent to headset to write the App Name key, see VXI_APPNAME, app name is the application name as a string, maximum of 22 characters. Note that strings must be packed into / unpacked from the memory location. Chip memory is 16 bits wide, so 2 chars / WORD |
|
AT+ANDROID: BP, APPNAME, app name |
| APPKEY | Sent to headset to write the App ID key, see VXI_APPID, |
|
AT+ANDROID: BP, APPKEY, app key |
| ENTKEY1 | Sent to headset to write Enterprise Key 1, see BP_ENT_1, Enterprise Key 1 is a 16 bit decimal value |
|
AT+ANDROID: BP, ENTKEY1, Enterprise Key 1 |
| ENTKEY2 | Sent to headset to write Enterprise Key 2, see BP_ENT_2, Enterprise Key 2 is a 16 bit decimal value |
|
AT+ANDROID: BP, ENTKEY2, Enterprise Key 2 |
| ENTKEY3 | Sent to headset to write Enterprise Key 3, see BP_ENT_3, Enterprise Key 3 is a 16 bit decimal value |
|
AT+ANDROID: BP, ENTKEY3, Enterprise Key 3 |
| VERBOSITY | Sent to headset to set the verbosity level | |
AT+ANDROID:BP, VERBOSITY, level |
| BLE_ADVERTISE_ON | Sent to headset to enable/disable BLE advertisement | |
AT+ANDROID: BP, BLE_ADVERTISE_ON, boolean |
| CLASSIC_PTT_ON | Sent to headset to enable/disable Classic PTT | |
AT+ANDROID: BP, CLASSIC_PTT_ON, boolean |
| PTTOC_ON | Sent to headset to enable/disable Push-to-Talk over Cellular | |
AT+ANDROID: BP, PPTOC_ON, boolean |
| SHARED_DEVICE_MODE | Sent to the headset to enable/disable shared device mode | |
AT+ANDROID: BP, SHARED_DEVICE_MODE, boolean |
| QR_CODE_SCAN_MODE | Sent to the headset to enable/disable QR Code mode | |
AT+ANDROID: BP, QR_CODE_SCAN_MODE, boolean |
| TX_DSP_MODE | Set microphone noise suppression mode |
0: High 1: Medium (Default) 2: Off |
AT+ANDROID=BP,TXNR, mode |
| TX_GAIN_MODE | Set microphone gain mode |
0: -5dB 1: -4dB 2: -3dB 3: -2dB 4: -1dB 5: 0dB 6: 1dB 7: 2dB 8: 3dB 9: 4dB 10: 5dB 255: AGC (Auto Gain Control) |
AT+ANDROID=BP,TXGAIN, mode |
| Command | Description | Values | Payload |
|---|---|---|---|
| TEMPERATURE | Send notification to client when the temperature changes its value +/-1 deg C° | AT+ANDROID=BP, TEMPERATURE, temperature value in °C |
| Command | Description | Response Definition |
|---|---|---|
| ENDINIT | Sent from headset to indicate end of Init Response | AT+ANDROID=BP, ENDINIT |
| ENDSTATE | Sent from headset to indicate end of State Response | AT+ANDROID=BP, ENDSTATE |
| ENDENTINIT | Sent from headset to indicate end of Enterprise Init Response | AT+ANDROID=BP, ENDENTINIT |
| ENDENTSTATE | Sent from headset to indicate end of Enterprise State Response | AT+ANDROID=BP, ENDENTSTATE |
| Command | Description | Response Definition |
|---|---|---|
| PTT,P | When the Parrott button is pressed | AT+ANDROID=BP, PTT,P |
| PTT,R | When the Parrott button is released | AT+ANDROID=BP, PTT,R |
| PTT,T | When the Parrott button is single tapped | AT+ANDROID=BP, PTT,T |
| PTT,D | When the Parrott button is double tapped | AT+ANDROID=BP, PTT,D |
| PTT,L | When the Parrott button is long pressed | AT+ANDROID=BP, PTT,L |
| PTT,P | When the Parrott button is pressed | AT+ANDROID=BP, PTT,P |
| Command | Description | Response Definition |
|---|---|---|
| BP_LOG | Logging message from the headset | AT+ANDROID=BP,BP_LOG,key:value |
The following example monitors Broadcast Receiver class Intents sent when the OS receive an AT Command over SPP. Prior to subscribing to the intent, use the filter to select the category(ies) and Action(s) that are needed – in the below example the usage it to monitor Jabra/Blueparrott events which uses Google’s Assigned number (+ANDROID) and Plantronics' Assigned number to monitor KODIAK events. It also listens to actions such as HEADSET_EVENT along with ACL_DISCONNECTED. The section pertaining to the parsing of the command and the action corresponding to each can be customized to fit the supported use cases and needs.
@SuppressLint("MissingPermission")
private void registerClassicReceivers() {
IntentFilter btIntentFilter = new IntentFilter();
Log.e(TAG, "registerClassicReceivers");
/*
Jabra / BlueParrott AT events uses +ANDROID (GOOGLE) suffix
EXAMPLE: AT+ANDROID BP, PTT, P
*/
btIntentFilter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.GOOGLE);
/*
OPTIONAL: The usage of PLANTRONICS is to monitor Kodiak AT commands
*/
btIntentFilter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.PLANTRONICS);
btIntentFilter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
btIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
m_context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT.equals(action)) {
Bundle eventExtras = intent.getExtras();
if(eventExtras == null) {
return;
}
//get the arguments that the headset sent
Object[] args = (Object[]) eventExtras.get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
if (args == null) {
Log.e(TAG, "Null args for vendor specific event");
return;
}
String qualifier = (args.length >= 1) ? "" + args[0] : "";
String eventName = (args.length >= 2) ? "" + args[1] : "";
String data = (args.length >= 3) ? "" + args[2] : "";
if (args.length == 3) {
Log.e(TAG, "[R]: " + qualifier + "," + eventName + "," + data);
} else {
Log.e(TAG, "[R]: " + qualifier + "," + eventName);
}
data = data.toLowerCase();
if (eventName.equals("PTT")) {
//PB EVENTS
if (data.equals("p")) {
handleButtonEvent(PB_BUTTON_DOWN);
} else if (data.equals("r")) {
handleButtonEvent(PB_BUTTON_UP);
} else if (data.equals("d")) {
handleButtonEvent(PB_BUTTON_DOUBLE_TAP);
} else if (data.equals("l")) {
handleButtonEvent(PB_BUTTON_LONG_PRESS);
} else if (data.equals("t")) {
handleButtonEvent(PB_BUTTON_TAP);
}
}
} else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
Log.e(TAG, "Headset got disconnected");
}
}
}, btIntentFilter);
}
private BluetoothHeadset mBluetoothHeadset = null; //init onServiceConnected
private BluetoothDevice mHfpDevice = null; // init based on adapter.getBondedDevices()
String command = "+ANDROID";
String args = agrs0 + "," + args1 + ", " + args2; //Example BP,MODE,2
When all combined:
AT+ANDROID:BP,MODE,2 → This will set the PB to a mode to send PTT events
@SuppressLint("MissingPermission")
private boolean sendVendorAT(BluetoothDevice device, String command, String args) {
Log.d(TAG, "AT" + command + ":" + args);
if (mHfpDevice == null ){
Log.d(TAG, "mHfpDevice object is null");
return false;
}
if (mBluetoothHeadset == null ){
Log.d(TAG, "mBluetoothHeadset object is null");
return false;
}
logStatus("AT" + command + ":" + args);
return mBluetoothHeadset.sendVendorSpecificResultCode(device, command, args);
}