A nice BLE demo program which allows remote switch of an LED via GATT interface.
Dependencies: BLE_API mbed nRF51822
Fork of BLE_Button by
bricks/characteristic.h
- Committer:
- hux
- Date:
- 2017-10-21
- Revision:
- 13:0563f1aa6a75
File content as of revision 13:0563f1aa6a75:
// 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_