2020-03-29 17:44:20 -06:00
|
|
|
/*
|
|
|
|
|
* NimBLECharacteristic.h
|
|
|
|
|
*
|
|
|
|
|
* Created: on March 3, 2020
|
|
|
|
|
* Author H2zero
|
2020-05-13 22:03:56 -06:00
|
|
|
*
|
2020-03-29 17:44:20 -06:00
|
|
|
* Originally:
|
|
|
|
|
* BLECharacteristic.h
|
|
|
|
|
*
|
|
|
|
|
* Created on: Jun 22, 2017
|
|
|
|
|
* Author: kolban
|
|
|
|
|
*/
|
|
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
#ifndef NIMBLE_CPP_CHARACTERISTIC_H_
|
|
|
|
|
#define NIMBLE_CPP_CHARACTERISTIC_H_
|
2020-05-13 22:03:56 -06:00
|
|
|
#include "nimconfig.h"
|
2021-09-06 21:14:43 -06:00
|
|
|
#if defined(CONFIG_BT_ENABLED) && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2020-03-29 17:44:20 -06:00
|
|
|
class NimBLECharacteristicCallbacks;
|
2024-07-26 14:47:36 -06:00
|
|
|
class NimBLECharacteristic;
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
# include "NimBLELocalValueAttribute.h"
|
|
|
|
|
# include "NimBLEServer.h"
|
|
|
|
|
# include "NimBLEService.h"
|
|
|
|
|
# include "NimBLEDescriptor.h"
|
|
|
|
|
# include "NimBLEAttValue.h"
|
|
|
|
|
# include "NimBLEConnInfo.h"
|
|
|
|
|
|
|
|
|
|
# include <string>
|
|
|
|
|
# include <vector>
|
2020-03-29 17:44:20 -06:00
|
|
|
|
|
|
|
|
/**
|
2024-07-26 14:47:36 -06:00
|
|
|
* @brief The model of a BLE Characteristic.
|
2020-03-29 17:44:20 -06:00
|
|
|
*
|
2024-07-26 14:47:36 -06:00
|
|
|
* A BLE Characteristic is an identified value container that manages a value. It is exposed by a BLE service and
|
|
|
|
|
* can be read and written to by a BLE client.
|
2020-03-29 17:44:20 -06:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
class NimBLECharacteristic : public NimBLELocalValueAttribute {
|
|
|
|
|
public:
|
|
|
|
|
NimBLECharacteristic(const char* uuid,
|
|
|
|
|
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
|
|
|
|
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
|
|
|
|
|
NimBLEService* pService = nullptr);
|
|
|
|
|
NimBLECharacteristic(const NimBLEUUID& uuid,
|
|
|
|
|
uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
|
|
|
|
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN,
|
|
|
|
|
NimBLEService* pService = nullptr);
|
2021-05-23 13:07:00 -06:00
|
|
|
|
|
|
|
|
~NimBLECharacteristic();
|
2021-02-08 15:28:32 +00:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
std::string toString() const;
|
|
|
|
|
size_t getSubscribedCount() const;
|
|
|
|
|
void addDescriptor(NimBLEDescriptor* pDescriptor);
|
|
|
|
|
void removeDescriptor(NimBLEDescriptor* pDescriptor, bool deleteDsc = false);
|
|
|
|
|
uint16_t getProperties() const;
|
|
|
|
|
void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
|
|
|
|
|
void indicate(uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
|
|
|
|
void indicate(const uint8_t* value, size_t length, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
|
|
|
|
void notify(uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
|
|
|
|
void notify(const uint8_t* value, size_t length, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
|
|
|
|
|
2022-01-16 20:11:18 -07:00
|
|
|
NimBLEDescriptor* createDescriptor(const char* uuid,
|
2024-07-26 14:47:36 -06:00
|
|
|
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
|
|
|
|
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
|
|
|
|
NimBLEDescriptor* createDescriptor(const NimBLEUUID& uuid,
|
|
|
|
|
uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
|
|
|
|
|
uint16_t max_len = BLE_ATT_ATTR_MAX_LEN);
|
|
|
|
|
NimBLEDescriptor* getDescriptorByUUID(const char* uuid) const;
|
|
|
|
|
NimBLEDescriptor* getDescriptorByUUID(const NimBLEUUID& uuid) const;
|
|
|
|
|
NimBLEDescriptor* getDescriptorByHandle(uint16_t handle) const;
|
|
|
|
|
NimBLEService* getService() const;
|
2022-01-16 20:11:18 -07:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLECharacteristicCallbacks* getCallbacks() const;
|
2022-01-16 20:11:18 -07:00
|
|
|
|
|
|
|
|
/*********************** Template Functions ************************/
|
|
|
|
|
|
|
|
|
|
/**
|
2024-10-14 18:02:21 -05:00
|
|
|
* @brief Template to send a notification for classes which may have
|
|
|
|
|
* data()/size() or c_str()/length() methods. Falls back to sending
|
|
|
|
|
* the data by casting the first element of the array to a uint8_t
|
|
|
|
|
* pointer and getting the length of the array using sizeof.
|
2022-01-16 20:11:18 -07:00
|
|
|
* @tparam T The a reference to a class containing the data to send.
|
|
|
|
|
* @param[in] value The <type\>value to set.
|
2024-10-14 18:02:21 -05:00
|
|
|
* @param[in] conn_handle The connection handle to send the notification to.
|
|
|
|
|
* @note This function is only available if the type T is not a pointer.
|
2022-01-16 20:11:18 -07:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
template <typename T>
|
2024-10-14 18:02:21 -05:00
|
|
|
typename std::enable_if<!std::is_pointer<T>::value, void>::type
|
|
|
|
|
notify(const T& value, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const {
|
|
|
|
|
if constexpr (Has_data_size<T>::value) {
|
|
|
|
|
notify(reinterpret_cast<const uint8_t*>(value.data()), value.size(), conn_handle);
|
|
|
|
|
} else if constexpr (Has_c_str_length<T>::value) {
|
|
|
|
|
notify(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), conn_handle);
|
|
|
|
|
} else {
|
|
|
|
|
notify(reinterpret_cast<const uint8_t*>(&value), sizeof(value), conn_handle);
|
|
|
|
|
}
|
2022-01-16 20:11:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-10-14 18:02:21 -05:00
|
|
|
* @brief Template to send an indication for classes which may have
|
|
|
|
|
* data()/size() or c_str()/length() methods. Falls back to sending
|
|
|
|
|
* the data by casting the first element of the array to a uint8_t
|
|
|
|
|
* pointer and getting the length of the array using sizeof.
|
2022-01-16 20:11:18 -07:00
|
|
|
* @tparam T The a reference to a class containing the data to send.
|
|
|
|
|
* @param[in] value The <type\>value to set.
|
2024-10-14 18:02:21 -05:00
|
|
|
* @param[in] conn_handle The connection handle to send the indication to.
|
|
|
|
|
* @note This function is only available if the type T is not a pointer.
|
2022-01-16 20:11:18 -07:00
|
|
|
*/
|
2024-07-26 14:47:36 -06:00
|
|
|
template <typename T>
|
2024-10-14 18:02:21 -05:00
|
|
|
typename std::enable_if<!std::is_pointer<T>::value, void>::type
|
|
|
|
|
indicate(const T& value, uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const {
|
|
|
|
|
if constexpr (Has_data_size<T>::value) {
|
|
|
|
|
indicate(reinterpret_cast<const uint8_t*>(value.data()), value.size(), conn_handle);
|
|
|
|
|
} else if constexpr (Has_c_str_length<T>::value) {
|
|
|
|
|
indicate(reinterpret_cast<const uint8_t*>(value.c_str()), value.length(), conn_handle);
|
|
|
|
|
} else {
|
|
|
|
|
indicate(reinterpret_cast<const uint8_t*>(&value), sizeof(value), conn_handle);
|
|
|
|
|
}
|
2022-01-16 20:11:18 -07:00
|
|
|
}
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
private:
|
|
|
|
|
friend class NimBLEServer;
|
|
|
|
|
friend class NimBLEService;
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
void setService(NimBLEService* pService);
|
|
|
|
|
void setSubscribe(const ble_gap_event* event, NimBLEConnInfo& connInfo);
|
|
|
|
|
void readEvent(NimBLEConnInfo& connInfo) override;
|
|
|
|
|
void writeEvent(const uint8_t* val, uint16_t len, NimBLEConnInfo& connInfo) override;
|
|
|
|
|
void sendValue(const uint8_t* value,
|
|
|
|
|
size_t length,
|
|
|
|
|
bool is_notification = true,
|
|
|
|
|
uint16_t conn_handle = BLE_HS_CONN_HANDLE_NONE) const;
|
2020-03-29 17:44:20 -06:00
|
|
|
|
2024-07-26 14:47:36 -06:00
|
|
|
NimBLECharacteristicCallbacks* m_pCallbacks{nullptr};
|
|
|
|
|
NimBLEService* m_pService{nullptr};
|
|
|
|
|
std::vector<NimBLEDescriptor*> m_vDescriptors{};
|
|
|
|
|
std::vector<std::pair<uint16_t, uint16_t>> m_subscribedVec{};
|
2020-03-29 17:44:20 -06:00
|
|
|
}; // NimBLECharacteristic
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Callbacks that can be associated with a %BLE characteristic to inform of events.
|
|
|
|
|
*
|
|
|
|
|
* When a server application creates a %BLE characteristic, we may wish to be informed when there is either
|
|
|
|
|
* a read or write request to the characteristic's value. An application can register a
|
|
|
|
|
* sub-classed instance of this class and will be notified when such an event happens.
|
|
|
|
|
*/
|
|
|
|
|
class NimBLECharacteristicCallbacks {
|
2024-07-26 14:47:36 -06:00
|
|
|
public:
|
|
|
|
|
virtual ~NimBLECharacteristicCallbacks() {}
|
2022-08-27 08:28:15 -06:00
|
|
|
virtual void onRead(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo);
|
|
|
|
|
virtual void onWrite(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo);
|
2022-08-26 20:40:21 -06:00
|
|
|
virtual void onStatus(NimBLECharacteristic* pCharacteristic, int code);
|
2022-08-27 08:28:15 -06:00
|
|
|
virtual void onSubscribe(NimBLECharacteristic* pCharacteristic, NimBLEConnInfo& connInfo, uint16_t subValue);
|
2020-03-29 17:44:20 -06:00
|
|
|
};
|
2020-05-13 22:03:56 -06:00
|
|
|
|
2021-09-06 21:14:43 -06:00
|
|
|
#endif /* CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_PERIPHERAL */
|
2024-07-26 14:47:36 -06:00
|
|
|
#endif /*NIMBLE_CPP_CHARACTERISTIC_H_*/
|