forked from h2zero/esp-nimble-cpp
[Bugfix] notify/indicate incorrectly returning success with custom value
When sending an array of data with a length value the wrong overload/template was being used and the length value was being interpreted as the connection handle. This updates the template to disable it when an array is passed and will now also report the error.
This commit is contained in:
@@ -268,17 +268,32 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (value != nullptr && length > 0) { // custom notification value
|
if (value != nullptr && length > 0) { // custom notification value
|
||||||
// Notify all connected peers unless a specific handle is provided
|
os_mbuf* om = nullptr;
|
||||||
for (const auto& ch : NimBLEDevice::getServer()->getPeerDevices()) {
|
|
||||||
if (connHandle != BLE_HS_CONN_HANDLE_NONE && ch != connHandle) {
|
if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
|
||||||
continue; // only send to the specific handle, minor inefficiency but saves code.
|
om = ble_hs_mbuf_from_flat(value, length);
|
||||||
|
if (!om) {
|
||||||
|
rc = BLE_HS_ENOMEM;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Null buffer will read the value from the characteristic
|
||||||
|
if (isNotification) {
|
||||||
|
rc = ble_gattc_notify_custom(connHandle, m_handle, om);
|
||||||
|
} else {
|
||||||
|
rc = ble_gattc_indicate_custom(connHandle, m_handle, om);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all connected peers unless a specific handle is provided
|
||||||
|
for (const auto& ch : NimBLEDevice::getServer()->getPeerDevices()) {
|
||||||
// Must re-create the data buffer on each iteration because it is freed by the calls bellow.
|
// Must re-create the data buffer on each iteration because it is freed by the calls bellow.
|
||||||
os_mbuf* om = ble_hs_mbuf_from_flat(value, length);
|
om = ble_hs_mbuf_from_flat(value, length);
|
||||||
if (!om) {
|
if (!om) {
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to allocate mbuf");
|
rc = BLE_HS_ENOMEM;
|
||||||
return false;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNotification) {
|
if (isNotification) {
|
||||||
@@ -286,24 +301,25 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i
|
|||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_indicate_custom(ch, m_handle, om);
|
rc = ble_gattc_indicate_custom(ch, m_handle, om);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc != 0) {
|
|
||||||
NIMBLE_LOGE(LOG_TAG, "<< sendValue: failed to send value, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) { // only sending to specific peer
|
} else if (connHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||||
// Null buffer will read the value from the characteristic
|
// Null buffer will read the value from the characteristic
|
||||||
if (isNotification) {
|
if (isNotification) {
|
||||||
rc = ble_gattc_notify_custom(connHandle, m_handle, NULL);
|
rc = ble_gattc_notify_custom(connHandle, m_handle, nullptr);
|
||||||
} else {
|
} else {
|
||||||
rc = ble_gattc_indicate_custom(connHandle, m_handle, NULL);
|
rc = ble_gattc_indicate_custom(connHandle, m_handle, nullptr);
|
||||||
}
|
}
|
||||||
} else { // Notify or indicate to all connected peers the characteristic value
|
} else { // Notify or indicate to all connected peers the characteristic value
|
||||||
ble_gatts_chr_updated(m_handle);
|
ble_gatts_chr_updated(m_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc == 0;
|
done:
|
||||||
|
if (rc != 0) {
|
||||||
|
NIMBLE_LOGE(LOG_TAG, "failed to send value, rc=%d %s", rc, NimBLEUtils::returnCodeToString(rc));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
} // sendValue
|
} // sendValue
|
||||||
|
|
||||||
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
|
void NimBLECharacteristic::readEvent(NimBLEConnInfo& connInfo) {
|
||||||
|
@@ -87,7 +87,9 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
|||||||
# ifdef _DOXYGEN_
|
# ifdef _DOXYGEN_
|
||||||
bool
|
bool
|
||||||
# else
|
# else
|
||||||
typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
|
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
|
||||||
|
!Has_data_size<T>::value,
|
||||||
|
bool>::type
|
||||||
# endif
|
# endif
|
||||||
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
notify(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
return notify(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
|
return notify(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
|
||||||
@@ -133,7 +135,9 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
|||||||
# ifdef _DOXYGEN_
|
# ifdef _DOXYGEN_
|
||||||
bool
|
bool
|
||||||
# else
|
# else
|
||||||
typename std::enable_if<!std::is_pointer<T>::value && !Has_c_str_length<T>::value && !Has_data_size<T>::value, bool>::type
|
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
|
||||||
|
!Has_data_size<T>::value,
|
||||||
|
bool>::type
|
||||||
# endif
|
# endif
|
||||||
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
indicate(const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
return indicate(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
|
return indicate(reinterpret_cast<const uint8_t*>(&v), sizeof(T), connHandle);
|
||||||
@@ -182,8 +186,8 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
|||||||
* @note This function is only available if the type T is not a pointer.
|
* @note This function is only available if the type T is not a pointer.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!std::is_pointer<T>::value, bool>::type notify(const T& value,
|
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type notify(
|
||||||
uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
if constexpr (Has_data_size<T>::value) {
|
if constexpr (Has_data_size<T>::value) {
|
||||||
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
return notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
||||||
} else if constexpr (Has_c_str_length<T>::value) {
|
} else if constexpr (Has_c_str_length<T>::value) {
|
||||||
@@ -204,7 +208,7 @@ class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
|||||||
* @note This function is only available if the type T is not a pointer.
|
* @note This function is only available if the type T is not a pointer.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename std::enable_if<!std::is_pointer<T>::value, bool>::type indicate(
|
typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value, bool>::type indicate(
|
||||||
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE) const {
|
||||||
if constexpr (Has_data_size<T>::value) {
|
if constexpr (Has_data_size<T>::value) {
|
||||||
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
return indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), connHandle);
|
||||||
|
Reference in New Issue
Block a user