diff options
author | JF002 <JF002@users.noreply.github.com> | 2020-10-27 21:57:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-27 21:57:48 +0100 |
commit | cb9e8815d8bc6ce71fd8e97f3e3dae402658ce1f (patch) | |
tree | 1750edfed02f547102e468eca485caab3b08e98d /src/components | |
parent | c5bf09d21b2ed8e2435ec625e351594f58713924 (diff) | |
parent | 7de43a16608e599369867cb3cfa7d5776a5b6380 (diff) |
Merge pull request #108 from JF002/notification-ui
Improved notification UI
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/ble/AlertNotificationClient.cpp | 28 | ||||
-rw-r--r-- | src/components/ble/AlertNotificationService.cpp | 35 | ||||
-rw-r--r-- | src/components/ble/AlertNotificationService.h | 4 | ||||
-rw-r--r-- | src/components/ble/ImmediateAlertService.cpp | 8 | ||||
-rw-r--r-- | src/components/ble/NotificationManager.cpp | 85 | ||||
-rw-r--r-- | src/components/ble/NotificationManager.h | 20 |
6 files changed, 121 insertions, 59 deletions
diff --git a/src/components/ble/AlertNotificationClient.cpp b/src/components/ble/AlertNotificationClient.cpp index ddc72967..40970e0b 100644 --- a/src/components/ble/AlertNotificationClient.cpp +++ b/src/components/ble/AlertNotificationClient.cpp @@ -105,25 +105,21 @@ int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connect void AlertNotificationClient::OnNotification(ble_gap_event *event) { if(event->notify_rx.attr_handle == newAlertHandle) { - // TODO implement this with more memory safety (and constexpr) - static const size_t maxBufferSize{21}; - static const size_t maxMessageSize{18}; - size_t bufferSize = min(OS_MBUF_PKTLEN(event->notify_rx.om), maxBufferSize); + constexpr size_t stringTerminatorSize = 1; // end of string '\0' + constexpr size_t headerSize = 3; + const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; + const auto maxBufferSize{maxMessageSize + headerSize}; - uint8_t data[bufferSize]; - os_mbuf_copydata(event->notify_rx.om, 0, bufferSize, data); + const auto dbgPacketLen = OS_MBUF_PKTLEN(event->notify_rx.om); + size_t bufferSize = min(dbgPacketLen + stringTerminatorSize, maxBufferSize); + auto messageSize = min(maxMessageSize, (bufferSize-headerSize)); - char *s = (char *) &data[3]; - auto messageSize = min(maxMessageSize, (bufferSize-3)); + NotificationManager::Notification notif; + os_mbuf_copydata(event->notify_rx.om, headerSize, messageSize-1, notif.message.data()); + notif.message[messageSize-1] = '\0'; + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); - for (uint i = 0; i < messageSize-1; i++) { - if (s[i] == 0x00) { - s[i] = 0x0A; - } - } - s[messageSize-1] = '\0'; - - notificationManager.Push(Pinetime::Controllers::NotificationManager::Categories::SimpleAlert, s, messageSize); systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); } } diff --git a/src/components/ble/AlertNotificationService.cpp b/src/components/ble/AlertNotificationService.cpp index 9a9b535d..32711b92 100644 --- a/src/components/ble/AlertNotificationService.cpp +++ b/src/components/ble/AlertNotificationService.cpp @@ -38,7 +38,7 @@ AlertNotificationService::AlertNotificationService ( System::SystemTask& systemT 0 } }, - serviceDefinition{ + serviceDefinition{ { /* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, @@ -48,33 +48,28 @@ AlertNotificationService::AlertNotificationService ( System::SystemTask& systemT { 0 }, - }, m_systemTask{systemTask}, m_notificationManager{notificationManager} { + }, systemTask{systemTask}, notificationManager{notificationManager} { } int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt) { - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - // TODO implement this with more memory safety (and constexpr) - static const size_t maxBufferSize{21}; - static const size_t maxMessageSize{18}; - size_t bufferSize = min(OS_MBUF_PKTLEN(ctxt->om), maxBufferSize); - - uint8_t data[bufferSize]; - os_mbuf_copydata(ctxt->om, 0, bufferSize, data); + constexpr size_t stringTerminatorSize = 1; // end of string '\0' + constexpr size_t headerSize = 3; + const auto maxMessageSize {NotificationManager::MaximumMessageSize()}; + const auto maxBufferSize{maxMessageSize + headerSize}; - char *s = (char *) &data[3]; - auto messageSize = min(maxMessageSize, (bufferSize-3)); + const auto dbgPacketLen = OS_MBUF_PKTLEN(ctxt->om); + size_t bufferSize = min(dbgPacketLen + stringTerminatorSize, maxBufferSize); + auto messageSize = min(maxMessageSize, (bufferSize-headerSize)); - for (uint i = 0; i < messageSize-1; i++) { - if (s[i] == 0x00) { - s[i] = 0x0A; - } - } - s[messageSize-1] = '\0'; + NotificationManager::Notification notif; + os_mbuf_copydata(ctxt->om, headerSize, messageSize-1, notif.message.data()); + notif.message[messageSize-1] = '\0'; + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); - m_notificationManager.Push(Pinetime::Controllers::NotificationManager::Categories::SimpleAlert, s, messageSize); - m_systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); + systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); } return 0; } diff --git a/src/components/ble/AlertNotificationService.h b/src/components/ble/AlertNotificationService.h index 53cb44cc..1b8c4989 100644 --- a/src/components/ble/AlertNotificationService.h +++ b/src/components/ble/AlertNotificationService.h @@ -32,8 +32,8 @@ namespace Pinetime { struct ble_gatt_chr_def characteristicDefinition[2]; struct ble_gatt_svc_def serviceDefinition[2]; - Pinetime::System::SystemTask &m_systemTask; - NotificationManager &m_notificationManager; + Pinetime::System::SystemTask &systemTask; + NotificationManager ¬ificationManager; }; } } diff --git a/src/components/ble/ImmediateAlertService.cpp b/src/components/ble/ImmediateAlertService.cpp index 3b7f47bf..e2cee308 100644 --- a/src/components/ble/ImmediateAlertService.cpp +++ b/src/components/ble/ImmediateAlertService.cpp @@ -1,4 +1,5 @@ #include <systemtask/SystemTask.h> +#include <cstring> #include "ImmediateAlertService.h" #include "AlertNotificationService.h" @@ -67,7 +68,12 @@ int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16 if(context->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { auto alertLevel = static_cast<Levels>(context->om->om_data[0]); auto* alertString = ToString(alertLevel); - notificationManager.Push(Pinetime::Controllers::NotificationManager::Categories::SimpleAlert, alertString, strlen(alertString)); + + NotificationManager::Notification notif; + std::memcpy(notif.message.data(), alertString, strlen(alertString)); + notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert; + notificationManager.Push(std::move(notif)); + systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification); } } diff --git a/src/components/ble/NotificationManager.cpp b/src/components/ble/NotificationManager.cpp index 0aea0697..67711723 100644 --- a/src/components/ble/NotificationManager.cpp +++ b/src/components/ble/NotificationManager.cpp @@ -1,30 +1,81 @@ #include <cstring> +#include <algorithm> #include "NotificationManager.h" using namespace Pinetime::Controllers; -void NotificationManager::Push(Pinetime::Controllers::NotificationManager::Categories category, - const char *message, uint8_t currentMessageSize) { - // TODO handle edge cases on read/write index - auto checkedSize = std::min(currentMessageSize, uint8_t{18}); - auto& notif = notifications[writeIndex]; - std::memcpy(notif.message.data(), message, checkedSize); - notif.message[checkedSize] = '\0'; - notif.category = category; +constexpr uint8_t NotificationManager::MessageSize; + +void NotificationManager::Push(NotificationManager::Notification &¬if) { + notif.id = GetNextId(); + notif.valid = true; + notifications[writeIndex] = std::move(notif); writeIndex = (writeIndex + 1 < TotalNbNotifications) ? writeIndex + 1 : 0; - if(!empty && writeIndex == readIndex) - readIndex = writeIndex + 1; + if(!empty) + readIndex = (readIndex + 1 < TotalNbNotifications) ? readIndex + 1 : 0; + else empty = false; + + newNotification = true; } -NotificationManager::Notification Pinetime::Controllers::NotificationManager::Pop() { -// TODO handle edge cases on read/write index +NotificationManager::Notification NotificationManager::GetLastNotification() { NotificationManager::Notification notification = notifications[readIndex]; + notification.index = 1; + return notification; +} - if(readIndex != writeIndex) { - readIndex = (readIndex + 1 < TotalNbNotifications) ? readIndex + 1 : 0; - } +NotificationManager::Notification::Id NotificationManager::GetNextId() { + return nextId++; +} - // TODO Check move optimization on return - return notification; +NotificationManager::Notification NotificationManager::GetNext(NotificationManager::Notification::Id id) { + auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;}); + if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{}; + + auto& lastNotification = notifications[readIndex]; + + NotificationManager::Notification result; + + if(currentIterator == (notifications.end()-1)) + result = *(notifications.begin()); + else + result = *(currentIterator+1); + + if(result.id <= id) return {}; + + result.index = (lastNotification.id - result.id)+1; + return result; } + +NotificationManager::Notification NotificationManager::GetPrevious(NotificationManager::Notification::Id id) { + auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;}); + if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{}; + + auto& lastNotification = notifications[readIndex]; + + NotificationManager::Notification result; + + if(currentIterator == notifications.begin()) + result = *(notifications.end()-1); + else + result = *(currentIterator-1); + + if(result.id >= id) return {}; + + result.index = (lastNotification.id - result.id)+1; + return result; +} + +bool NotificationManager::AreNewNotificationsAvailable() { + return newNotification; +} + +bool NotificationManager::ClearNewNotificationFlag() { + return newNotification.exchange(false); +} + +size_t NotificationManager::NbNotifications() const { + return std::count_if(notifications.begin(), notifications.end(), [](const Notification& n){ return n.valid;}); +} + diff --git a/src/components/ble/NotificationManager.h b/src/components/ble/NotificationManager.h index daa1571b..49fe8306 100644 --- a/src/components/ble/NotificationManager.h +++ b/src/components/ble/NotificationManager.h @@ -1,29 +1,43 @@ #pragma once #include <array> +#include <atomic> namespace Pinetime { namespace Controllers { class NotificationManager { public: enum class Categories {Unknown, SimpleAlert, Email, News, IncomingCall, MissedCall, Sms, VoiceMail, Schedule, HighProriotyAlert, InstantMessage }; - static constexpr uint8_t MessageSize{18}; + static constexpr uint8_t MessageSize{100}; struct Notification { + using Id = uint8_t; + Id id; + bool valid = false; + uint8_t index; std::array<char, MessageSize+1> message; Categories category = Categories::Unknown; }; + Notification::Id nextId {0}; - void Push(Categories category, const char* message, uint8_t messageSize); - Notification Pop(); + void Push(Notification&& notif); + Notification GetLastNotification(); + Notification GetNext(Notification::Id id); + Notification GetPrevious(Notification::Id id); + bool ClearNewNotificationFlag(); + bool AreNewNotificationsAvailable(); + static constexpr uint8_t MaximumMessageSize() { return MessageSize; }; + size_t NbNotifications() const; private: + Notification::Id GetNextId(); static constexpr uint8_t TotalNbNotifications = 5; std::array<Notification, TotalNbNotifications> notifications; uint8_t readIndex = 0; uint8_t writeIndex = 0; bool empty = true; + std::atomic<bool> newNotification{false}; }; } }
\ No newline at end of file |