How to advertise TX power of a peripheral

Hi,

I am programming the nRF52833 DK using the nRF Connect SDK (v2.00).  I have built and flashed the Bluetooth: Peripheral HT sample from Zephyr to both boards successfully. I use the Android nRF Connect app to connect to the SoC.

I would like to see what the TX power of the peripheral is so that I can confrim that it has been set as desired but I am not sure how to show this information. I have seen that some devices advertise soemthing like: "TX power level: 0dBm". How do I do this? I have attached a PDF file with a screenshot of this.

I have also attached a piece of code that shows the advertising data (taken from Bluetooth: Peripheral HT). I can see in the Zephyr gap.h file that there are numerous flags / data type definitions that can be used as adveritsing data. BT_DATA_TX_POWER is one of these - I tried to use it as shown blow (commented out) but it did not work.

Thanks,

Adam

static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	//BT_DATA_BYTES(BT_DATA_TX_POWER), 
	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
		      BT_UUID_16_ENCODE(BT_UUID_HTS_VAL),
		      BT_UUID_16_ENCODE(BT_UUID_DIS_VAL),
		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL)),
};

tx power data.pdf

Parents
  • Hello,

    I can find there is a bt_tx_power_adv_data_fill() implementation in bt_tx_power_adv.c that you likely you can use here. I can find that the peripheral_fast_pair example seem to call this from bt_adv_helper_tx_power_prepare(). Basically the bt_tx_power_adv_data_fill() will read out the tx power used in the controller and prepare to be used in advertisment. 

    static struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
    		      BT_UUID_16_ENCODE(BT_UUID_HIDS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL)),
    	/* Empty placeholder for TX power advertising data. */
    	{
    	},
    	/* Empty placeholder for Fast Pair advertising data. */
    	{
    	},
    };

    Best regards,
    Kenneth

Reply
  • Hello,

    I can find there is a bt_tx_power_adv_data_fill() implementation in bt_tx_power_adv.c that you likely you can use here. I can find that the peripheral_fast_pair example seem to call this from bt_adv_helper_tx_power_prepare(). Basically the bt_tx_power_adv_data_fill() will read out the tx power used in the controller and prepare to be used in advertisment. 

    static struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
    		      BT_UUID_16_ENCODE(BT_UUID_HIDS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL)),
    	/* Empty placeholder for TX power advertising data. */
    	{
    	},
    	/* Empty placeholder for Fast Pair advertising data. */
    	{
    	},
    };

    Best regards,
    Kenneth

Children
  • Thanks Kenneth,

    I have included the relevant files/functions from the fast pair sample into the Bluetooth: Peripheral HT sample; however, the applciation is failing to build. I have attached my main.c and prj.conf file. Please let me know if I am using the functions correctly - I have pointed out clearly the changes I have made to the Bluetooth: Peripheral HT sample.

    Adam

    /* main.c - Application main entry point */
    
    /*
     * Copyright (c) 2019 Aaron Tsui <[email protected]>
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr/types.h>
    #include <stddef.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/printk.h>
    #include <sys/byteorder.h>
    #include <zephyr.h>
    
    #include <bluetooth/bluetooth.h>
    #include <bluetooth/hci.h>
    #include <bluetooth/conn.h>
    #include <bluetooth/uuid.h>
    #include <bluetooth/gatt.h>
    #include <bluetooth/services/bas.h>
    
    #include "hts.h"
    #include "bt_tx_power_adv.h"
    
    // Taken from fast pair example
    #include <logging/log.h>
    //LOG_MODULE_DECLARE(fp_sample, LOG_LEVEL_INF);
    
    #define TX_POWER_ADV_DATA_POS	(ARRAY_SIZE(ad) - 2)
    //
    
    
    
    // Took away const
    static struct bt_data ad[] = {
    	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    	BT_DATA_BYTES(BT_DATA_UUID16_ALL,
    		      BT_UUID_16_ENCODE(BT_UUID_HTS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_DIS_VAL),
    		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL)),
    	/* Empty placeholder for TX power advertising data. */
    	{
    	},
    	/* Empty placeholder for Fast Pair advertising data. */
    	{
    	},
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err) {
    		printk("Connection failed (err 0x%02x)\n", err);
    	} else {
    		printk("Connected\n");
    	}
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	printk("Disconnected (reason 0x%02x)\n", reason);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {
    	.connected = connected,
    	.disconnected = disconnected,
    };
    
    
    //Added from fast pair sample
    static int bt_adv_helper_tx_power_prepare(struct bt_data *adv_data)
    {
    	/* Make sure that TX power data was freed and set to NULL to prevent memory leaks. */
    	if (adv_data->data) {
    		k_free((void *)adv_data->data);
    		adv_data->data = NULL;
    	}
    
    	size_t buf_size = bt_tx_power_adv_data_size();
    	uint8_t *buf = k_malloc(buf_size);
    
    	if (!buf) {
    		return -ENOMEM;
    	}
    
    	int err = bt_tx_power_adv_data_fill(adv_data, buf, buf_size);
    
    	if (err) {
    		k_free(buf);
    	}
    
    	return err;
    }
    /////
    
    
    
    
    static void bt_ready(void)
    {
    	int err;
    
    	printk("Bluetooth initialized\n");
    
    	hts_init();
    
    	// Added from fast pair example
    	err = bt_adv_helper_tx_power_prepare(&ad[TX_POWER_ADV_DATA_POS]);
    	if (err) {
    		LOG_ERR("Cannot prepare TX power advertising data (err: %d)", err);
    		return err;
    	}
    	///////
    
    	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Advertising failed to start (err %d)\n", err);
    		return;
    	}
    
    	printk("Advertising successfully started\n");
    }
    
    static void auth_cancel(struct bt_conn *conn)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	printk("Pairing cancelled: %s\n", addr);
    }
    
    static struct bt_conn_auth_cb auth_cb_display = {
    	.cancel = auth_cancel,
    };
    
    static void bas_notify(void)
    {
    	uint8_t battery_level = bt_bas_get_battery_level();
    
    	battery_level--;
    
    	if (!battery_level) {
    		battery_level = 100U;
    	}
    
    	bt_bas_set_battery_level(battery_level);
    }
    
    void main(void)
    {
    	int err;
    
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return;
    	}
    
    	bt_ready();
    
    	bt_conn_auth_cb_register(&auth_cb_display);
    
    	/* Implement indicate. At the moment there is no suitable way
    	 * of starting delayed work so we do it here
    	 */
    	while (1) {
    		k_sleep(K_SECONDS(1));
    
    		/* Temperature measurements simulation */
    		hts_indicate();
    
    		/* Battery level simulation */
    		bas_notify();
    	}
    }
    

    CONFIG_BT=y
    CONFIG_BT_DEBUG_LOG=y
    CONFIG_BT_SMP=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DIS=y
    CONFIG_BT_DIS_PNP=y
    CONFIG_BT_BAS=y
    CONFIG_BT_DEVICE_NAME="Zephyr Health Thermometer"
    CONFIG_BT_DEVICE_APPEARANCE=768
    CONFIG_BT_ATT_ENFORCE_FLOW=n
    CONFIG_CBPRINTF_FP_SUPPORT=y
    
    CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y

Related