Hi!
I am fully aware on how Eddystone works. Or at least I believe so. Sadly there is some weirdnesses when I am trying to broadcast using the Nordic SDK.
So what am I trying to do:
- Send a URL to my Webpage, so the Nearby API will recognize my Beacon and display a Notification.
- Send normal advertisement packets containing my available services.
- Send advertisement packets other centrals can receive and react to.
- Stay connectable and deliver more indepth data and measurements through the GATT DB.
Best would be if I could use the Mesh too, but as this does not work with API 14 I will refrain from that for now.
So what have I working:
- I can send a static advertisement packet containing a name and the available service UUID (more than one does not work funnily enough (One VS and one SIG, so that should be just 20 bytes + some overhead. One works tho which suffices). Running just the normal adverts, I can connect to the GATT DB just fine.
- I can advertise an Eddystone URL.
What are my issues:
- When advertise the Eddystone URL, I will not be able anymore to connect to GATT anymore.
- I can only advertise the Eddystone URL. No EID, UID or TLM. This is not a big issue but I also can't advertise any normal packets anymore. And I would absolutely like to have those.
So what did I do and try to fix this stuff:
I did not find any real docs on the Eddystone API. Well sure there is function declarations and a very brief explanation of them. The rest is really shady to me. So I had a look at the example to figure how to use the Eddystone API.
Sadly there is just a few general functions invoking the ESCS which I don't even want as I just want a beacon that broadcasts device data that the device sets itself.
Then there is a huge set of config flags which I set like this
#define MAC_RANDOMIZED //!< Configuration option to specify whether the BLE address should be randomized when advertising EIDs.
#define APP_CONFIG_LOCK_CODE {0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF, \
0xFF, 0xFF, 0xFF, 0xFF} //!< Beacon lock code. @warning This lock code must be changed before going to production.
#ifdef NRF52
#define APP_CONFIG_CALIBRATED_RANGING_DATA {-49, -39, -29, -24, -19, -14, -9, -7, -5} //!< Calibrated TX power at 0 m. See the nRF52 Product Specification for corresponding TX values.
#elif NRF51
#define APP_CONFIG_CALIBRATED_RANGING_DATA {-39, -26, -23, -18, -13, -12, -9, -2} //!< Calibrated TX power at 0 m. See the nRF51 Product Specification for corresponding TX values.
#else
#error MISSING CALIBRATED DATA
#endif
#define APP_CONFIG_TLM_TEMP_VBATT_UPDATE_INTERVAL_SECONDS 10 //!< How often should the data in the TLM frame be updated.
#define APP_CONFIG_TLM_ADV_INTERLEAVE_RATIO 5 //!< How often should the TLM frame be advertised.
#define APP_CONFIG_ADV_INTERVAL_MS_MAX 20000 //!< Maximum allowed advertisement interval. Can be undefined without int
#define APP_CONFIG_ADV_FRAME_SPACING_MS_MIN 500 //!< Minimum time between advertisement frames. Imposes limit on minumum accepted advertisement interval.
#ifdef NRF52
#define APP_CONFIG_ADV_FRAME_ETLM_SPACING_MS 300 //!< The time that is reqired for preparing an eTLM slot. Imposes limit on minimum accepted advertisement interval.
#else
#error MISSING ETLM DELAY TIMING
#endif
#define ES_STOPWATCH_MAX_USERS 4 //!< Maximum amount of users that can be registered with the es_stopwatch module.
#define DEBUG_TIMING_INIT_VALUE 65280 //!< Initial time (as recommended by Google) to test the TK rollover behavior.
#define APP_CONFIG_TIMING_INIT_VALUE DEBUG_TIMING_INIT_VALUE //!< Initializing value for the timing value of security slots.
#define APP_CONFIG_TLM_TEMP_INTERVAL_SECONDS (30) //!< How often should the temperature of the beacon be updated when TLM slot is configured.
#define APP_CONFIG_TLM_VBATT_INTERVAL_SECONDS (30) //!< How often should the battery voltage of the beacon be updated when TLM slot is configured.
// HW CONFIGS
#define BUTTON_REGISTRATION BUTTON_1 //!< Button to push when putting the beacon in registration mode.
#define USE_ECB_ENCRYPT_HW 1 //!< Configuration option to use the hardware peripheral (1) or the software library (0) for ECB encryption (decryption always uses the software library).
// BLE CONFIGS
#define APP_DEVICE_NAME "nRF5x_Eddystone" //!< Advertised device name in the scan response when in connectable mode.
#define IS_SRVC_CHANGED_CHARACT_PRESENT 0 //!< Information whether the service changed characteristic is available. If it is not enabled, the server's database cannot be changed for the lifetime of the device.
#define MAX_ADV_INTERVAL (10240) //!< Maximum connection interval (in ms).
#define MIN_CONN_ADV_INTERVAL (20) //!< Minimum connection interval (in ms).
#define MIN_NON_CONN_ADV_INTERVAL (100) //!< Minimum advertisement interval for non-connectable advertisements (in ms).
#define APP_CFG_NON_CONN_ADV_TIMEOUT 0 //!< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables the time-out.
#define APP_CFG_NON_CONN_ADV_INTERVAL_MS 1000 //!< The advertising interval for non-connectable advertisement (in milliseconds). This value can vary between 100 ms and 10.24 s.
#define APP_CFG_CONNECTABLE_ADV_TIMEOUT 60 //!< Time for which the device must be advertising in connectable mode (in seconds). 0 disables the time-out.
#define APP_CFG_CONNECTABLE_ADV_INTERVAL_MS 100 //!< The advertising interval for connectable advertisement (in milliseconds). This value can vary between 20 ms and 10.24 s.
#define APP_CFG_DEFAULT_RADIO_TX_POWER 0x00 //!< Default TX power of the radio.
// ES CONFIGS
#define APP_MAX_ADV_SLOTS 5 //!< Maximum number of advertisement slots.
#define APP_MAX_EID_SLOTS APP_MAX_ADV_SLOTS /**< @brief Maximum number of EID slots.
* @note The maximum number of EID slots must be equal to the maximum number of advertisement slots (@ref APP_MAX_ADV_SLOTS). If your application
* does not adhere to this convention, you must modify the @ref eddystone_security module, because the security module maps the security slots'
* slot numbers 1 to 1 to the slots'. */
// Broadcast Capabilities
#define APP_IS_VARIABLE_ADV_SUPPORTED ESCS_BROADCAST_VAR_ADV_SUPPORTED_No //!< Information whether variable advertisement intervals are supported.
#define APP_IS_VARIABLE_TX_POWER_SUPPORTED ESCS_BROADCAST_VAR_TX_POWER_SUPPORTED_Yes //!< Information whether variable advertisement TX power is supported.
#define APP_IS_UID_SUPPORTED ESCS_FRAME_TYPE_UID_SUPPORTED_Yes //!< Information whether the UID frame is supported.
#define APP_IS_URL_SUPPORTED ESCS_FRAME_TYPE_URL_SUPPORTED_Yes //!< Information whether the URL frame is supported.
#define APP_IS_TLM_SUPPORTED ESCS_FRAME_TYPE_TLM_SUPPORTED_Yes //!< Information whether the TLM frame is supported.
#define APP_IS_EID_SUPPORTED ESCS_FRAME_TYPE_EID_SUPPORTED_Yes //!< Information whether the EID frame is supported.
// Remain connectable
#define APP_IS_REMAIN_CONNECTABLE_SUPPORTED ESCS_FUNCT_REMAIN_CONNECTABLE_SUPPORTED_Yes //!< Information whether the 'remain connectable' option is supported.
// Eddystone common data
#define APP_ES_UUID 0xFEAA //!< UUID for Eddystone beacons according to specification.
// Eddystone UID data
#define APP_ES_UID_FRAME_TYPE ES_FRAME_TYPE_UID //!< UID frame type (fixed at 0x00).
#define APP_ES_UID_NAMESPACE 0xAA, 0xAA, 0xBB, 0xBB, \
0xCC, 0xCC, 0xDD, 0xDD, \
0xEE, 0xEE //!< Mock values for 10-byte Eddystone UID ID namespace.
#define APP_ES_UID_ID 0x01, 0x02, 0x03, 0x04, \
0x05, 0x06 //!< Mock values for 6-byte Eddystone UID ID instance.
#define APP_ES_UID_RFU 0x00, 0x00 //!< Reserved for future use according to specification.
// Eddystone URL data
#define APP_ES_URL_FRAME_TYPE ES_FRAME_TYPE_URL //!< URL Frame type (fixed at 0x10).
#define APP_ES_URL_SCHEME 0x03 //!< URL prefix scheme according to specification (0x03 = "https://").
#define APP_ES_URL_URL 0x79, 0x61, 0x74, 0x65, 0x6B, 0x69, 0x69, 0x2E, 0x63, 0x68
#define DEFAULT_FRAME_TYPE APP_ES_URL_FRAME_TYPE //!< Frame type of default frame.
#define DEFAULT_FRAME_TX_POWER 0x00 //!< Default frame TX power.
/** @brief This value should mimic the data that would be written to the RW ADV Slot characteristic (for example, no RSSI for UID). */
#define DEFAULT_FRAME_DATA {DEFAULT_FRAME_TYPE, DEFAULT_FRAME_TX_POWER, APP_ES_URL_SCHEME, APP_ES_URL_URL}
#define DEFAULT_FRAME_LENGTH 13 //!< 1 - Frame Type, 1 - TX - power, 1 - URL Scheme, URL - 10 = 13
// SCHEDULER CONFIGS
#define SCHED_MAX_EVENT_DATA_SIZE APP_TIMER_SCHED_EVENT_DATA_SIZE //!< Maximum size of the scheduler event data.
#define SCHED_QUEUE_SIZE 10 //!< Size of the scheduler queue.
I am kind of sure that I wont even need 1/4 of those features.
Now how I think the API works is that I can set a set of advertisement slots (in my case 5) which I can fill with URL, UID, TLM or EID frames. Internally this will then have a scheduler configured that will cycle through all slots.
To make this work I put app_sched_execute();
into my main loop. Unfortunately it still will only display the URL frame and not the UID one. This is really sad.
To start the whole ES machinery I call nrf_ble_es_init(on_es_evt);
after I configured the statical normal advertisement frame with my UUIDs.
So much for the issues with advertising. Now I have the problem that I cannot connect to the GATT DB anymore when I change to ES adverts.
I suspected that this is because it defaults to non connectable mode. So after starting ES I immediately call nrf_ble_es_on_start_connectable_advertising()
resulting in
nrf_ble_es_init(on_es_evt);
nrf_ble_es_on_start_connectable_advertising();
on_es_evt
is the default eventhandler delivered with the example. Sadly this will ultimately result in a err_code == 7 in adv_start()
when calling sd_ble_gap_adv_start()
. Changing BLE_CONN_CFG_TAG_DEFAULT
to 1
will make the device advertise properly. It will then show my static adverts. And I am able to connect to the GATT DB. Unfortunately with that I would have to tamper with the SDK code which is not intended and I will also not be able to see the ES adverts.
So can anyone help me do this right? I am tinkering since hours and it seems that the example is overbloated to hell also using the saadc to measure battery voltage which I don't intend to do at all. I am also kind of sure I could figure how to do all of this after some time and just bisecting the entire SDK code until I hit the SD code (not visible unfortunately as docs are sometimes a bit vague ;)), but then my code might be just wrong in the macro scope.
I would be really grateful for a sample on how to get a ES broadcasting with alternating frames running without any service or measuring of data, just plain configuration of a frame and starting the adverts.
Thanks a whole lot in advance and have a nice day! Noah