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)
const;
73 NimBLEDescriptor* getDescriptorByUUID(
const NimBLEUUID& uuid)
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 {
129 reinterpret_cast<const uint8_t*
>(v.data()),
130 v.size() *
sizeof(
typename T::value_type),
140 template <
typename T>
144 typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value,
bool>::type
146 notify(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
147 return notify(
reinterpret_cast<const uint8_t*
>(v.data()), v.size(), connHandle);
156 template <
typename T>
160 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value && !Has_c_str_length<T>::value &&
161 !Has_data_size<T>::value,
164 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
165 return indicate(
reinterpret_cast<const uint8_t*
>(&v),
sizeof(T), connHandle);
173 template <
typename T>
177 typename std::enable_if<Has_c_str_length<T>::value && !Has_data_size<T>::value,
bool>::type
179 indicate(
const T& s, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
180 return indicate(
reinterpret_cast<const uint8_t*
>(s.c_str()), s.length(), connHandle);
189 template <
typename T>
193 typename std::enable_if<Has_data_size<T>::value && Has_value_type<T>::value,
bool>::type
195 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
197 reinterpret_cast<const uint8_t*
>(v.data()),
198 v.size() *
sizeof(
typename T::value_type),
208 template <
typename T>
212 typename std::enable_if<Has_data_size<T>::value && !Has_value_type<T>::value,
bool>::type
214 indicate(
const T& v, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
215 return indicate(
reinterpret_cast<const uint8_t*
>(v.data()), v.size(), connHandle);
230 template <
typename T>
231 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value,
bool>::type notify(
232 const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
233 if constexpr (Has_data_size<T>::value) {
234 if constexpr (Has_value_type<T>::value) {
235 return notify(
reinterpret_cast<const uint8_t*
>(value.data()), value.size() *
sizeof(
typename T::value_type), connHandle);
237 return notify(
reinterpret_cast<const uint8_t*
>(value.data()), value.size(), connHandle);
239 }
else if constexpr (Has_c_str_length<T>::value) {
240 return notify(
reinterpret_cast<const uint8_t*
>(value.c_str()), value.length(), connHandle);
242 return notify(
reinterpret_cast<const uint8_t*
>(&value),
sizeof(value), connHandle);
256 template <
typename T>
257 typename std::enable_if<!std::is_pointer<T>::value && !std::is_array<T>::value,
bool>::type indicate(
258 const T& value, uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const {
259 if constexpr (Has_data_size<T>::value) {
260 if constexpr (Has_value_type<T>::value) {
261 return indicate(
reinterpret_cast<const uint8_t*
>(value.data()), value.size() *
sizeof(
typename T::value_type), connHandle);
263 return indicate(
reinterpret_cast<const uint8_t*
>(value.data()), value.size(), connHandle);
265 }
else if constexpr (Has_c_str_length<T>::value) {
266 return indicate(
reinterpret_cast<const uint8_t*
>(value.c_str()), value.length(), connHandle);
268 return indicate(
reinterpret_cast<const uint8_t*
>(&value),
sizeof(value), connHandle);
274 friend class NimBLEServer;
275 friend class NimBLEService;
277 void setService(NimBLEService* pService);
279 void writeEvent(
const uint8_t* val, uint16_t len,
NimBLEConnInfo& connInfo)
override;
280 bool sendValue(
const uint8_t* value,
282 bool is_notification =
true,
283 uint16_t connHandle = BLE_HS_CONN_HANDLE_NONE)
const;
285 struct SubPeerEntry {
286 enum : uint8_t { AWAITING_SECURE = 1 << 0, SECURE = 1 << 1, SUB_NOTIFY = 1 << 2, SUB_INDICATE = 1 << 3 };
287 void setConnHandle(uint16_t connHandle) { m_connHandle = connHandle; }
288 uint16_t getConnHandle()
const {
return m_connHandle; }
289 void setAwaitingSecure(
bool awaiting) { awaiting ? m_flags |= AWAITING_SECURE : m_flags &= ~AWAITING_SECURE; }
290 void setSecured(
bool secure) { secure ? m_flags |= SECURE : m_flags &= ~SECURE; }
291 void setSubNotify(
bool notify) { notify ? m_flags |= SUB_NOTIFY : m_flags &= ~SUB_NOTIFY; }
292 void setSubIndicate(
bool indicate) { indicate ? m_flags |= SUB_INDICATE : m_flags &= ~SUB_INDICATE; }
293 bool isSubNotify()
const {
return m_flags & SUB_NOTIFY; }
294 bool isSubIndicate()
const {
return m_flags & SUB_INDICATE; }
295 bool isSecured()
const {
return m_flags & SECURE; }
296 bool isAwaitingSecure()
const {
return m_flags & AWAITING_SECURE; }
299 uint16_t m_connHandle{BLE_HS_CONN_HANDLE_NONE};
301 } __attribute__((packed));
303 using SubPeerArray = std::array<SubPeerEntry, MYNEWT_VAL(BLE_MAX_CONNECTIONS)>;
304 SubPeerArray getSubscribers()
const {
return m_subPeers; }
305 void processSubRequest(
NimBLEConnInfo& connInfo, uint8_t subVal)
const;
308 NimBLECharacteristicCallbacks* m_pCallbacks{
nullptr};
309 NimBLEService* m_pService{
nullptr};
310 std::vector<NimBLEDescriptor*> m_vDescriptors{};
311 mutable SubPeerArray m_subPeers{};
321class NimBLECharacteristicCallbacks {
323 virtual ~NimBLECharacteristicCallbacks() {}
324 virtual void onRead(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo);
325 virtual void onWrite(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo);
326 virtual void onStatus(NimBLECharacteristic* pCharacteristic,
int code);
327 virtual void onStatus(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo,
int code);
328 virtual void onSubscribe(NimBLECharacteristic* pCharacteristic,
NimBLEConnInfo& connInfo, uint16_t subValue);
Connection information.
Definition NimBLEConnInfo.h:32
A model of a BLE UUID.
Definition NimBLEUUID.h:41