BLE Hands on Beacon Solution - joe-possum/IoT-Developer-Boot-Camp GitHub Wiki
The following is my entire "app.c" which can be dropped in to Bluetooth - SoC Empty. It requires the Bluetooth Feature Legacy Advertiser and Platform Driver TEMPDRV.
#include "em_common.h"
#include "app_assert.h"
#include "sl_bluetooth.h"
#include "gatt_db.h"
#include "app.h"
#include "tempdrv.h"
// The advertising set handle allocated from Bluetooth stack.
static uint8_t advertising_set_handle = 0xff;
// Structure for Eddystone TLM beacon --- contains big-endian fields
struct __attribute__((packed)) {
uint8_t len_serviceList, type_serviceList;
uint16_t serviceList[1];
uint8_t len_serviceData, type_serviceData;
uint16_t id;
uint8_t frameType, version;
uint16_t be_mvBattery;
int16_t be_temperature;
uint32_t be_pduCount, be_time;
} advData = { .len_serviceList = 3,
.type_serviceList = 3,
.serviceList = { 0xfeaa },
.len_serviceData = 0x11,
.type_serviceData = 0x16,
.id = 0xfeaa,
.frameType = 0x20,
.version = 0,
.be_mvBattery = 0,
};
// Flag to indicate AdvData should be updated in app_process_action()
bool update_advData = false;
// Running counter for advertisement packets
uint32_t advCount;
void setAdvData(void) {
sl_status_t sc;
uint16_t tx_packets, rx_packets, crc_errors, failures;
int16_t temperature = TEMPDRV_GetTemp() << 8;
uint32_t time = 10*sl_sleeptimer_get_tick_count64()/sl_sleeptimer_get_timer_frequency();
sc = sl_bt_system_get_counters(1, &tx_packets, &rx_packets, &crc_errors, &failures);
app_assert_status(sc);
advCount += rx_packets;
advData.be_temperature = __builtin_bswap16((int16_t) temperature);
advData.be_pduCount = __builtin_bswap32(advCount);
advData.be_time = __builtin_bswap32(time);
sc = sl_bt_legacy_advertiser_set_data(advertising_set_handle, 0, 22, (uint8_t*)&advData);
app_assert_status(sc);
}
void app_init(void)
{
app_assert(22 == sizeof(advData));
TEMPDRV_Init();
advCount = 0;
}
SL_WEAK void app_process_action(void)
{
if(update_advData) setAdvData();
}
void sl_bt_on_event(sl_bt_msg_t *evt)
{
sl_status_t sc;
switch (SL_BT_MSG_ID(evt->header)) {
case sl_bt_evt_system_boot_id:
// Create an advertising set.
sc = sl_bt_advertiser_create_set(&advertising_set_handle);
app_assert_status(sc);
// Set advertising interval to 100ms.
sc = sl_bt_advertiser_set_timing(
advertising_set_handle,
160, // min. adv. interval (milliseconds * 1.6)
160, // max. adv. interval (milliseconds * 1.6)
0, // adv. duration
0); // max. num. adv. events
app_assert_status(sc);
// Set initial data before starting advertisement
setAdvData();
// Start advertising
sc = sl_bt_legacy_advertiser_start(advertising_set_handle,
sl_bt_advertiser_non_connectable);
app_assert_status(sc);
update_advData = true;
break;
// Default event handler.
default:
app_assert("No other events expected");
break;
}
}