From 10f544f80adf1d6d90efea0987f8d364b7a38e55 Mon Sep 17 00:00:00 2001 From: h2zero Date: Fri, 29 May 2020 18:26:41 -0600 Subject: [PATCH] Update remote characteristic value from a notification * Add NimBLERemoteCharacteristic::getValue(time_t *timestamp = nullptr) to get the latest remote characteristic and (optionally) it's timestamp. * Added a timestamp to NimBLEAdvertisedDevice for the moment a device was scanned --- src/NimBLEAdvertisedDevice.cpp | 5 +++++ src/NimBLEAdvertisedDevice.h | 4 +++- src/NimBLEClient.cpp | 6 +++++- src/NimBLEDevice.cpp | 2 +- src/NimBLERemoteCharacteristic.cpp | 23 ++++++++++++++++++++--- src/NimBLERemoteCharacteristic.h | 2 ++ src/NimBLEScan.cpp | 1 + 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/NimBLEAdvertisedDevice.cpp b/src/NimBLEAdvertisedDevice.cpp index f81b172..3e33b77 100644 --- a/src/NimBLEAdvertisedDevice.cpp +++ b/src/NimBLEAdvertisedDevice.cpp @@ -546,6 +546,11 @@ uint8_t NimBLEAdvertisedDevice::getAddressType() { } +time_t NimBLEAdvertisedDevice::getTimestamp() { + return m_timestamp; +} + + void NimBLEAdvertisedDevice::setAddressType(uint8_t type) { m_addressType = type; } diff --git a/src/NimBLEAdvertisedDevice.h b/src/NimBLEAdvertisedDevice.h index 8f0b78c..f38a9b4 100644 --- a/src/NimBLEAdvertisedDevice.h +++ b/src/NimBLEAdvertisedDevice.h @@ -55,7 +55,8 @@ public: uint8_t* getPayload(); size_t getPayloadLength(); uint8_t getAddressType(); - void setAddressType(uint8_t type); + time_t getTimestamp(); + void setAddressType(uint8_t type); bool isAdvertisingService(const NimBLEUUID &uuid); @@ -111,6 +112,7 @@ private: uint8_t* m_payload; size_t m_payloadLength = 0; uint8_t m_addressType; + time_t m_timestamp; }; /** diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index a385126..1bcbeb6 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -720,6 +720,11 @@ uint16_t NimBLEClient::getMTU() { if(characteristic != cVector->cend()) { NIMBLE_LOGD(LOG_TAG, "Got Notification for characteristic %s", (*characteristic)->toString().c_str()); + if((*characteristic)->m_semaphoreReadCharEvt.take(0, "notifyValue")) { + (*characteristic)->m_value = std::string((char *)event->notify_rx.om->om_data, event->notify_rx.om->om_len); + (*characteristic)->m_timestamp = time(nullptr); + (*characteristic)->m_semaphoreReadCharEvt.give(); + } if ((*characteristic)->m_notifyCallback != nullptr) { NIMBLE_LOGD(LOG_TAG, "Invoking callback for notification on characteristic %s", (*characteristic)->toString().c_str()); @@ -727,7 +732,6 @@ uint16_t NimBLEClient::getMTU() { event->notify_rx.om->om_len, !event->notify_rx.indication); } - break; } } diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 1540f63..1695a51 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -40,7 +40,7 @@ static const char* LOG_TAG = "NimBLEDevice"; /** * Singletons for the NimBLEDevice. */ -bool initialized = false; +static bool initialized = false; #if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) NimBLEScan* NimBLEDevice::m_pScan = nullptr; #endif diff --git a/src/NimBLERemoteCharacteristic.cpp b/src/NimBLERemoteCharacteristic.cpp index 85760b4..e818b77 100644 --- a/src/NimBLERemoteCharacteristic.cpp +++ b/src/NimBLERemoteCharacteristic.cpp @@ -60,6 +60,7 @@ static const char* LOG_TAG = "NimBLERemoteCharacteristic"; m_notifyCallback = nullptr; m_rawData = nullptr; m_dataLen = 0; + m_timestamp = 0; } // NimBLERemoteCharacteristic @@ -389,8 +390,6 @@ std::string NimBLERemoteCharacteristic::readValue() { int rc = 0; int retryCount = 1; - // Clear the value before reading. - m_value = ""; NimBLEClient* pClient = getRemoteService()->getClient(); @@ -402,6 +401,8 @@ std::string NimBLERemoteCharacteristic::readValue() { do { m_semaphoreReadCharEvt.take("readValue"); + // Clear the value before reading. + m_value = ""; rc = ble_gattc_read_long(pClient->getConnId(), m_handle, 0, NimBLERemoteCharacteristic::onReadCB, @@ -440,6 +441,21 @@ std::string NimBLERemoteCharacteristic::readValue() { } // readValue +/** + * @brief Get the value of the remote characteristic. + * @return The value of the remote characteristic. + */ +std::string NimBLERemoteCharacteristic::getValue(time_t *timestamp) { + m_semaphoreReadCharEvt.take("getValue"); + std::string value = m_value; + if(timestamp != nullptr) { + *timestamp = m_timestamp; + } + m_semaphoreReadCharEvt.give(); + return value; +} + + /** * @brief Callback for characteristic read operation. * @return 0 or error code. @@ -462,6 +478,7 @@ int NimBLERemoteCharacteristic::onReadCB(uint16_t conn_handle, NIMBLE_LOGD(LOG_TAG, "Got %d bytes", attr->om->om_len); characteristic->m_value += std::string((char*) attr->om->om_data, attr->om->om_len); + characteristic->m_timestamp = time(nullptr); return 0; } } @@ -509,7 +526,7 @@ bool NimBLERemoteCharacteristic::registerForNotify(notify_callback notifyCallbac /** * @brief Delete the descriptors in the descriptor vector. * We maintain a vector called m_descriptorVector that contains pointers to BLERemoteDescriptors - * object references. Since we allocated these in this class, we are also responsible for deleteing + * object references. Since we allocated these in this class, we are also responsible for deleting * them. This method does just that. * @return N/A. */ diff --git a/src/NimBLERemoteCharacteristic.h b/src/NimBLERemoteCharacteristic.h index 0b7d490..c04e1f4 100644 --- a/src/NimBLERemoteCharacteristic.h +++ b/src/NimBLERemoteCharacteristic.h @@ -57,6 +57,7 @@ public: uint8_t readUInt8(); uint16_t readUInt16(); uint32_t readUInt32(); + std::string getValue(time_t *timestamp = nullptr); bool registerForNotify(notify_callback _callback, bool notifications = true, bool response = true); @@ -105,6 +106,7 @@ private: uint8_t* m_rawData; size_t m_dataLen; notify_callback m_notifyCallback; + time_t m_timestamp; // We maintain a vector of descriptors owned by this characteristic. std::vector m_descriptorVector; diff --git a/src/NimBLEScan.cpp b/src/NimBLEScan.cpp index deecda1..eedc39a 100644 --- a/src/NimBLEScan.cpp +++ b/src/NimBLEScan.cpp @@ -143,6 +143,7 @@ NimBLEScan::NimBLEScan() { advertisedDevice->parseAdvertisement(&fields); advertisedDevice->setScan(pScan); advertisedDevice->setAdvertisementResult(event->disc.data, event->disc.length_data); + advertisedDevice->m_timestamp = time(nullptr); if (pScan->m_pAdvertisedDeviceCallbacks) { // If not active scanning report the result to the listener.