Add support for BLE notification (ANS client).
Work In Progress!!!
This commit is contained in:
parent
7e9a7e4d5f
commit
68240704c7
|
@ -260,7 +260,8 @@ macro(nRF5x_setup)
|
||||||
list(APPEND SDK_SOURCE_FILES
|
list(APPEND SDK_SOURCE_FILES
|
||||||
"${NRF5_SDK_PATH}/components/ble/ble_db_discovery/ble_db_discovery.c"
|
"${NRF5_SDK_PATH}/components/ble/ble_db_discovery/ble_db_discovery.c"
|
||||||
"${NRF5_SDK_PATH}/components/ble/ble_services/ble_cts_c/ble_cts_c.c"
|
"${NRF5_SDK_PATH}/components/ble/ble_services/ble_cts_c/ble_cts_c.c"
|
||||||
"${NRF5_SDK_PATH}/external/thedotfactory_fonts/orkney24pts.c"
|
"${NRF5_SDK_PATH}/components/ble/ble_services/ble_ans_c/ble_ans_c.c"
|
||||||
|
# "${NRF5_SDK_PATH}/external/thedotfactory_fonts/orkney24pts.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
#BLE S132
|
#BLE S132
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <ble/ble_services/ble_hrs/ble_hrs.h>
|
#include <ble/ble_services/ble_hrs/ble_hrs.h>
|
||||||
#include <ble/ble_services/ble_bas/ble_bas.h>
|
#include <ble/ble_services/ble_bas/ble_bas.h>
|
||||||
#include <ble/ble_services/ble_dis/ble_dis.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 <ble/common/ble_conn_params.h>
|
||||||
#include <libraries/fds/fds.h>
|
#include <libraries/fds/fds.h>
|
||||||
#include "nrf_sdh_soc.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_event_handler(ble_conn_params_evt_t *p_evt);
|
||||||
void ble_manager_conn_params_error_handler(uint32_t nrf_error);
|
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.
|
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.
|
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.
|
BLE_CTS_C_DEF(ble_manager_cts_client); // Current Time service instance.
|
||||||
NRF_BLE_GATT_DEF(ble_manager_gatt); // GATT module instance.
|
NRF_BLE_GATT_DEF(ble_manager_gatt); // GATT module instance.
|
||||||
BLE_ADVERTISING_DEF(ble_manager_advertising); // Advertising module instance.
|
BLE_ADVERTISING_DEF(ble_manager_advertising); // Advertising module instance.
|
||||||
BLE_DB_DISCOVERY_DEF(ble_manager_db_discovery);
|
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.*/
|
static ble_uuid_t ble_manager_advertising_uuids[] = /* Universally unique service identifiers.*/
|
||||||
{
|
{
|
||||||
|
@ -88,6 +106,21 @@ static char const *month_of_year[] =
|
||||||
"December"
|
"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() {
|
void ble_manager_init() {
|
||||||
ble_manager_init_stack();
|
ble_manager_init_stack();
|
||||||
ble_manager_init_gap_params();
|
ble_manager_init_gap_params();
|
||||||
|
@ -133,6 +166,11 @@ void ble_manager_set_ble_disconnection_callback(void (*OnBleDisconnection)()) {
|
||||||
OnBleDisconnectionCallback = 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) {
|
void ble_manager_event_handler(ble_evt_t const *p_ble_evt, void *p_context) {
|
||||||
uint32_t err_code;
|
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) {
|
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);
|
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() {
|
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() {
|
void ble_manager_init_services() {
|
||||||
ret_code_t err_code;
|
ret_code_t err_code;
|
||||||
ble_hrs_init_t hrs_init;
|
ble_hrs_init_t hrs_init;
|
||||||
ble_bas_init_t bas_init;
|
ble_bas_init_t bas_init;
|
||||||
ble_dis_init_t dis_init;
|
ble_dis_init_t dis_init;
|
||||||
ble_cts_c_init_t cts_init;
|
ble_cts_c_init_t cts_init;
|
||||||
|
ble_ans_c_init_t ans_init_obj;
|
||||||
nrf_ble_qwr_init_t qwr_init = {0};
|
nrf_ble_qwr_init_t qwr_init = {0};
|
||||||
uint8_t body_sensor_location;
|
uint8_t body_sensor_location;
|
||||||
|
|
||||||
|
@ -441,6 +634,21 @@ void ble_manager_init_services() {
|
||||||
cts_init.error_handler = ble_manager_cts_error_handler;
|
cts_init.error_handler = ble_manager_cts_error_handler;
|
||||||
err_code = ble_cts_c_init(&ble_manager_cts_client, &cts_init);
|
err_code = ble_cts_c_init(&ble_manager_cts_client, &cts_init);
|
||||||
APP_ERROR_CHECK(err_code);
|
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) {
|
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. ");
|
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
|
// 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
|
// 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) {
|
// if (p_evt->conn_handle != BLE_CONN_HANDLE_INVALID) {
|
||||||
err_code = sd_ble_gap_disconnect(p_evt->conn_handle,
|
// err_code = sd_ble_gap_disconnect(p_evt->conn_handle,
|
||||||
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
// BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||||
APP_ERROR_CHECK(err_code);
|
// APP_ERROR_CHECK(err_code);
|
||||||
}
|
// }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BLE_CTS_C_EVT_DISCONN_COMPLETE:
|
case BLE_CTS_C_EVT_DISCONN_COMPLETE:
|
||||||
|
|
|
@ -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 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 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_init();
|
||||||
void ble_manager_start_advertising(void *p_erase_bonds);
|
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_disconnection_callback(void (*OnBleDisconnection)());
|
||||||
void ble_manager_set_ble_connection_callback(void (*OnBleConnection)());
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
#include "BleController.h"
|
#include "BleController.h"
|
||||||
|
|
||||||
using namespace Pinetime::Controllers;
|
using namespace Pinetime::Controllers;
|
||||||
|
|
||||||
|
Ble::Ble() {
|
||||||
|
notificationQueue = xQueueCreate(10, sizeof(NotificationMessage));
|
||||||
|
}
|
||||||
|
|
||||||
void Ble::Connect() {
|
void Ble::Connect() {
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
}
|
}
|
||||||
|
@ -9,3 +15,25 @@ void Ble::Connect() {
|
||||||
void Ble::Disconnect() {
|
void Ble::Disconnect() {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ble::PushNotification(const char *message, uint8_t size) {
|
||||||
|
char* messageCopy = static_cast<char *>(malloc(sizeof(char) * size));
|
||||||
|
std::memcpy(messageCopy, message, size);
|
||||||
|
NotificationMessage msg;
|
||||||
|
msg.size = size;
|
||||||
|
msg.message = messageCopy;
|
||||||
|
|
||||||
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
xQueueSendFromISR(notificationQueue, &msg, &xHigherPriorityTaskWoken);
|
||||||
|
if (xHigherPriorityTaskWoken) {
|
||||||
|
/* Actual macro used here is port specific. */
|
||||||
|
// TODO : should I do something here?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ble::PopNotification(Ble::NotificationMessage& msg) {
|
||||||
|
return xQueueReceive(notificationQueue, &msg, 0) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <FreeRTOS.h>>
|
||||||
|
#include <queue.h>
|
||||||
|
|
||||||
namespace Pinetime {
|
namespace Pinetime {
|
||||||
namespace Controllers {
|
namespace Controllers {
|
||||||
class Ble {
|
class Ble {
|
||||||
public:
|
public:
|
||||||
|
struct NotificationMessage {
|
||||||
|
uint8_t size = 0;
|
||||||
|
const char* message = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Ble();
|
||||||
bool IsConnected() const {return isConnected;}
|
bool IsConnected() const {return isConnected;}
|
||||||
void Connect();
|
void Connect();
|
||||||
void Disconnect();
|
void Disconnect();
|
||||||
|
|
||||||
|
void PushNotification(const char* message, uint8_t size);
|
||||||
|
bool PopNotification(NotificationMessage& msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isConnected = false;
|
bool isConnected = false;
|
||||||
|
QueueHandle_t notificationQueue;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -38,6 +38,7 @@ DisplayApp::DisplayApp(Pinetime::Drivers::St7789& lcd,
|
||||||
systemTask{systemTask} {
|
systemTask{systemTask} {
|
||||||
msgQueue = xQueueCreate(queueSize, itemSize);
|
msgQueue = xQueueCreate(queueSize, itemSize);
|
||||||
onClockApp = true;
|
onClockApp = true;
|
||||||
|
modal.reset(new Screens::Modal(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayApp::Start() {
|
void DisplayApp::Start() {
|
||||||
|
@ -103,6 +104,7 @@ void DisplayApp::Refresh() {
|
||||||
state = States::Running;
|
state = States::Running;
|
||||||
break;
|
break;
|
||||||
case Messages::UpdateDateTime:
|
case Messages::UpdateDateTime:
|
||||||
|
// modal->Show();
|
||||||
break;
|
break;
|
||||||
case Messages::UpdateBleConnection:
|
case Messages::UpdateBleConnection:
|
||||||
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected);
|
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected);
|
||||||
|
@ -110,6 +112,15 @@ void DisplayApp::Refresh() {
|
||||||
case Messages::UpdateBatteryLevel:
|
case Messages::UpdateBatteryLevel:
|
||||||
// clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining());
|
// clockScreen.SetBatteryPercentRemaining(batteryController.PercentRemaining());
|
||||||
break;
|
break;
|
||||||
|
case Messages::NewNotification: {
|
||||||
|
Pinetime::Controllers::Ble::NotificationMessage notificationMessage;
|
||||||
|
if (bleController.PopNotification(notificationMessage)) {
|
||||||
|
std::string m {notificationMessage.message, notificationMessage.size};
|
||||||
|
modal->Show(m);
|
||||||
|
// TODO delete message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Messages::TouchEvent: {
|
case Messages::TouchEvent: {
|
||||||
if (state != States::Running) break;
|
if (state != States::Running) break;
|
||||||
auto gesture = OnTouchEvent();
|
auto gesture = OnTouchEvent();
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <date/date.h>
|
#include <date/date.h>
|
||||||
#include <DisplayApp/Screens/Clock.h>
|
#include <DisplayApp/Screens/Clock.h>
|
||||||
#include <drivers/Watchdog.h>
|
#include <drivers/Watchdog.h>
|
||||||
|
#include <DisplayApp/Screens/Modal.h>
|
||||||
#include "TouchEvents.h"
|
#include "TouchEvents.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,7 +28,9 @@ namespace Pinetime {
|
||||||
class DisplayApp {
|
class DisplayApp {
|
||||||
public:
|
public:
|
||||||
enum class States {Idle, Running};
|
enum class States {Idle, Running};
|
||||||
enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, SwitchScreen,ButtonPushed};
|
enum class Messages : uint8_t {GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, SwitchScreen,ButtonPushed,
|
||||||
|
NewNotification
|
||||||
|
};
|
||||||
enum class FullRefreshDirections { None, Up, Down };
|
enum class FullRefreshDirections { None, Up, Down };
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,6 +81,8 @@ namespace Pinetime {
|
||||||
Apps nextApp = Apps::None;
|
Apps nextApp = Apps::None;
|
||||||
bool onClockApp = false; // TODO find a better way to know that we should handle gestures and button differently for the Clock app.
|
bool onClockApp = false; // TODO find a better way to know that we should handle gestures and button differently for the Clock app.
|
||||||
Controllers::BrightnessController brightnessController;
|
Controllers::BrightnessController brightnessController;
|
||||||
|
std::unique_ptr<Screens::Modal> modal;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ bool Modal::OnButtonPushed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Modal::Show() {
|
void Modal::Show() {
|
||||||
|
if(isVisible) return;
|
||||||
|
isVisible = true;
|
||||||
lv_style_copy(&modal_style, &lv_style_plain_color);
|
lv_style_copy(&modal_style, &lv_style_plain_color);
|
||||||
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
||||||
modal_style.body.opa = LV_OPA_50;
|
modal_style.body.opa = LV_OPA_50;
|
||||||
|
@ -63,6 +65,7 @@ void Modal::Hide() {
|
||||||
/* Delete the parent modal background */
|
/* Delete the parent modal background */
|
||||||
lv_obj_del_async(lv_obj_get_parent(mbox));
|
lv_obj_del_async(lv_obj_get_parent(mbox));
|
||||||
mbox = NULL; /* happens before object is actually deleted! */
|
mbox = NULL; /* happens before object is actually deleted! */
|
||||||
|
isVisible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Modal::mbox_event_cb(lv_obj_t *obj, lv_event_t evt) {
|
void Modal::mbox_event_cb(lv_obj_t *obj, lv_event_t evt) {
|
||||||
|
@ -79,3 +82,37 @@ void Modal::OnEvent(lv_obj_t *event_obj, lv_event_t evt) {
|
||||||
// Hide();
|
// Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Modal::Show(const std::string& message) {
|
||||||
|
if(isVisible) return;
|
||||||
|
this->message = message;
|
||||||
|
isVisible = true;
|
||||||
|
lv_style_copy(&modal_style, &lv_style_plain_color);
|
||||||
|
modal_style.body.main_color = modal_style.body.grad_color = LV_COLOR_BLACK;
|
||||||
|
modal_style.body.opa = LV_OPA_50;
|
||||||
|
|
||||||
|
obj = lv_obj_create(lv_scr_act(), NULL);
|
||||||
|
lv_obj_set_style(obj, &modal_style);
|
||||||
|
lv_obj_set_pos(obj, 0, 0);
|
||||||
|
lv_obj_set_size(obj, LV_HOR_RES, LV_VER_RES);
|
||||||
|
lv_obj_set_opa_scale_enable(obj, true); /* Enable opacity scaling for the animation */
|
||||||
|
|
||||||
|
static const char * btns2[] = {"Ok", ""};
|
||||||
|
|
||||||
|
/* Create the message box as a child of the modal background */
|
||||||
|
mbox = lv_mbox_create(obj, NULL);
|
||||||
|
lv_mbox_add_btns(mbox, btns2);
|
||||||
|
lv_mbox_set_text(mbox, message.data());
|
||||||
|
lv_obj_align(mbox, NULL, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_event_cb(mbox, Modal::mbox_event_cb);
|
||||||
|
|
||||||
|
mbox->user_data = this;
|
||||||
|
|
||||||
|
/* Fade the message box in with an animation */
|
||||||
|
lv_anim_t a;
|
||||||
|
lv_anim_init(&a);
|
||||||
|
lv_anim_set_time(&a, 500, 0);
|
||||||
|
lv_anim_set_values(&a, LV_OPA_TRANSP, LV_OPA_COVER);
|
||||||
|
lv_anim_set_exec_cb(&a, obj, (lv_anim_exec_xcb_t)lv_obj_set_opa_scale);
|
||||||
|
lv_anim_create(&a);
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ namespace Pinetime {
|
||||||
~Modal() override;
|
~Modal() override;
|
||||||
|
|
||||||
void Show();
|
void Show();
|
||||||
|
void Show(const std::string& message);
|
||||||
void Hide();
|
void Hide();
|
||||||
|
|
||||||
bool Refresh() override;
|
bool Refresh() override;
|
||||||
|
@ -37,6 +38,8 @@ namespace Pinetime {
|
||||||
lv_obj_t *mbox;
|
lv_obj_t *mbox;
|
||||||
lv_obj_t *info;
|
lv_obj_t *info;
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
bool isVisible = false;
|
||||||
|
std::string message;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ void SystemTask::Work() {
|
||||||
watchdog.Start();
|
watchdog.Start();
|
||||||
NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason()));
|
NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason()));
|
||||||
APP_GPIOTE_INIT(2);
|
APP_GPIOTE_INIT(2);
|
||||||
bool erase_bonds=false;
|
bool erase_bonds=true;
|
||||||
ble_manager_init_peer_manager();
|
ble_manager_init_peer_manager();
|
||||||
nrf_sdh_freertos_init(ble_manager_start_advertising, &erase_bonds);
|
nrf_sdh_freertos_init(ble_manager_start_advertising, &erase_bonds);
|
||||||
|
|
||||||
|
@ -84,6 +84,12 @@ void SystemTask::Work() {
|
||||||
NRF_LOG_INFO("[SystemTask] Going to sleep");
|
NRF_LOG_INFO("[SystemTask] Going to sleep");
|
||||||
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep);
|
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::GoToSleep);
|
||||||
isSleeping = true; break;
|
isSleeping = true; break;
|
||||||
|
case Messages::OnNewTime:
|
||||||
|
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::UpdateDateTime);
|
||||||
|
break;
|
||||||
|
case Messages::OnNewNotification:
|
||||||
|
displayApp->PushMessage(Pinetime::Applications::DisplayApp::Messages::NewNotification);
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,8 @@ namespace Pinetime {
|
||||||
namespace System {
|
namespace System {
|
||||||
class SystemTask {
|
class SystemTask {
|
||||||
public:
|
public:
|
||||||
enum class Messages {GoToSleep, GoToRunning};
|
enum class Messages {GoToSleep, GoToRunning, OnNewTime, OnNewNotification
|
||||||
|
};
|
||||||
|
|
||||||
SystemTask(Pinetime::Drivers::SpiMaster& spi,
|
SystemTask(Pinetime::Drivers::SpiMaster& spi,
|
||||||
Pinetime::Drivers::St7789& lcd,
|
Pinetime::Drivers::St7789& lcd,
|
||||||
|
|
|
@ -85,6 +85,11 @@ void OnBleDisconnection() {
|
||||||
bleController.Disconnect();
|
bleController.Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnNewNotification(const char* message, uint8_t size) {
|
||||||
|
bleController.PushNotification(message, size);
|
||||||
|
systemTask->PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
|
||||||
|
}
|
||||||
|
|
||||||
void OnNewTime(current_time_char_t* currentTime) {
|
void OnNewTime(current_time_char_t* currentTime) {
|
||||||
auto dayOfWeek = currentTime->exact_time_256.day_date_time.day_of_week;
|
auto dayOfWeek = currentTime->exact_time_256.day_date_time.day_of_week;
|
||||||
auto year = currentTime->exact_time_256.day_date_time.date_time.year;
|
auto year = currentTime->exact_time_256.day_date_time.date_time.year;
|
||||||
|
@ -96,6 +101,8 @@ void OnNewTime(current_time_char_t* currentTime) {
|
||||||
|
|
||||||
dateTimeController.SetTime(year, month, day,
|
dateTimeController.SetTime(year, month, day,
|
||||||
dayOfWeek, hour, minute, second, nrf_rtc_counter_get(portNRF_RTC_REG));
|
dayOfWeek, hour, minute, second, nrf_rtc_counter_get(portNRF_RTC_REG));
|
||||||
|
|
||||||
|
systemTask->PushMessage(Pinetime::System::SystemTask::Messages::OnNewTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
|
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
|
||||||
|
@ -128,6 +135,7 @@ int main(void) {
|
||||||
ble_manager_set_new_time_callback(OnNewTime);
|
ble_manager_set_new_time_callback(OnNewTime);
|
||||||
ble_manager_set_ble_connection_callback(OnBleConnection);
|
ble_manager_set_ble_connection_callback(OnBleConnection);
|
||||||
ble_manager_set_ble_disconnection_callback(OnBleDisconnection);
|
ble_manager_set_ble_disconnection_callback(OnBleDisconnection);
|
||||||
|
ble_manager_set_new_notification_callback(OnNewNotification);
|
||||||
|
|
||||||
vTaskStartScheduler();
|
vTaskStartScheduler();
|
||||||
|
|
||||||
|
|
|
@ -1322,7 +1322,15 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef BLE_ANS_C_ENABLED
|
#ifndef BLE_ANS_C_ENABLED
|
||||||
#define BLE_ANS_C_ENABLED 0
|
#define BLE_ANS_C_ENABLED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLE_ANS_C_LOG_ENABLED
|
||||||
|
#define BLE_ANS_C_LOG_ENABLED 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BLE_ANS_C_LOG_LEVEL
|
||||||
|
#define BLE_ANS_C_LOG_LEVEL 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// <q> BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client
|
// <q> BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client
|
||||||
|
@ -8532,7 +8540,7 @@
|
||||||
// <4=> Debug
|
// <4=> Debug
|
||||||
|
|
||||||
#ifndef NRF_LOG_DEFAULT_LEVEL
|
#ifndef NRF_LOG_DEFAULT_LEVEL
|
||||||
#define NRF_LOG_DEFAULT_LEVEL 3
|
#define NRF_LOG_DEFAULT_LEVEL 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// <q> NRF_LOG_DEFERRED - Enable deffered logger.
|
// <q> NRF_LOG_DEFERRED - Enable deffered logger.
|
||||||
|
|
Loading…
Reference in a new issue