Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API X_NUCLEO_IDB0XA1 mbed
Fork of BLE_HeartRate_IDB0XA1 by
bricks/characteristic.h@29:8eb46b976f0f, 2018-05-19 (annotated)
- Committer:
- hux
- Date:
- Sat May 19 15:53:19 2018 +0000
- Revision:
- 29:8eb46b976f0f
- Parent:
- 28:114eaad388c1
Published
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| hux | 28:114eaad388c1 | 1 | // characteristic.h - an easy to use overloaded characteristic class | 
| hux | 28:114eaad388c1 | 2 | // | 
| hux | 28:114eaad388c1 | 3 | // Synopsis: | 
| hux | 28:114eaad388c1 | 4 | // | 
| hux | 28:114eaad388c1 | 5 | // Characteristic<type> myCharacteristic(col,uuid,mode); | 
| hux | 28:114eaad388c1 | 6 | // Characteristic<type> myCharacteristic(col,uuid,mode,name); | 
| hux | 28:114eaad388c1 | 7 | // Characteristic<type> myCharacteristic(col,uuid,mode,name,inidata); | 
| hux | 28:114eaad388c1 | 8 | // Characteristic<type> myCharacteristic(col,uuid,mode,inidata); | 
| hux | 28:114eaad388c1 | 9 | // | 
| hux | 28:114eaad388c1 | 10 | // Declaration of a characteristic, specifying value type, UUID and access mode, | 
| hux | 28:114eaad388c1 | 11 | // optionally providing a name (user descriptor) and initial data. | 
| hux | 28:114eaad388c1 | 12 | // | 
| hux | 28:114eaad388c1 | 13 | // col: Collection, to which the constructed characteristic is automati- | 
| hux | 28:114eaad388c1 | 14 | // cally added. After construction and adding all characteristics to | 
| hux | 28:114eaad388c1 | 15 | // a collection this collection is passed to a service constructor, | 
| hux | 28:114eaad388c1 | 16 | // which gets thus knowledge about all characteristics which have to | 
| hux | 28:114eaad388c1 | 17 | // be involved in the service | 
| hux | 28:114eaad388c1 | 18 | // | 
| hux | 28:114eaad388c1 | 19 | // uuid: A unique universal ID which identifies the characteristic | 
| hux | 28:114eaad388c1 | 20 | // | 
| hux | 28:114eaad388c1 | 21 | // mode: A string comprising zero or more mode characters which | 
| hux | 28:114eaad388c1 | 22 | // define possible properties of the characteristic. | 
| hux | 28:114eaad388c1 | 23 | // | 
| hux | 28:114eaad388c1 | 24 | // "" no properties | 
| hux | 28:114eaad388c1 | 25 | // "b" broadcast | 
| hux | 28:114eaad388c1 | 26 | // "r" read access | 
| hux | 28:114eaad388c1 | 27 | // "s" send & pray (write without response) | 
| hux | 28:114eaad388c1 | 28 | // "w" write access (with feedback) | 
| hux | 28:114eaad388c1 | 29 | // "n" notification (no client confirmation) | 
| hux | 28:114eaad388c1 | 30 | // "i" indication (with client confirmation) | 
| hux | 28:114eaad388c1 | 31 | // "a" authentication signed write | 
| hux | 28:114eaad388c1 | 32 | // "x" extended access | 
| hux | 28:114eaad388c1 | 33 | // | 
| hux | 28:114eaad388c1 | 34 | // name: An optional name provided in terms of a user descriptor. If this | 
| hux | 28:114eaad388c1 | 35 | // argument is omitted the user descriptor is not created. | 
| hux | 28:114eaad388c1 | 36 | // | 
| hux | 28:114eaad388c1 | 37 | // inidata: A pointer to a variable containing initializing data for the | 
| hux | 28:114eaad388c1 | 38 | // characteristic. If the inidata argument is not provided, an | 
| hux | 28:114eaad388c1 | 39 | // implicit initialization is performed which clears the characte- | 
| hux | 28:114eaad388c1 | 40 | // ristic (all bytes set to 0). As a concluding remark it needs to | 
| hux | 28:114eaad388c1 | 41 | // be noted that the implicite initialozation works only for | 
| hux | 28:114eaad388c1 | 42 | // sizeof(Type) <= SIZE_INIBUFFER (defined in "bricks/types.h") | 
| hux | 28:114eaad388c1 | 43 | // | 
| hux | 28:114eaad388c1 | 44 | // | 
| hux | 28:114eaad388c1 | 45 | // Example 1: A protocol might be declared as a class as follows | 
| hux | 28:114eaad388c1 | 46 | // | 
| hux | 28:114eaad388c1 | 47 | // Collection col; // collection used during setup | 
| hux | 28:114eaad388c1 | 48 | // | 
| hux | 28:114eaad388c1 | 49 | // Characteristic<ObjectId> id(col,0x2AC3,"rw","ID"); | 
| hux | 28:114eaad388c1 | 50 | // Characteristic<ObjectName> name(col,0x2ABE,"rw","Name"); | 
| hux | 28:114eaad388c1 | 51 | // Characteristic<Digital> presence(col,0x2A56,"r","Presence"); | 
| hux | 28:114eaad388c1 | 52 | // | 
| hux | 28:114eaad388c1 | 53 | // Service presenceDetection(col,0xA001); // instantiate service | 
| hux | 28:114eaad388c1 | 54 | // | 
| hux | 28:114eaad388c1 | 55 | // onSetup(Blob &blue) | 
| hux | 28:114eaad388c1 | 56 | // { | 
| hux | 28:114eaad388c1 | 57 | // blue.service(presenceDetection); // add service | 
| hux | 28:114eaad388c1 | 58 | // } | 
| hux | 28:114eaad388c1 | 59 | // | 
| hux | 28:114eaad388c1 | 60 | // Example 2: service definition by means of a service definition class | 
| hux | 28:114eaad388c1 | 61 | // | 
| hux | 28:114eaad388c1 | 62 | // class PresenceDetector | 
| hux | 28:114eaad388c1 | 63 | // { | 
| hux | 28:114eaad388c1 | 64 | // public: | 
| hux | 28:114eaad388c1 | 65 | // Collection col; // collection used during setup | 
| hux | 28:114eaad388c1 | 66 | // | 
| hux | 28:114eaad388c1 | 67 | // Characteristic<ObjectId> id; // ID of presence detector | 
| hux | 28:114eaad388c1 | 68 | // Characteristic<ObjectName> name; // name of presence detector | 
| hux | 28:114eaad388c1 | 69 | // Characteristic<Digital> presence; // digital presence value | 
| hux | 28:114eaad388c1 | 70 | // Characteristic<DateTime> timestamp; // last detection change's time | 
| hux | 28:114eaad388c1 | 71 | // Characteristic<ObjectName> layout; // name of model railway layout | 
| hux | 28:114eaad388c1 | 72 | // | 
| hux | 28:114eaad388c1 | 73 | // Service presenceDetection; // the service | 
| hux | 28:114eaad388c1 | 74 | // | 
| hux | 28:114eaad388c1 | 75 | // public: | 
| hux | 28:114eaad388c1 | 76 | // PresenceDetector(Blob &blue, cost UUID uuid) : | 
| hux | 28:114eaad388c1 | 77 | // list; // init service list | 
| hux | 28:114eaad388c1 | 78 | // id(list,0x2AC3,"rw","ID"), // instantiate characteristic | 
| hux | 28:114eaad388c1 | 79 | // name(list,0x2ABE,"rw","Name"), // instantiate characteristic | 
| hux | 28:114eaad388c1 | 80 | // presence(list,0x2A56,"r","Presence"),// instantiate characteristic | 
| hux | 28:114eaad388c1 | 81 | // timestamp(list,0x2A08,"r","Timestamp"),// instantiate characteristic | 
| hux | 28:114eaad388c1 | 82 | // layout(list,0x2ABE,"rw","Layout"), // instantiate characteristic | 
| hux | 28:114eaad388c1 | 83 | // presenceDetection(list,uuid) // instantiate service | 
| hux | 28:114eaad388c1 | 84 | // { | 
| hux | 28:114eaad388c1 | 85 | // blue.service(presenceDetection); // add service | 
| hux | 28:114eaad388c1 | 86 | // } | 
| hux | 28:114eaad388c1 | 87 | // }; | 
| hux | 28:114eaad388c1 | 88 | // | 
| hux | 28:114eaad388c1 | 89 | #ifndef _CHARACTERISTIC_H_ | 
| hux | 28:114eaad388c1 | 90 | #define _CHARACTERISTIC_H_ | 
| hux | 28:114eaad388c1 | 91 | |
| hux | 28:114eaad388c1 | 92 | #include "ble/BLE.h" | 
| hux | 28:114eaad388c1 | 93 | #include "ble/Gap.h" | 
| hux | 28:114eaad388c1 | 94 | #include "bricks/types.h" | 
| hux | 28:114eaad388c1 | 95 | #include "bricks/collection.h" | 
| hux | 28:114eaad388c1 | 96 | #include "bricks/descriptor.h" | 
| hux | 28:114eaad388c1 | 97 | |
| hux | 28:114eaad388c1 | 98 | extern IniBuffer characteristicInidata; // to initialize a characteristic | 
| hux | 28:114eaad388c1 | 99 | |
| hux | 28:114eaad388c1 | 100 | class Service; | 
| hux | 28:114eaad388c1 | 101 | |
| hux | 28:114eaad388c1 | 102 | template <typename Type> | 
| hux | 28:114eaad388c1 | 103 | class Characteristic : public GattCharacteristic | 
| hux | 28:114eaad388c1 | 104 | { | 
| hux | 28:114eaad388c1 | 105 | private: | 
| hux | 28:114eaad388c1 | 106 | void init() // initialize inibuffer | 
| hux | 28:114eaad388c1 | 107 | { | 
| hux | 28:114eaad388c1 | 108 | static int initialized = 0; | 
| hux | 28:114eaad388c1 | 109 | |
| hux | 28:114eaad388c1 | 110 | if (!initialized) // clear init data buffer | 
| hux | 28:114eaad388c1 | 111 | { initialized = 1; | 
| hux | 28:114eaad388c1 | 112 | memset(characteristicInidata,0,sizeof(IniBuffer)); | 
| hux | 28:114eaad388c1 | 113 | } | 
| hux | 28:114eaad388c1 | 114 | } | 
| hux | 28:114eaad388c1 | 115 | |
| hux | 28:114eaad388c1 | 116 | private: | 
| hux | 28:114eaad388c1 | 117 | UserDescriptor descriptor; // characteristic's user descriptor | 
| hux | 28:114eaad388c1 | 118 | |
| hux | 28:114eaad388c1 | 119 | uint8_t getmask(const char *pmask) | 
| hux | 28:114eaad388c1 | 120 | { | 
| hux | 28:114eaad388c1 | 121 | uint8_t mask = 0; | 
| hux | 28:114eaad388c1 | 122 | |
| hux | 28:114eaad388c1 | 123 | for(;*pmask;pmask++) | 
| hux | 28:114eaad388c1 | 124 | { switch (*pmask) | 
| hux | 28:114eaad388c1 | 125 | { | 
| hux | 28:114eaad388c1 | 126 | case 'b': // broad cast | 
| hux | 28:114eaad388c1 | 127 | mask = mask | BLE_GATT_CHAR_PROPERTIES_BROADCAST; | 
| hux | 28:114eaad388c1 | 128 | break; | 
| hux | 28:114eaad388c1 | 129 | case 'r': // read | 
| hux | 28:114eaad388c1 | 130 | mask = mask | BLE_GATT_CHAR_PROPERTIES_READ; | 
| hux | 28:114eaad388c1 | 131 | break; | 
| hux | 28:114eaad388c1 | 132 | case 's': // send (& pray) | 
| hux | 28:114eaad388c1 | 133 | mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE; | 
| hux | 28:114eaad388c1 | 134 | break; | 
| hux | 28:114eaad388c1 | 135 | case 'w': // write | 
| hux | 28:114eaad388c1 | 136 | mask = mask | BLE_GATT_CHAR_PROPERTIES_WRITE; | 
| hux | 28:114eaad388c1 | 137 | break; | 
| hux | 28:114eaad388c1 | 138 | case 'n': // notify | 
| hux | 28:114eaad388c1 | 139 | mask = mask | BLE_GATT_CHAR_PROPERTIES_NOTIFY; | 
| hux | 28:114eaad388c1 | 140 | break; | 
| hux | 28:114eaad388c1 | 141 | case 'i': // indicate | 
| hux | 28:114eaad388c1 | 142 | mask = mask | BLE_GATT_CHAR_PROPERTIES_INDICATE; | 
| hux | 28:114eaad388c1 | 143 | break; | 
| hux | 28:114eaad388c1 | 144 | case 'a': // authenticated signed write | 
| hux | 28:114eaad388c1 | 145 | mask = mask | BLE_GATT_CHAR_PROPERTIES_AUTHENTICATED_SIGNED_WRITES; | 
| hux | 28:114eaad388c1 | 146 | break; | 
| hux | 28:114eaad388c1 | 147 | case 'x': // extended properties | 
| hux | 28:114eaad388c1 | 148 | mask = mask | BLE_GATT_CHAR_PROPERTIES_EXTENDED_PROPERTIES; | 
| hux | 28:114eaad388c1 | 149 | break; | 
| hux | 28:114eaad388c1 | 150 | } | 
| hux | 28:114eaad388c1 | 151 | } | 
| hux | 28:114eaad388c1 | 152 | return mask; | 
| hux | 28:114eaad388c1 | 153 | } | 
| hux | 28:114eaad388c1 | 154 | |
| hux | 28:114eaad388c1 | 155 | public: | 
| hux | 28:114eaad388c1 | 156 | Characteristic<Type> (Service &service, UUID uuid, const char *mode, | 
| hux | 28:114eaad388c1 | 157 | Type *valuePtr = (Type*)&characteristicInidata) : | 
| hux | 28:114eaad388c1 | 158 | GattCharacteristic(uuid, | 
| hux | 28:114eaad388c1 | 159 | reinterpret_cast<uint8_t*> (valuePtr), | 
| hux | 28:114eaad388c1 | 160 | sizeof(Type), | 
| hux | 28:114eaad388c1 | 161 | sizeof(Type), | 
| hux | 28:114eaad388c1 | 162 | getmask(mode), | 
| hux | 28:114eaad388c1 | 163 | NULL, // descriptor list | 
| hux | 28:114eaad388c1 | 164 | 0, // number of descriptors | 
| hux | 28:114eaad388c1 | 165 | false) | 
| hux | 28:114eaad388c1 | 166 | { | 
| hux | 28:114eaad388c1 | 167 | init(); // assure initializing | 
| hux | 28:114eaad388c1 | 168 | |
| hux | 28:114eaad388c1 | 169 | // there is a potential danger that we use implicite initializing | 
| hux | 28:114eaad388c1 | 170 | // with sizeof(Type) > sizeof(inibuffer). This must be prevented! | 
| hux | 28:114eaad388c1 | 171 | |
| hux | 28:114eaad388c1 | 172 | int feasible = (sizeof(Type) <= sizeof(inibuffer)); | 
| hux | 28:114eaad388c1 | 173 | if (feasible || valuePtr != (Type*)&characteristicInidata) | 
| hux | 28:114eaad388c1 | 174 | { | 
| hux | 28:114eaad388c1 | 175 | service.add(this); // add to service | 
| hux | 28:114eaad388c1 | 176 | } // otherwise just ignore! | 
| hux | 28:114eaad388c1 | 177 | } | 
| hux | 28:114eaad388c1 | 178 | |
| hux | 28:114eaad388c1 | 179 | public: | 
| hux | 28:114eaad388c1 | 180 | Characteristic<Type> (Service &service, UUID uuid, const char *mode, | 
| hux | 28:114eaad388c1 | 181 | const char *name, Type *valuePtr = (Type*)&characteristicInidata) : | 
| hux | 28:114eaad388c1 | 182 | GattCharacteristic(uuid, | 
| hux | 28:114eaad388c1 | 183 | reinterpret_cast<uint8_t*> (valuePtr), | 
| hux | 28:114eaad388c1 | 184 | sizeof(Type), | 
| hux | 28:114eaad388c1 | 185 | sizeof(Type), | 
| hux | 28:114eaad388c1 | 186 | getmask(mode), | 
| hux | 28:114eaad388c1 | 187 | descriptor.plist, // descriptor list | 
| hux | 28:114eaad388c1 | 188 | 1, // number of descriptors | 
| hux | 28:114eaad388c1 | 189 | false), | 
| hux | 28:114eaad388c1 | 190 | descriptor(name) // construct descriptor | 
| hux | 28:114eaad388c1 | 191 | { | 
| hux | 28:114eaad388c1 | 192 | init(); // assure initializing | 
| hux | 28:114eaad388c1 | 193 | |
| hux | 28:114eaad388c1 | 194 | // there is a potential danger that we use implicite initializing | 
| hux | 28:114eaad388c1 | 195 | // with sizeof(Type) > sizeof(inibuffer). This must be prevented! | 
| hux | 28:114eaad388c1 | 196 | |
| hux | 28:114eaad388c1 | 197 | int feasible = (sizeof(Type) <= sizeof(IniBuffer)); | 
| hux | 28:114eaad388c1 | 198 | if (feasible || valuePtr != (Type*)&characteristicInidata) | 
| hux | 28:114eaad388c1 | 199 | { | 
| hux | 28:114eaad388c1 | 200 | service.add(this); // add to service | 
| hux | 28:114eaad388c1 | 201 | } // otherwise just ignore! | 
| hux | 28:114eaad388c1 | 202 | } | 
| hux | 28:114eaad388c1 | 203 | }; | 
| hux | 28:114eaad388c1 | 204 | |
| hux | 28:114eaad388c1 | 205 | |
| hux | 28:114eaad388c1 | 206 | #endif // _CHARACTERISTIC_H_ | 
