18#ifndef NIMBLE_CPP_CHARACTERISTIC_H_
19#define NIMBLE_CPP_CHARACTERISTIC_H_
21#include "syscfg/syscfg.h"
22#if CONFIG_BT_NIMBLE_ENABLED && MYNEWT_VAL(BLE_ROLE_PERIPHERAL)
24class NimBLECharacteristicCallbacks;
26class NimBLECharacteristic;
27class NimBLEDescriptor;
30# include "NimBLELocalValueAttribute.h"
42class NimBLECharacteristic :
public NimBLELocalValueAttribute {
44 NimBLECharacteristic(
const char* uuid,
45 uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
46 uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
47 NimBLEService* pService =
nullptr);
49 uint16_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
50 uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN,
51 NimBLEService* pService =
nullptr);
53 ~NimBLECharacteristic();
55 std::string toString()
const;
56 void addDescriptor(NimBLEDescriptor* pDescriptor);
57 void removeDescriptor(NimBLEDescriptor* pDescriptor,
bool deleteDsc =
false);
58 uint16_t getProperties()
const;
59 void setCallbacks(NimBLECharacteristicCallbacks* pCallbacks);
60 bool indicate(uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
61 bool indicate(
const uint8_t* value,
size_t length, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
62 bool notify(uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
63 bool notify(
const uint8_t* value,
size_t length, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
65 NimBLEDescriptor* createDescriptor(
const char* uuid,
66 uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
67 uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN);
68 NimBLEDescriptor* createDescriptor(
const NimBLEUUID& uuid,
69 uint32_t properties = NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE,
70 uint16_t maxLen = BLE_ATT_ATTR_MAX_LEN);
71 NimBLE2904* create2904();
72 NimBLEDescriptor* getDescriptorByUUID(
const char* uuid, uint16_t index = 0)
const;
73 NimBLEDescriptor* getDescriptorByUUID(
const NimBLEUUID& uuid, uint16_t index = 0)
const;
74 NimBLEDescriptor* getDescriptorByHandle(uint16_t handle)
const;
75 NimBLEService* getService()
const;
77 NimBLECharacteristicCallbacks* getCallbacks()
const;
81# if __cplusplus < 201703L
92 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
93 !Has_data_size<T>::value,
96 notify(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
97 return notify(
reinterpret_cast<const uint8_t*
>(&v),
sizeof(T), connHandle);
105 template <
typename T>
109 typename std::enable_if<Has_c_str_length<T>::value && !Has_data_size<T>::value,
bool>::type
111 notify(
const T& s, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
112 return notify(
reinterpret_cast<const uint8_t*
>(s.c_str()), s.length(), connHandle);
121 template <
typename T>
125 typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value,
bool>::type
127 notify(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
128 return notify(
reinterpret_cast<const uint8_t*
>(v.data()), v.size() *
sizeof(
typename T::value_type), connHandle);
136 template <
typename T>
140 typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value,
bool>::type
142 notify(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
143 return notify(
reinterpret_cast<const uint8_t*
>(v.data()), v.size(), connHandle);
152 template <
typename T>
156 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
157 !Has_data_size<T>::value,
160 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
161 return indicate(
reinterpret_cast<const uint8_t*
>(&v),
sizeof(T), connHandle);
169 template <
typename T>
173 typename std::enable_if<Has_c_str_length<T>::value && !Has_data_size<T>::value,
bool>::type
175 indicate(
const T& s, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
176 return indicate(
reinterpret_cast<const uint8_t*
>(s.c_str()), s.length(), connHandle);
185 template <
typename T>
189 typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value,
bool>::type
191 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
192 return indicate(
reinterpret_cast<const uint8_t*
>(v.data()), v.size() *
sizeof(
typename T::value_type), connHandle);
200 template <
typename T>
204 typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value,
bool>::type
206 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
207 return indicate(
reinterpret_cast<const uint8_t*
>(v.data()), v.size(), connHandle);
222 template <
typename T>
223 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value,
bool>::type notify(
224 const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
225 if constexpr (Has_data_size<T>::value) {
226 if constexpr (Has_value_type<T>::value) {
227 return notify(
reinterpret_cast<const uint8_t*
>(value.data()),
228 value.size() *
sizeof(
typename T::value_type),
231 return notify(
reinterpret_cast<const uint8_t*
>(value.data()), value.size(), connHandle);
233 }
else if constexpr (Has_c_str_length<T>::value) {
234 return notify(
reinterpret_cast<const uint8_t*
>(value.c_str()), value.length(), connHandle);
236 return notify(
reinterpret_cast<const uint8_t*
>(&value),
sizeof(value), connHandle);
250 template <
typename T>
251 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value,
bool>::type indicate(
252 const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
253 if constexpr (Has_data_size<T>::value) {
254 if constexpr (Has_value_type<T>::value) {
255 return indicate(
reinterpret_cast<const uint8_t*
>(value.data()),
256 value.size() *
sizeof(
typename T::value_type),
259 return indicate(
reinterpret_cast<const uint8_t*
>(value.data()), value.size(), connHandle);
261 }
else if constexpr (Has_c_str_length<T>::value) {
262 return indicate(
reinterpret_cast<const uint8_t*
>(value.c_str()), value.length(), connHandle);
264 return indicate(
reinterpret_cast<const uint8_t*
>(&value),
sizeof(value), connHandle);
270 friend class NimBLEServer;
271 friend class NimBLEService;
273 void setService(NimBLEService* pService);
275 void writeEvent(
const uint8_t* val, uint16_t len,
NimBLEConnInfo& connInfo)
override;
276 bool sendValue(
const uint8_t* value,
278 bool is_notification =
true,
279 uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
281 struct SubPeerEntry {
282 enum : uint8_t { AWAITING_SECURE = 1 << 0, SECURE = 1 << 1, SUB_NOTIFY = 1 << 2, SUB_INDICATE = 1 << 3 };
283 void setConnHandle(uint16_t connHandle) { m_connHandle = connHandle; }
284 uint16_t getConnHandle()
const {
return m_connHandle; }
285 void setAwaitingSecure(
bool awaiting) { awaiting ? m_flags |= AWAITING_SECURE : m_flags &= ~AWAITING_SECURE; }
286 void setSecured(
bool secure) { secure ? m_flags |= SECURE : m_flags &= ~SECURE; }
287 void setSubNotify(
bool notify) { notify ? m_flags |= SUB_NOTIFY : m_flags &= ~SUB_NOTIFY; }
288 void setSubIndicate(
bool indicate) { indicate ? m_flags |= SUB_INDICATE : m_flags &= ~SUB_INDICATE; }
289 bool isSubNotify()
const {
return m_flags & SUB_NOTIFY; }
290 bool isSubIndicate()
const {
return m_flags & SUB_INDICATE; }
291 bool isSecured()
const {
return m_flags & SECURE; }
292 bool isAwaitingSecure()
const {
return m_flags & AWAITING_SECURE; }
295 uint16_t m_connHandle{BLE_HS_CONN_HANDLE_NONE};
297 } __attribute__((packed));
299 using SubPeerArray = std::array<SubPeerEntry, MYNEWT_VAL(BLE_MAX_CONNECTIONS)>;
300 SubPeerArray getSubscribers()
const {
return m_subPeers; }
301 void processSubRequest(
NimBLEConnInfo& connInfo, uint8_t subVal)
const;
304 NimBLECharacteristicCallbacks* m_pCallbacks{
nullptr};
305 NimBLEService* m_pService{
nullptr};
306 std::vector<NimBLEDescriptor*> m_vDescriptors{};
307 mutable SubPeerArray m_subPeers{};
317class NimBLECharacteristicCallbacks {
319 virtual ~NimBLECharacteristicCallbacks() {}
320 virtual void onRead(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo);
321 virtual void onWrite(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo);
322 virtual void onStatus(NimBLECharacteristic* pCharacteristic,
int code);
323 virtual void onStatus(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo,
int code);
324 virtual void onSubscribe(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo, uint16_t subValue);
Connection information.
Definition NimBLEConnInfo.h:33
A model of a BLE UUID.
Definition NimBLEUUID.h:41