Transmitting data in beacon mode, but am not seeing all data.

I'm using beacon mode to transmit a set of data which is stored as hex code. I've set the advertising data to iterate through the data set 10 times. When looking at the data with a sniffer on Wireshark, all the data is not sent, and it will sometimes send the data in a group rather than separately. Ideally, I would be able to send the data most efficiently. Code is attached and the data is stored in data.h. Not sure if this is an issue with Wireshark or I need to store data in different packet sizes before sending.

/* main.c - Application main entry point */

/*
 * Copyright (c) 2015-2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <stdbool.h>
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include "Tdata.h"

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

#define LED_DRIVE 		0x74	//bit 7 -0 off 1 on, bit 0:6 LED driving strength. 000 0000: 4mA 000 0001: 6mA 000 0010: 8mA
#define COMPANY_ID_CODE         0x0059




static unsigned char url_data[] = { 0x17, '/', '/', 'a', 'c', 'a', 'd', 'e', 'm',
	'y',  '.', 'n', 'o', 'r', 'd', 'i', 'c', 's',
	'e',  'm', 'i', '.', 'c', 'o', 'm' };

/*Create an LE Advertising Parameters variable */
static struct bt_le_adv_param *adv_param =
	BT_LE_ADV_PARAM(BT_LE_ADV_OPT_NONE, /* No options specified */
			32, /* Min Advertising Interval 500ms (800*0.625ms) [20ms (32*0.625)] */
			40, /* Max Advertising Interval 500.625ms (801*0.625ms) [25ms (35*0.625)] */
			NULL); /* Set to NULL for undirected advertising */ 
typedef struct adv_mfg_data {
	uint16_t company_code;	    /* Company Identifier Code. */
	uint16_t Transmit;      /* Recordings from sensor*/
} adv_mfg_data_type;

static adv_mfg_data_type adv_mfg_data = {COMPANY_ID_CODE,0x00};

/*Set Advertisement data*/
static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
	BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char *)&adv_mfg_data, sizeof(adv_mfg_data)),
};

/* Set Scan Response data */
static const struct bt_data sd[] = {
	BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)),
};


static void bt_ready(int err)
{
	char addr_s[BT_ADDR_LE_STR_LEN];
	bt_addr_le_t addr = {0};
	size_t count = 1;

	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
		return;
	}

	printk("Bluetooth initialized\n");

	/* Start advertising */
	err = bt_le_adv_start(BT_LE_ADV_NCONN_IDENTITY, ad, ARRAY_SIZE(ad),
			      sd, ARRAY_SIZE(sd));
	if (err) {
		printk("Advertising failed to start (err %d)\n", err);
		return;
	}

	/* For connectable advertising you would use
	 * bt_le_oob_get_local().  For non-connectable non-identity
	 * advertising an non-resolvable private address is used;
	 * there is no API to retrieve that.
	 */

	bt_id_get(&addr, &count);
	bt_addr_le_to_str(&addr, addr_s, sizeof(addr_s));

	printk("Beacon started, advertising as %s\n", addr_s);
}

int main(void)
{
	int i, j;
	int err;
	
	printk("Starting Beacon\n");
	/* Initialize the Bluetooth Subsystem */
	err = bt_enable(bt_ready);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
	}


	for(i=0; i<10; i++){
		for(j=0; j<sizeof(data); j++){
		/*Update the advertising data dynamically */
		adv_mfg_data.Transmit = data[j];
		bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
        }
	}

	return 0;
}

Parents
  • John,

    What are you trying to achieve exactly? 

    "trying to send data most efficiently" and "sending data in groups" does not seems to conflict. What is the exact problem that you are trying to solve? I cannot look into your code with a generalized problem. We need very specific issue that you are trying to solve to invest time into code debugging.

  • Hi Susheel, the main goal is sending the data in the most power efficient manner. The issue I'm finding with the code above; it looks like the advertised data is not updating as I expected to. What I expected to happen is one hex code would be advertised and then updated to the next one until the whole section has been iterated through. When looking on Wireshark, this is not what is being received.

  • Hi John,

    Understood what you need now. Your loop of advertising send is basically flooding the packets, the controller will only transmit what ever last updated adv data it had before it schedules an outgoing packet. During that time your loop can update the advertising data twice and only one could have been sent out as the other one was overwritten before the controller to schedule it out.

    Wireshark/scanners could miss advertising packets, And you should not design anything where you assume that scanners cannot miss advertising packets. 

    I suggest that instead of flooding the adv update, you wait around advertising interval time so that your every update have a maximum chance of being scheduled by the controller to be sent out. Something like this

    for (i = 0; i < 10; i++) {
        for (j = 0; j < ARRAY_SIZE(data); j++) {
            adv_mfg_data.Transmit = data[j];
            err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
            if (err) {
                printk("adv update err %d\n", err);
            }
            k_msleep(50); /* something >= adv interval so it actually gets sent */
        }
    }
    

Reply
  • Hi John,

    Understood what you need now. Your loop of advertising send is basically flooding the packets, the controller will only transmit what ever last updated adv data it had before it schedules an outgoing packet. During that time your loop can update the advertising data twice and only one could have been sent out as the other one was overwritten before the controller to schedule it out.

    Wireshark/scanners could miss advertising packets, And you should not design anything where you assume that scanners cannot miss advertising packets. 

    I suggest that instead of flooding the adv update, you wait around advertising interval time so that your every update have a maximum chance of being scheduled by the controller to be sent out. Something like this

    for (i = 0; i < 10; i++) {
        for (j = 0; j < ARRAY_SIZE(data); j++) {
            adv_mfg_data.Transmit = data[j];
            err = bt_le_adv_update_data(ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
            if (err) {
                printk("adv update err %d\n", err);
            }
            k_msleep(50); /* something >= adv interval so it actually gets sent */
        }
    }
    

Children
Related