![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
A cute tiny piece of code implementing an IoT NAND device, demonstrating how to setup and advertise a cute GATT (NAND) service. The code has been tested on a Nordic nRF51822-DK.
Dependencies: BLE_API mbed nRF51822
Fork of BLE_HeartRate_IDB0XA1 by
Diff: bricks/characteristic.h
- Revision:
- 26:dce30a5341bb
diff -r 339931243be4 -r dce30a5341bb bricks/characteristic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/characteristic.h Sat May 19 14:10:17 2018 +0000 @@ -0,0 +1,247 @@ +// characteristic.h - an easy to use overloaded characteristic class +// +// Synopsis: +// +// Characteristic<type> myCharacteristic(col,uuid,mode); +// Characteristic<type> myCharacteristic(col,uuid,mode,name); +// Characteristic<type> myCharacteristic(col,uuid,mode,name,inidata); +// Characteristic<type> myCharacteristic(col,uuid,mode,inidata); +// +// Declaration of a characteristic, specifying value type, UUID and access mode, +// optionally providing a name (user descriptor) and initial data. +// +// col: Collection, to which the constructed characteristic is automati- +// cally added. After construction and adding all characteristics to +// a collection this collection is passed to a service constructor, +// which gets thus knowledge about all characteristics which have to +// be involved in the service +// +// uuid: A unique universal ID which identifies the characteristic +// +// mode: A string comprising zero or more mode characters which +// define possible properties of the characteristic. +// +// "" no properties +// "b" broadcast +// "r" read access +// "s" send & pray (write without response) +// "w" write access (with feedback) +// "n" notification (no client confirmation) +// "i" indication (with client confirmation) +// "a" authentication signed write +// "x" extended access +// +// name: An optional name provided in terms of a user descriptor. If this +// argument is omitted the user descriptor is not created. +// +// inidata: A pointer to a variable containing initializing data for the +// characteristic. If the inidata argument is not provided, an +// implicit initialization is performed which clears the characte- +// ristic (all bytes set to 0). As a concluding remark it needs to +// be noted that the implicite initialozation works only for +// sizeof(Type) <= SIZE_INIBUFFER (defined in "bricks/types.h") +// +// +// Example 1: A protocol might be declared as a class as follows +// +// Collection col; // collection used during setup +// +// Characteristic<ObjectId> id(col,0x2AC3,"rw","ID"); +// Characteristic<ObjectName> name(col,0x2ABE,"rw","Name"); +// Characteristic<Digital> presence(col,0x2A56,"r","Presence"); +// +// Service presenceDetection(col,0xA001); // instantiate service +// +// onSetup(Blob &blue) +// { +// blue.service(presenceDetection); // add service +// } +// +// Example 2: service definition by means of a service definition class +// +// class PresenceDetector +// { +// public: +// Collection col; // collection used during setup +// +// Characteristic<ObjectId> id; // ID of presence detector +// Characteristic<ObjectName> name; // name of presence detector +// Characteristic<Digital> presence; // digital presence value +// Characteristic<DateTime> timestamp; // last detection change's time +// Characteristic<ObjectName> layout; // name of model railway layout +// +// Service presenceDetection; // the service +// +// public: +// PresenceDetector(Blob &blue, cost UUID uuid) : +// list; // init service list +// id(list,0x2AC3,"rw","ID"), // instantiate characteristic +// name(list,0x2ABE,"rw","Name"), // instantiate characteristic +// presence(list,0x2A56,"r","Presence"),// instantiate characteristic +// timestamp(list,0x2A08,"r","Timestamp"),// instantiate characteristic +// layout(list,0x2ABE,"rw","Layout"), // instantiate characteristic +// presenceDetection(list,uuid) // instantiate service +// { +// blue.service(presenceDetection); // add service +// } +// }; +// +#ifndef _CHARACTERISTIC_H_ +#define _CHARACTERISTIC_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" +#include "bricks/types.h" +#include "bricks/collection.h" +#include "bricks/descriptor.h" + + // the following #define is helpful if characteristics are defined on base + // of the BLE API (the tedious way) + +#define UserDescriptor(name,attribute,descriptor,text) \ + static char *name = text; \ + static GattAttribute attribute(0x2901,(uint8_t*)name,strlen(name),strlen(name)); \ + static GattAttribute *descriptor[] = {&attribute}; + + // the declaration of Characteristics needs the availability of an + // initializing buffer in the default case + + extern IniBuffer characteristicInidata; // to initialize a characteristic + + // class definition of a characteristic initializer + + class CharacteristicInitializer // provides pointers to initialized data + { + private: + IniBuffer inibuf; // initialized data + + public: + ObjectId *pObjectId() { return (ObjectId*) &inibuf; } + ObjectName *pObjectName() { return (ObjectName*) &inibuf; } + Bool *pBool() { return (Bool*) &inibuf; } + Digital *pDigital() { return (Digital*) &inibuf; } + DateTime *pDateTime() { return (DateTime*) &inibuf; } + Buffer *pBuffer() { return (Buffer*) &inibuf; } + + public: + CharacteristicInitializer() // constructor + { + memset(inibuf,0,sizeof(IniBuffer)); + + // besides of the local inibuf also initialize the global + // init buffer characteristicInidata; + + memset(characteristicInidata,0,sizeof(IniBuffer)); + } + }; + + // definition of class Characteristic + + class Service; + + template <typename Type> + class Characteristic : public GattCharacteristic + { + private: + void init() // initialize inibuffer + { + static int initialized = 0; + + if (!initialized) // clear init data buffer + { initialized = 1; + memset(characteristicInidata,0,sizeof(IniBuffer)); + } + } + + private: + UserDescriptor descriptor; // characteristic's user descriptor + + uint8_t getmask(const char *pmask) + { + uint8_t mask = 0; + + for(;*pmask;pmask++) + { switch (*pmask) + { + case 'b': // broad cast + mask = mask | BLE_GATT_CHAR_PROPERTIES_BROADCAST; + break; + case 'r': // read + mask = mask | BLE_GATT_CHAR_PROPERTIES_READ; + break; + case 's': // send (& pray) + mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE; + break; + case 'w': // write + mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE; + break; + case 'n': // notify + mask = mask | BLE_GATT_CHAR_PROPERTIES_NOTIFY; + break; + case 'i': // indicate + mask = mask | BLE_GATT_CHAR_PROPERTIES_INDICATE; + break; + case 'a': // authenticated signed write + mask = mask | BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; + break; + case 'x': // extended properties + mask = mask | BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES; + break; + } + } + return mask; + } +/* + public: + Characteristic<Type> (Service &service, UUID uuid, const char *mode, + Type *valuePtr = (Type*)&characteristicInidata) : + GattCharacteristic(uuid, + reinterpret_cast<uint8_t*> (valuePtr), + sizeof(Type), + sizeof(Type), + getmask(mode), + NULL, // descriptor list + 0, // number of descriptors + false), + descriptor("") // construct descriptor + { + init(); // assure initializing + + // there is a potential danger that we use implicite initializing + // with sizeof(Type) > sizeof(inibuffer). This must be prevented! + + int feasible = (sizeof(Type) <= sizeof(IniBuffer)); + if (feasible || valuePtr != (Type*)&characteristicInidata) + { + service.add(this); // add to service + } // otherwise just ignore! + } +*/ + public: + Characteristic<Type> (Service &service, UUID uuid, const char *mode, + const char *name, Type *valuePtr = (Type*)&characteristicInidata) : + GattCharacteristic(uuid, + reinterpret_cast<uint8_t*> (valuePtr), + sizeof(Type), + sizeof(Type), + getmask(mode), + descriptor.plist, // descriptor list + 1, // number of descriptors + false), + descriptor(name) // construct descriptor + { + init(); // assure initializing + + // there is a potential danger that we use implicite initializing + // with sizeof(Type) > sizeof(inibuffer). This must be prevented! + + int feasible = (sizeof(Type) <= sizeof(IniBuffer)); + if (feasible || valuePtr != (Type*)&characteristicInidata) + { + service.add(this); // add to service + } // otherwise just ignore! + } + }; + + +#endif // _CHARACTERISTIC_H_ \ No newline at end of file