Ayla Device Bluetooth Services

This page provides high-level application notes for device application developers using Ayla’s Device Bluetooth (ADB) services.

Ayla’s Bluetooth services provide two major features:

  1. Wi-Fi configuration and device registration (device onboarding)
  2. BLE Local Control, which enables a device to be managed and controlled over a Bluetooth connection.

The BLE Local Control feature is optional and not required to support the Wi-Fi configuration and registration features. However, the local control feature may not be used without enabling base Bluetooth support, which include the Wi-Fi configuration and registration features.

Building the Ayla Device Agent with BLE Services

Support for Bluetooth features in the Ayla Device Agent is enabled using the following compiler defines.

Compiler Define



Includes base Bluetooth functionality in compilation. This includes the Wi-Fi configuration and device registration functionality.


Includes local control support, enabling the device to be monitored and controlled over BLE.
AYLA_BLUETOOTH_SUPPORT must also be defined.

Initializing Ayla Bluetooth Services from Device Application

On startup, an application desiring to use Ayla Bluetooth features must initialize the Bluetooth subsystem and register the BLE GATT services that enable these features.

void app_bt_register_services_cb(void)

     * Application initialization code

The register services callback function is called at the appropriate time during initialization. All BLE GATT-based services that are going to be used must be registered at this time. Services may not be deregistered. By the BLE standard devices are generally expected to have a fixed set of services that do not change over the life of the device. Therefore, all services should be registered in the same order each time the device restarts. There are four Ayla defined BLE GATT services:



Ayla Service

Provides access to basic identification information for an Ayla device, such as DSN (Device Serial Number) and OEM model, etc.

  • Identify function - write this characteristic to generate a callback to a function registered with adb_ayla_svc_identify_cb_set function to be called to blink an LED, make a sound, etc., to help the user identify the device from a list on a mobile app.

Ayla Connection Service

Provides a characteristic for the mobile app to write a “setup token” used to associate the device with a user during onboarding.

Ayla Local Control Service

Provides characteristics used to send and receive messages used to monitor and control the device over a BLE connection.

Ayla Wi-Fi Configuration Service

Provides characteristics that enable initial Wi-Fi provisioning so the device can connect to a Wi-Fi network and gain access to the Internet. This service may only be used when the device has not previously been configured or has been factory reset.

Identify Callback Registration

The Ayla service provides a characteristic that when written will make a function call to a callback the application registers, if one has been registered. This callback function my be used to provide an indication to an end user that will help that user identify a particular device from a list of devices shown on the mobile app. For example, the callback function may cause an LED to blink for a few seconds enabling the user to determine which device is which. The following is an example that prints a message:

void demo_identify_cb(void)
    printf("%s called\n", __func__);

     * App initialization or Bluetooth service registration

Factory Configuration of Ayla Bluetooth Features

There are two Bluetooth configuration items that may be configured during factory configuration of a device.

Configuration Item



The BT device name advertised by the device during onboarding. This is the name that will be displayed on the mobile app when selecting a device to onboard.

The name is defined by the following format string:

<prefix> - any ASCII string that doesn't include '%'
<digits> - even number of hex digits of BT device address to append
X - optional, to specify upper case hex, defaults to lower case

Example: “Ayla%4X” will result in a name like Ayla1234

NOTE: BLE advertisement frames only provide for 37 bytes of payload. One item of the payload is the name. Therefore, the name configured here should be very short, in the range of 8 to 12 characters.

Default, if not configured: “Ayla%4X


Configured passkey used during onboarding.
Passkeys are 6 digits that may include leading zeros.

Configuration is as follows:
0 - 999999: fixed passkey defined by config
-1: no-passkey auth
-2: random passkey

All other configured values or no configured value result in no-passkey auth.

Default if not configured: -1

Advertising, Pairing and Bonding

The Ayla Device Bluetooth features provide a number of advertisement and pairing modes that vary depending on the configuration state of the device.

Advertisement and Pairing Behavior of an Un-configured Device

When the device is un-configured or has recently been factory reset it advertises its name based on the bt/hostname factory configuration item. If the bt/hostname is not configured, the default name format Ayla%4X will be used. The device allows a single Bluetooth connection and supports pairing with no-passkey, a factory configured 6 digit numeric passkey, or a randomly generated 6 digit passkey depending on the configuration of the bt/key item. If the bt/key item is not configured, the default is no-passkey, which allows any device to connect without authentication.

