summaryrefslogtreecommitdiff
path: root/src/BLE
diff options
context:
space:
mode:
authorJF <jf@codingfield.com>2020-03-25 21:23:40 +0100
committerJF <jf@codingfield.com>2020-03-25 21:23:40 +0100
commit68240704c7a60534342cfc0157564f11cf82d9d8 (patch)
tree8472af61a5fa8a99ce5549f2de73b47f73cf41b6 /src/BLE
parent7e9a7e4d5fa0f55b43180600d499f1d0ce6aded1 (diff)
Add support for BLE notification (ANS client).
Work In Progress!!!
Diffstat (limited to 'src/BLE')
-rw-r--r--src/BLE/BleManager.c220
-rw-r--r--src/BLE/BleManager.h4
2 files changed, 218 insertions, 6 deletions
diff --git a/src/BLE/BleManager.c b/src/BLE/BleManager.c
index 48653982..b7d6074a 100644
--- a/src/BLE/BleManager.c
+++ b/src/BLE/BleManager.c
@@ -12,6 +12,7 @@
#include <ble/ble_services/ble_hrs/ble_hrs.h>
#include <ble/ble_services/ble_bas/ble_bas.h>
#include <ble/ble_services/ble_dis/ble_dis.h>
+#include <ble/ble_services/ble_ans_c/ble_ans_c.h>
#include <ble/common/ble_conn_params.h>
#include <libraries/fds/fds.h>
#include "nrf_sdh_soc.h"
@@ -42,14 +43,31 @@ void ble_manager_cts_print_time(ble_cts_c_evt_t *p_evt);
void ble_manager_conn_params_event_handler(ble_conn_params_evt_t *p_evt);
void ble_manager_conn_params_error_handler(uint32_t nrf_error);
+typedef enum
+{
+ ALERT_NOTIFICATION_DISABLED, /**< Alert Notifications has been disabled. */
+ ALERT_NOTIFICATION_ENABLED, /**< Alert Notifications has been enabled. */
+ ALERT_NOTIFICATION_ON, /**< Alert State is on. */
+} ble_ans_c_alert_state_t;
+
+void on_ans_c_evt(ble_ans_c_evt_t * p_evt);
+void alert_notification_error_handler(uint32_t nrf_error);
+void handle_alert_notification(ble_ans_c_evt_t * p_evt);
+void supported_alert_notification_read(void);
+void alert_notification_setup(void);
+void control_point_setup(ble_ans_c_evt_t * p_evt);
+
uint16_t ble_manager_connection_handle = BLE_CONN_HANDLE_INVALID; // Handle of the current connection.
NRF_BLE_QWR_DEF(ble_manager_queue_write); // Context for the Queued Write module.
BLE_CTS_C_DEF(ble_manager_cts_client); // Current Time service instance.
NRF_BLE_GATT_DEF(ble_manager_gatt); // GATT module instance.
BLE_ADVERTISING_DEF(ble_manager_advertising); // Advertising module instance.
BLE_DB_DISCOVERY_DEF(ble_manager_db_discovery);
+BLE_ANS_C_DEF(m_ans_c);
-
+static uint8_t m_alert_message_buffer[MESSAGE_BUFFER_SIZE]; /**< Message buffer for optional notify messages. */
+static ble_ans_c_alert_state_t m_new_alert_state = ALERT_NOTIFICATION_DISABLED; /**< State that holds the current state of New Alert Notifications, i.e. Enabled, Alert On, Disabled. */
+static ble_ans_c_alert_state_t m_unread_alert_state = ALERT_NOTIFICATION_DISABLED; /**< State that holds the current state of Unread Alert Notifications, i.e. Enabled, Alert On, Disabled. */
static ble_uuid_t ble_manager_advertising_uuids[] = /* Universally unique service identifiers.*/
{
@@ -88,6 +106,21 @@ static char const *month_of_year[] =
"December"
};
+static char const * lit_catid[BLE_ANS_NB_OF_CATEGORY_ID] =
+ {
+ "Simple alert",
+ "Email",
+ "News",
+ "Incoming call",
+ "Missed call",
+ "SMS/MMS",
+ "Voice mail",
+ "Schedule",
+ "High prioritized alert",
+ "Instant message"
+ };
+
+
void ble_manager_init() {
ble_manager_init_stack();
ble_manager_init_gap_params();
@@ -133,6 +166,11 @@ void ble_manager_set_ble_disconnection_callback(void (*OnBleDisconnection)()) {
OnBleDisconnectionCallback = OnBleDisconnection;
}
+void (*OnNewNotificationCallback)(const char* message, uint8_t size);
+void ble_manager_set_new_notification_callback(void (*OnNewNotification)(const char*, uint8_t size)) {
+ OnNewNotificationCallback = OnNewNotification;
+}
+
void ble_manager_event_handler(ble_evt_t const *p_ble_evt, void *p_context) {
uint32_t err_code;
@@ -227,6 +265,8 @@ void ble_manager_init_db_discovery() {
void ble_manager_discover_handler(ble_db_discovery_evt_t *p_evt) {
ble_cts_c_on_db_disc_evt(&ble_manager_cts_client, p_evt);
+ NRF_LOG_INFO("ble_ans_c_on_db_disc_evt");
+ ble_ans_c_on_db_disc_evt(&m_ans_c, p_evt);
}
void ble_manager_init_advertising() {
@@ -382,12 +422,165 @@ void ble_manager_start_advertising(void *p_erase_bonds) {
}
}
+void handle_alert_notification(ble_ans_c_evt_t * p_evt)
+{
+ ret_code_t err_code;
+
+ if (p_evt->uuid.uuid == BLE_UUID_UNREAD_ALERT_CHAR)
+ {
+ if (m_unread_alert_state == ALERT_NOTIFICATION_ENABLED)
+ {
+// err_code = bsp_indication_set(BSP_INDICATE_ALERT_1);
+ APP_ERROR_CHECK(err_code);
+ m_unread_alert_state = ALERT_NOTIFICATION_ON;
+ NRF_LOG_INFO("Unread Alert state: On.");
+ NRF_LOG_INFO(" Category: %s",
+ (uint32_t)lit_catid[p_evt->data.alert.alert_category]);
+ NRF_LOG_INFO(" Number of unread alerts: %d",
+ p_evt->data.alert.alert_category_count);
+ }
+ }
+ else if (p_evt->uuid.uuid == BLE_UUID_NEW_ALERT_CHAR)
+ {
+// if (m_new_alert_state == ALERT_NOTIFICATION_ENABLED)
+ if(true)
+ {
+// err_code = bsp_indication_set(BSP_INDICATE_ALERT_0);
+// APP_ERROR_CHECK(err_code);
+ m_new_alert_state = ALERT_NOTIFICATION_ON;
+ NRF_LOG_INFO("New Alert state: On.");
+ NRF_LOG_INFO(" Category: %s",
+ (uint32_t)lit_catid[p_evt->data.alert.alert_category]);
+ NRF_LOG_INFO(" Number of new alerts: %d",
+ p_evt->data.alert.alert_category_count);
+ NRF_LOG_INFO(" Text String Information: (%d) %s",
+ p_evt->data.alert.alert_msg_length, (uint32_t)p_evt->data.alert.p_alert_msg_buf);
+
+ OnNewNotificationCallback(p_evt->data.alert.p_alert_msg_buf, p_evt->data.alert.alert_msg_length);
+ }
+ }
+ else
+ {
+ // Only Unread and New Alerts exists, thus do nothing.
+ }
+}
+
+void supported_alert_notification_read(void)
+{
+ NRF_LOG_INFO("Read supported Alert Notification characteristics on the connected peer.");
+
+ ret_code_t err_code;
+
+ err_code = ble_ans_c_new_alert_read(&m_ans_c);
+ APP_ERROR_CHECK(err_code);
+
+ err_code = ble_ans_c_unread_alert_read(&m_ans_c);
+ APP_ERROR_CHECK(err_code);
+
+}
+
+void alert_notification_setup(void)
+{
+ ret_code_t err_code;
+
+ err_code = ble_ans_c_enable_notif_new_alert(&m_ans_c);
+ APP_ERROR_CHECK(err_code);
+
+ m_new_alert_state = ALERT_NOTIFICATION_ENABLED;
+ NRF_LOG_INFO("New Alert State: Enabled.");
+
+ err_code = ble_ans_c_enable_notif_unread_alert(&m_ans_c);
+ APP_ERROR_CHECK(err_code);
+
+ m_unread_alert_state = ALERT_NOTIFICATION_ENABLED;
+ NRF_LOG_INFO("Unread Alert State: Enabled.");
+
+ NRF_LOG_INFO("Notifications enabled.");
+}
+
+void control_point_setup(ble_ans_c_evt_t * p_evt)
+{
+ uint32_t err_code;
+ ble_ans_control_point_t setting;
+
+ if (p_evt->uuid.uuid == BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR)
+ {
+ setting.command = ANS_ENABLE_UNREAD_CATEGORY_STATUS_NOTIFICATION;
+ setting.category = (ble_ans_category_id_t)p_evt->data.alert.alert_category;
+ NRF_LOG_INFO("Unread status notification enabled for received categories.");
+ }
+ else if (p_evt->uuid.uuid == BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR)
+ {
+ setting.command = ANS_ENABLE_NEW_INCOMING_ALERT_NOTIFICATION;
+ setting.category = (ble_ans_category_id_t)p_evt->data.alert.alert_category;
+ NRF_LOG_INFO("New incoming notification enabled for received categories.");
+ }
+ else
+ {
+ return;
+ }
+
+ err_code = ble_ans_c_control_point_write(&m_ans_c, &setting);
+ APP_ERROR_CHECK(err_code);
+}
+
+void on_ans_c_evt(ble_ans_c_evt_t * p_evt)
+{
+ ret_code_t err_code;
+ NRF_LOG_INFO("ANS %d", p_evt->evt_type);
+
+
+ switch (p_evt->evt_type)
+ {
+ case BLE_ANS_C_EVT_DISCOVERY_FAILED:
+ NRF_LOG_INFO("ANS discovery failed");
+ break;
+ case BLE_ANS_C_EVT_NOTIFICATION:
+ handle_alert_notification(p_evt);
+ NRF_LOG_INFO("Alert Notification received from server, UUID: %X.", p_evt->uuid.uuid);
+ break; // BLE_ANS_C_EVT_NOTIFICATION
+
+ case BLE_ANS_C_EVT_DISCOVERY_COMPLETE:
+ NRF_LOG_INFO("Alert Notification Service discovered on the server.");
+ err_code = ble_ans_c_handles_assign(&m_ans_c,
+ p_evt->conn_handle,
+ &p_evt->data.service);
+ APP_ERROR_CHECK(err_code);
+ supported_alert_notification_read();
+ alert_notification_setup();
+ break; // BLE_ANS_C_EVT_DISCOVERY_COMPLETE
+
+ case BLE_ANS_C_EVT_READ_RESP:
+ NRF_LOG_INFO("Alert Setup received from server, UUID: %X.", p_evt->uuid.uuid);
+ control_point_setup(p_evt);
+ break; // BLE_ANS_C_EVT_READ_RESP
+
+ case BLE_ANS_C_EVT_DISCONN_COMPLETE:
+ m_new_alert_state = ALERT_NOTIFICATION_DISABLED;
+ m_unread_alert_state = ALERT_NOTIFICATION_DISABLED;
+
+// err_code = bsp_indication_set(BSP_INDICATE_ALERT_OFF);
+ APP_ERROR_CHECK(err_code);
+ break; // BLE_ANS_C_EVT_DISCONN_COMPLETE
+
+ default:
+ // No implementation needed.
+ break;
+ }
+}
+
+void alert_notification_error_handler(uint32_t nrf_error)
+{
+ APP_ERROR_HANDLER(nrf_error);
+}
+
void ble_manager_init_services() {
ret_code_t err_code;
ble_hrs_init_t hrs_init;
ble_bas_init_t bas_init;
ble_dis_init_t dis_init;
ble_cts_c_init_t cts_init;
+ ble_ans_c_init_t ans_init_obj;
nrf_ble_qwr_init_t qwr_init = {0};
uint8_t body_sensor_location;
@@ -441,6 +634,21 @@ void ble_manager_init_services() {
cts_init.error_handler = ble_manager_cts_error_handler;
err_code = ble_cts_c_init(&ble_manager_cts_client, &cts_init);
APP_ERROR_CHECK(err_code);
+
+ // Alert Notification service
+ memset(&ans_init_obj, 0, sizeof(ans_init_obj));
+ memset(m_alert_message_buffer, 0, MESSAGE_BUFFER_SIZE);
+
+ ans_init_obj.evt_handler = on_ans_c_evt;
+ ans_init_obj.message_buffer_size = MESSAGE_BUFFER_SIZE;
+ ans_init_obj.p_message_buffer = m_alert_message_buffer;
+ ans_init_obj.error_handler = alert_notification_error_handler;
+
+ NRF_LOG_INFO("ble_ans_c_init");
+ err_code = ble_ans_c_init(&m_ans_c, &ans_init_obj);
+ NRF_SDH_BLE_OBSERVER(ans_observer, BLE_ANS_C_BLE_OBSERVER_PRIO,*ble_ans_c_on_ble_evt, &m_ans_c);
+
+ APP_ERROR_CHECK(err_code);
}
void ble_manager_queue_write_error_handler(uint32_t nrf_error) {
@@ -467,11 +675,11 @@ void ble_manager_cts_event_handler(ble_cts_c_t *p_cts, ble_cts_c_evt_t *p_evt) {
NRF_LOG_INFO("Current Time Service not found on server. ");
// CTS not found in this case we just disconnect. There is no reason to stay
// in the connection for this simple app since it all wants is to interact with CT
- if (p_evt->conn_handle != BLE_CONN_HANDLE_INVALID) {
- err_code = sd_ble_gap_disconnect(p_evt->conn_handle,
- BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
- APP_ERROR_CHECK(err_code);
- }
+// if (p_evt->conn_handle != BLE_CONN_HANDLE_INVALID) {
+// err_code = sd_ble_gap_disconnect(p_evt->conn_handle,
+// BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+// APP_ERROR_CHECK(err_code);
+// }
break;
case BLE_CTS_C_EVT_DISCONN_COMPLETE:
diff --git a/src/BLE/BleManager.h b/src/BLE/BleManager.h
index 4424d665..e3b9faf3 100644
--- a/src/BLE/BleManager.h
+++ b/src/BLE/BleManager.h
@@ -31,6 +31,8 @@ extern "C" {
#define NEXT_CONN_PARAMS_UPDATE_DELAY 30000 /* Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /* Number of attempts before giving up the connection parameter negotiation. */
+#define MESSAGE_BUFFER_SIZE 18 /**< Size of buffer holding optional messages in notifications. */
+#define BLE_ANS_NB_OF_CATEGORY_ID 10 /**< Number of categories. */
void ble_manager_init();
void ble_manager_start_advertising(void *p_erase_bonds);
@@ -41,6 +43,8 @@ void ble_manager_set_new_time_callback(void (*OnNewTime)(current_time_char_t* cu
void ble_manager_set_ble_disconnection_callback(void (*OnBleDisconnection)());
void ble_manager_set_ble_connection_callback(void (*OnBleConnection)());
+void ble_manager_set_new_notification_callback(void (*OnNewNotification)(const char* message, uint8_t size));
+
#ifdef __cplusplus
}