#include "em_common.h"
#include "app_assert.h"
#include "sl_bluetooth.h"
#include "gatt_db.h"
#include "app.h"
#include "sl_sensor_rht.h"
// The advertising set handle allocated from Bluetooth stack.
static uint8_t advertising_set_handle = 0xff;
uint32_t nextMeasurementTick;
uint32_t interval;
uint8_t temperature_measurement_config;
uint8_t connection;
struct __attribute__((packed)) {
uint8_t flags;
uint32_t encodedValue;
} measurementData;
uint32_t encodeValue(float value) {
uint8_t exponent = -3;
int32_t number = 1000*value;
return (0x00ffffff & number) | (exponent << 24);
}
/**************************************************************************//**
* Application Init.
*****************************************************************************/
void app_init(void)
{
interval = sl_sleeptimer_get_timer_frequency();
temperature_measurement_config = 0;
sl_sensor_rht_init();
}
/**************************************************************************//**
* Application Process Action.
*****************************************************************************/
void app_process_action(void)
{
uint32_t now = sl_sleeptimer_get_tick_count();
if (now > nextMeasurementTick) {
nextMeasurementTick = now + interval;
if(2 == temperature_measurement_config) {
sl_status_t sc;
int32_t temperature = 0;
uint32_t humidity = 0;
// Measure temperature; units are % and milli-Celsius.
sc = sl_sensor_rht_get(&humidity, &temperature);
if(SL_STATUS_OK == sc) {
measurementData.flags = 0;
measurementData.encodedValue = encodeValue(1e-3 * temperature);
sl_bt_gatt_server_send_indication(connection, gattdb_temperature_measurement, 5, (uint8_t*)&measurementData);
}
}
}
}
/**************************************************************************//**
* Bluetooth stack event handler.
* This overrides the dummy weak implementation.
*
* @param[in] evt Event coming from the Bluetooth stack.
*****************************************************************************/
void sl_bt_on_event(sl_bt_msg_t *evt)
{
sl_status_t sc;
bd_addr address;
uint8_t address_type;
uint8_t system_id[8];
switch (SL_BT_MSG_ID(evt->header)) {
// -------------------------------
// This event indicates the device has started and the radio is ready.
// Do not call any stack command before receiving this boot event!
case sl_bt_evt_system_boot_id:
// Extract unique ID from BT Address.
sc = sl_bt_system_get_identity_address(&address, &address_type);
app_assert_status(sc);
// Pad and reverse unique ID to get System ID.
system_id[0] = address.addr[5];
system_id[1] = address.addr[4];
system_id[2] = address.addr[3];
system_id[3] = 0xFF;
system_id[4] = 0xFE;
system_id[5] = address.addr[2];
system_id[6] = address.addr[1];
system_id[7] = address.addr[0];
sc = sl_bt_gatt_server_write_attribute_value(gattdb_system_id,
0,
sizeof(system_id),
system_id);
app_assert_status(sc);
// 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);
// Start general advertising and enable connections.
sc = sl_bt_advertiser_start(
advertising_set_handle,
sl_bt_advertiser_general_discoverable,
sl_bt_advertiser_connectable_scannable);
app_assert_status(sc);
break;
// -------------------------------
// This event indicates that a new connection was opened.
case sl_bt_evt_connection_opened_id:
connection = evt->data.evt_connection_opened.connection;
break;
// -------------------------------
// This event indicates that a connection was closed.
case sl_bt_evt_connection_closed_id:
temperature_measurement_config = 0; // no more indications after close
// Restart advertising after client has disconnected.
sc = sl_bt_advertiser_start(
advertising_set_handle,
sl_bt_advertiser_general_discoverable,
sl_bt_advertiser_connectable_scannable);
app_assert_status(sc);
break;
case sl_bt_evt_gatt_server_characteristic_status_id:
if(gattdb_temperature_measurement == evt->data.evt_gatt_server_characteristic_status.characteristic) {
if(1 == evt->data.evt_gatt_server_characteristic_status.status_flags) {
temperature_measurement_config = evt->data.evt_gatt_server_characteristic_status.client_config_flags;
}
}
break;
///////////////////////////////////////////////////////////////////////////
// Add additional event handlers here as your application requires! //
///////////////////////////////////////////////////////////////////////////
// -------------------------------
// Default event handler.
default:
break;
}
}