If AYLA_LOCAL_CONTROL_SUPPORT is not enabled, pairing will only apply for the duration of the BLE connection. The pairing will not be persisted for future connections. In addition, once the device is onboarded, Bluetooth services will be terminated and not restarted unless the device is factory reset. Note, the BLE features of the ESP32 consume a significant amount of RAM that is made available to the heap when BLE is disabled.

If AYLA_LOCAL_CONTROL_SUPPORT is enabled, keys generated during the initial pairing will be persisted and the Bluetooth services will continue to operate after onboarding has been completed. This is referred to as the device and the mobile being “bonded”. This enables future connections by the same mobile device without requiring pairing operation each time the mobile connects for local control.

There is a timeout of 5 minutes for configuring an un-configured or factory reset device. After the device has been running for this period without being configured, Bluetooth services will be shutdown, such that if end users' devices that are never configured will not be left open to malicious activity over the BLE interface. A reset or power cycle will restart Bluetooth services for another 5 minutes.

Advertisement and Pairing Behavior of a Configured Device

NOTE: This case only applies to devices that have AYLA_LOCAL_CONTROL_SUPPORT enabled.

Once a device has been onboarded, the advertisement and pairing behavior changes permanently unless the device is factory reset to the un-configured state.

After onboarding is complete and the device has connected to the Ayla cloud, the BLE interface will stop advertising a name and switch to advertising a resolvable randomized Ayla Id. This is done to reduce the ability to track devices based on advertisements. The Ayla Id is a meaningless value to most observers except authorized mobile devices that have a key that enables securely associating an Ayla Id with a specific device. Mobile applications use the Ayla Id advertisements to discover devices they intend to connect with.

In addition, after onboarding has completed, pairing is disabled but may be temporarily re-enabled by the device application. For example, the device may re-enable pairing for a period of time (e.g. one minute) after the user presses a button on the device. The device application enables pairing by using the al_bt_pairing_mode_set API:

enum adb_pairing_mode {
    ADB_PM_DISABLED,        /**< no pairing allowed */
    ADB_PM_NO_PASSKEY,  /**< no passkey, no mitm protection */
    ADB_PM_CONFIGURED_PASSKEY,  /**< require configured passkey */
    ADB_PM_RANDOM_PASSKEY,  /**< random passkey, requires a display */
    ADB_PM_AYLA_PASSKEY,    /**< require LAN IP key generated passkey */

 * Set the pairing mode.
 * \param mode is the pairing mode to configure.
 * \param duration is the duration in seconds to enable this mode, 0 means
 * no time limit.
al_bt_pairing_mode_set(enum adb_pairing_mode mode, u16 duration)

NOTE: The ADB_PM_AYLA_PASSKEY mode is not currently supported by the Ayla mobile SDKs.

As with the initial pairing, subsequent pairings are persisted as bonds such that each mobile device only needs to be paired once. Up to 5 devices may be paired but only 3 many be connected at the same time.

Displaying a Passkey

If the device has a means to display a passkey, the application can register a callback, which will be called with the 6 digit passkey value when the passkey needs to be displayed. The API to register this callback is:

void al_bt_passkey_callback_set(void (*callback)(u32 passkey));

Ayla Device Bluetooth APIs

ADB APIs are fully documented in the following header files:

Bluetooth Debugging


Logging for Bluetooth features is under the bt module. Logs may be enabled and disabled for various levels using the log command. For example, debug level logging is enabled using the following command:

log --mod bt debug

Debug level logging is disable with the following command:

log --mod bt -debug

BT CLI Command

The bt CLI command provides current Bluetooth status information:

# bt
Device name: Ayla-6f72
Ayla id: 36b1eccc:dcf183f0
BLE advertisements: active
Pairing mode: disabled

Active connections:
0: handle 0 peer 88:66:a5:68:1d:c2

--- records in persisted storage ---
Our security:
0: 88:66:a5:68:1d:c2 key-size 16 ltk 1 irk 0 csrk 0 auth 0 sc 1

Peer security:
0: 88:66:a5:68:1d:c2 key-size 16 ltk 1 irk 1 csrk 0 auth 0 sc 1

0: 88:66:a5:68:1d:c2 handle 38 flags 0x0001 changed 0
1: 88:66:a5:68:1d:c2 handle 43 flags 0x0001 changed 0
2: 88:66:a5:68:1d:c2 handle 8 flags 0x0002 changed 0
3: 88:66:a5:68:1d:c2 handle 30 flags 0x0002 changed 0

Checking BLE Local Control Config

The enable status of BLE Local Control and LAN-mode can be determined by examining the device config.

On AylaDevKit devices (be sure to look for the entry starting with “s”, the factory config “f” will always contain 0:

--> conf
 s client/lan/enable = "3"

On ADA ayla_demo devices:

# nvs-get ada.client/lan/enable
ada.client/lan/enable : 3

The value of the enable parameter are a bit mask with 0x1 assigned to LAN-mode and 0x2 assigned to BLE LC:

0 - disabled
1 - LAN-mode enabled, BLE LC disabled
2 - LAN-mode disabled, BLE LC enabled
3 - LAN-mode enabled, BLE LC enabled

BT Error Codes in Log Messages

Error and reason codes a values from the Nimble BLE stack. Errors codes are printed in decimal but often need decoding to identify the specifics of the error Nimble is reporting. The following is an example of a log message with an error code given in decimal:

18:45:31.936 d b bt: disconnect reason 531

Error and reason codes a values from the Nimble BLE stack. If the value is less than 255, it is usually a direct error code from the Nimble host stack (ble_hs.h):

 * @brief Bluetooth Host Error Code
 * @defgroup bt_host_err Bluetooth Host Error Code
 * Defines error codes returned by Bluetooth host. If error comes from specific
 * component (eg L2CAP or Security Manager) it is shifted by base allowing to
 * identify component.
 * @{

#define BLE_HS_EAGAIN               1
#define BLE_HS_EALREADY             2
#define BLE_HS_EINVAL               3
#define BLE_HS_EMSGSIZE             4
#define BLE_HS_ENOENT               5
#define BLE_HS_ENOMEM               6
#define BLE_HS_ENOTCONN             7
#define BLE_HS_ENOTSUP              8
#define BLE_HS_EAPP                 9
#define BLE_HS_EBADDATA             10
#define BLE_HS_EOS                  11
#define BLE_HS_ECONTROLLER          12
#define BLE_HS_ETIMEOUT             13
#define BLE_HS_EDONE                14
#define BLE_HS_EBUSY                15
#define BLE_HS_EREJECT              16
#define BLE_HS_EUNKNOWN             17
#define BLE_HS_EROLE                18
#define BLE_HS_ETIMEOUT_HCI         19
#define BLE_HS_ENOMEM_EVT           20
#define BLE_HS_ENOADDR              21
#define BLE_HS_ENOTSYNCED           22
#define BLE_HS_EAUTHEN              23
#define BLE_HS_EAUTHOR              24
#define BLE_HS_EENCRYPT             25
#define BLE_HS_EENCRYPT_KEY_SZ      26
#define BLE_HS_ESTORE_CAP           27
#define BLE_HS_ESTORE_FAIL          28
#define BLE_HS_EPREEMPTED           29
#define BLE_HS_EDISABLED            30
#define BLE_HS_ESTALLED             31

Error values larger than 255 include a subsystem code in the most significant byte and an error code in the least significant byte. Decoding the error is a bit arcane. To do so, convert the decimal value to hexadecimal then look up the base using the upper byte with a lower byte of 0x00:

/** Error base for ATT errors */
#define BLE_HS_ERR_ATT_BASE         0x100

/** Error base for HCI errors */
#define BLE_HS_ERR_HCI_BASE         0x200

/** Error base for L2CAP errors */
#define BLE_HS_ERR_L2C_BASE         0x300

/** Error base for local Security Manager errors */
#define BLE_HS_ERR_SM_US_BASE       0x400

/** Error base for remote (peer) Security Manager errors */
#define BLE_HS_ERR_SM_PEER_BASE     0x500

/** Error base for hardware errors */
#define BLE_HS_ERR_HW_BASE          0x600

The definition of the error code depends on the subsystem. They are most often errors defined by the BLE spec (ble.h):

/* BLE Error Codes (Core v4.2 Vol 2 part D) */
enum ble_error_codes
    /* An "error" code of 0x0 means success */
    BLE_ERR_SUCCESS             = 0x00,
    BLE_ERR_UNKNOWN_HCI_CMD     = 0x01,
    BLE_ERR_UNK_CONN_ID         = 0x02,
    BLE_ERR_HW_FAIL             = 0x03,
    BLE_ERR_PAGE_TMO            = 0x04,
    BLE_ERR_AUTH_FAIL           = 0x05,
    BLE_ERR_PINKEY_MISSING      = 0x06,
    BLE_ERR_MEM_CAPACITY        = 0x07,
    BLE_ERR_CONN_SPVN_TMO       = 0x08,
    BLE_ERR_CONN_LIMIT          = 0x09,
    BLE_ERR_ACL_CONN_EXISTS     = 0x0b,
    BLE_ERR_CMD_DISALLOWED      = 0x0c,
    BLE_ERR_CONN_REJ_BD_ADDR    = 0x0f,
    BLE_ERR_CONN_ACCEPT_TMO     = 0x10,
    BLE_ERR_UNSUPPORTED         = 0x11,
    BLE_ERR_CONN_TERM_LOCAL     = 0x16,
    BLE_ERR_NO_PAIRING          = 0x18,
    BLE_ERR_UNK_LMP             = 0x19,
    BLE_ERR_SCO_OFFSET          = 0x1b,
    BLE_ERR_SCO_ITVL            = 0x1c,
    BLE_ERR_SCO_AIR_MODE        = 0x1d,
    BLE_ERR_INV_LMP_LL_PARM     = 0x1e,
    BLE_ERR_UNSPECIFIED         = 0x1f,
    BLE_ERR_NO_ROLE_CHANGE      = 0x21,
    BLE_ERR_LMP_LL_RSP_TMO      = 0x22,
    BLE_ERR_LMP_COLLISION       = 0x23,
    BLE_ERR_LMP_PDU             = 0x24,
    BLE_ERR_LINK_KEY_CHANGE     = 0x26,
    BLE_ERR_UNSUPP_QOS          = 0x27,
    BLE_ERR_INSTANT_PASSED      = 0x28,
    BLE_ERR_DIFF_TRANS_COLL     = 0x2a,
    /* BLE_ERR_RESERVED         = 0x2b */
    BLE_ERR_QOS_PARM            = 0x2c,
    BLE_ERR_QOS_REJECTED        = 0x2d,
    BLE_ERR_CHAN_CLASS          = 0x2e,
    /* BLE_ERR_RESERVED         = 0x31 */
    BLE_ERR_PENDING_ROLE_SW     = 0x32,
    /* BLE_ERR_RESERVED         = 0x33 */
    BLE_ERR_RESERVED_SLOT       = 0x34,
    BLE_ERR_ROLE_SW_FAIL        = 0x35,
    BLE_ERR_INQ_RSP_TOO_BIG     = 0x36,
    BLE_ERR_SEC_SIMPLE_PAIR     = 0x37,
    BLE_ERR_HOST_BUSY_PAIR      = 0x38,
    BLE_ERR_CTLR_BUSY           = 0x3a,
    BLE_ERR_CONN_PARMS          = 0x3b,
    BLE_ERR_DIR_ADV_TMO         = 0x3c,
    BLE_ERR_CONN_TERM_MIC       = 0x3d,
    BLE_ERR_MAC_CONN_FAIL       = 0x3f,
    BLE_ERR_COARSE_CLK_ADJ      = 0x40,
    BLE_ERR_UNK_ADV_INDENT      = 0x42,
    BLE_ERR_LIMIT_REACHED       = 0x43,
    BLE_ERR_MAX                 = 0xff

Error codes from the ATT subsystem are:

#define BLE_ATT_ERR_INVALID_HANDLE          0x01
#define BLE_ATT_ERR_INVALID_PDU             0x04
#define BLE_ATT_ERR_REQ_NOT_SUPPORTED       0x06
#define BLE_ATT_ERR_INVALID_OFFSET          0x07
#define BLE_ATT_ERR_ATTR_NOT_FOUND          0x0a
#define BLE_ATT_ERR_ATTR_NOT_LONG           0x0b
#define BLE_ATT_ERR_UNLIKELY                0x0e
#define BLE_ATT_ERR_INSUFFICIENT_ENC        0x0f
#define BLE_ATT_ERR_INSUFFICIENT_RES        0x11

Here is an example of decoding a result code in the following message:
18:45:31.936 d b bt: disconnect reason 531

531 = 0x213

  • base: 0x200 (BLE_HS_ERR_HCI_BASE)
  • error code: 0x13 (BLE_ERR_REM_USER_CONN_TERM)

The HCI subsystem (Host Controller Interface) has indicated that the remote user terminated the connection (mobile app was shutdown in this case).

Did this page help you?