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
Revision 13:0563f1aa6a75, committed 2017-10-21
- Comitter:
- hux
- Date:
- Sat Oct 21 19:56:15 2017 +0000
- Parent:
- 12:0d0ca44397dd
- Commit message:
- Switch LED via BLE GATT
Changed in this revision
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/blink.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/blink.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,49 @@ +// blink.h - blinking sequences for LED1 +#ifndef _BLINK_H_ +#define _BLINK_H_ + +#include <mbed.h> +#include "bricks/o.h" + +# define BLINK_SEQUENCE_IDLE "x " +# define BLINK_SEQUENCE_ADVERTISE "x xxx " +# define BLINK_SEQUENCE_CONNECTED " xxx " +# define BLINK_SEQUENCE_ACTION "x x x x x " +# define BLINK_SEQUENCE_ERROR "x x x x xxx " +# define BLINK_SEQUENCE_TRANSITION "x x x " + + void morse(O&o,const char *pattern, double periode = 0.2); + void blink(O&o,const char *pattern, const char* next, double interval = 0.2); + void blink(O&o,const char *pattern, double periode = 0.2); + + inline void blinkIdle(O&o, const char *action = BLINK_SEQUENCE_IDLE) + { + blink(o,action,BLINK_SEQUENCE_IDLE); + } + + inline void blinkAdvertise(O&o,const char *action = BLINK_SEQUENCE_ADVERTISE) + { + blink(o,action,BLINK_SEQUENCE_ADVERTISE); + } + + inline void blinkConnected(O&o, const char *action = BLINK_SEQUENCE_ACTION) + { + blink(o,action, BLINK_SEQUENCE_CONNECTED); + } + + inline void blinkAction(O&o) // 'action' blink sequence + { + blink(o,BLINK_SEQUENCE_ACTION, BLINK_SEQUENCE_IDLE); + } + + inline void blinkError(O&o, const char *action = BLINK_SEQUENCE_ERROR) + { + blink(o,action,BLINK_SEQUENCE_ERROR); + } + + inline void blink(O&o) // stop blinking + { + blink(o,""); // empty blinking pattern + } + +#endif // _BLINK_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/blob.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/blob.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,59 @@ +// blob.h - 'BLOBs' are BLuetooth OBjects +#ifndef _BLOB_H_ +#define _BLOB_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" + +#define _ICCC BLE::InitializationCompleteCallbackContext // pure short hand +#define _GDCP Gap::DisconnectionCallbackParams_t // pure short hand +#define _GCCP Gap::ConnectionCallbackParams_t // pure short hand +#define _GWCP GattWriteCallbackParams // pure short hand + + class Blob : public BLE + { + public: + const _ICCC *pComplete; // params to _ICCC context + const _GCCP *pConnect; // params to _GCCP context + const _GDCP *pDisconnect; // params to _GDPC context + const _GWCP *pWritten; // params to _GWCP context + + public: // construction + Blob() : BLE() // standard constructor + { + pComplete = 0; pDisconnect = 0; + } + }; + + +// Setup Advertising Name (syntactic sugar) + + inline void name(Blob &o, const char *str) + { + o.gap().accumulateAdvertisingPayload( + GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)str, strlen(str)+1); + } + + +// Setup Device Name (syntactic sugar) + + inline void device(Blob &o, const char *text) + { + o.gap().setDeviceName((const uint8_t *)text); + } + + +// Setup Advertising Data (syntactic sugar) + + inline void data(Blob &o, const uint8_t *buf, size_t buflen) + { + o.gap().accumulateAdvertisingPayload(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, buf, buflen); + } + + inline void data(Blob &o, const char *text) + { + size_t len = strlen(text); + data(o,(const uint8_t*)text,len); + } + +#endif // _BLOB_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/bricks.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/bricks.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,32 @@ +// bricks.h - single header for inclusion of BLE stuff +// and most common brick headers + +#ifndef _BRICKS_H_ +#define _BRICKS_H_ + +#include <mbed.h> +#include "ble/BLE.h" + + // include o.h before any other includes of bricks headers + +#include "bricks/o.h" + + // include other bricks headers in any order (we use alphabetical order) + +#include "bricks/advertise.h" +#include "bricks/blink.h" +#include "bricks/callback.h" +#include "bricks/characteristic.h" +#include "bricks/collection.h" +#include "bricks/enroll.h" +#include "bricks/get.h" +#include "bricks/init.h" +#include "bricks/print.h" +#include "bricks/service.h" +#include "bricks/set.h" +#include "bricks/sleep.h" +#include "bricks/trace.h" +#include "bricks/types.h" +#include "bricks/updated.h" + +#endif // _BRICKS_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/characteristic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/characteristic.h Sat Oct 21 19:56:15 2017 +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
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/collection.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/collection.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,93 @@ +// collection.h - used to setup a collection of characteristics in order to +// setup a service. +// +// Description: +// Collections are used to setup a service comprising a collection of +// characteristics. The setup sequence starts with declaring a collection +// (this constructs an empty collection) while passing the collection in- +// stance repeatedly to a constructor of a characteristic, which auto-adds +// the new constructed characteristics to the collection. Finally, when the +// collection instance is passed to a service constructor, the service con- +// structor is able to access all characteristics which have been collected +// previously. +// +// 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 _COLLECTION_H_ +#define _COLLECTION_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" + + class Collection + { + private: + typedef GattCharacteristic *GattCharPtr; + + public: + GattCharacteristic **plist; + int count; + + Collection() // construct empty collection + { + plist = 0; count = 0; // init properties + } + + void add(GattCharPtr p) + { + GattCharPtr *pnew = new GattCharPtr[count+1]; + pnew[count] = p; // add new characteristic + + if (count > 0) + { for (int i=0; i < count; i++) + pnew[i] = plist[i]; + delete plist; + } + plist = pnew; // update list pointer + count++; + } + }; + +#endif // _COLLECTION_H_
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/descriptor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/descriptor.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,50 @@ +// descriptor.h - a description list, containing a single descriptor +// +// Synopsis: +// +// Descriptor user(0x2901,"User"); +// Descriptor client(0x2902,"Client"); +// +// UserDescriptor status("Status"); // user descriptor 0x2901 +// ClientDescriptor client("Client"); // client descriptor 0x2902 +// +#ifndef _DESCRIPTOR_H_ +#define _DESCRIPTOR_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" + + class Descriptor : public GattAttribute + { + private: + typedef GattAttribute *GattAttributePtr; + + public: + GattAttributePtr plist[1]; + + Descriptor(UUID uuid, const char *name) : + GattAttribute(uuid,(uint8_t*)name,strlen(name),strlen(name)) + { + plist[0] = this; + } + }; + + class UserDescriptor : public Descriptor + { + public: + UserDescriptor(const char *name) : Descriptor(0x2901,name) + { + // empty + } + }; + + class ClientDescriptor : public Descriptor + { + public: + ClientDescriptor(const char *name) : Descriptor(0x2902,name) + { + // empty + } + }; + +#endif // _DESCRIPTOR_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/enroll.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/enroll.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,83 @@ +// enroll.h - enroll a service +// +// Synopsis: +// +// void enroll(Blob &o, GattService &gservice); +// void enroll(Blob &o, uint16_t bcid = 0xFFFF); +// +// void enroll(Blob &o, Service &service, uint16_t bcid = 0xFFFF); +// +// Arguments: +// +// o: Blob object (to avoid name clashes) +// gservice: The GattService to be enrolled +// service: The Service to be enrolled +// bcid: Broadcast ID (optional); if not provided the default value +// 0xFFFF will be used +// +// Description +// +// There are three ways to call enrollment. +// +// In the first case the service has been setup via a GattService class. +// The service is enrolled by registering the service @ GAP. On advertising +// the provided broadcast ID is used (otherwise default ID 0xFFFF). +// +// The second case is based on a Service class object which has been setup +// by having added a set of characteristics to the internal collection. Upon +// enrollment a GattService instance will be created internally and enroll- +// ment of this GattService will be performed according to the first case. +// +// The third way is to enroll only the service id. This calling syntax is +// used, if a Gatt servive is pre-enrolled without enrolling the service ID. +// +// Example 1: enrollment of GattService +// +// enroll(o,gservice); +// enroll(o,0xFFFF); +// +// See also: SERVICE +// +#ifndef _ENROLL_H_ +#define _ENROLL_H_ + +#include "bricks/blob.h" +#include "bricks/service.h" + + + inline void enroll(Blob &o, uint16_t bcid = 0xFFFF) + { + static uint16_t list[1]; + + // Custom UUID, FFFF is reserved for development + // Used for UUID's broadcast in advertising packet + + list[0] = bcid; // set broadcast ID + +// o.pble->gap().accumulateAdvertisingPayload( + o.gap().accumulateAdvertisingPayload( + GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, + (uint8_t *)list, sizeof(list)); + } + + + inline void enroll(Blob &o, GattService &gservice, uint16_t bcid = 0xFFFF) + { +// o.pble->addService(gservice); // add service to GATT attributes + o.addService(gservice); // add service to GATT attributes + enroll(o,bcid); // enroll GattService (without BCID) + } + + + inline void enroll(Blob &o, Service &service, uint16_t bcid = 0) + { + Collection &collection = service.collection; + GattService gservice(service.uuid, collection.plist, collection.count); + + if (bcid == 0) + bcid = service.uuid; + + enroll(o,gservice,bcid); // enroll GattService (with BCID) + } + +#endif // _ENROLL_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/get.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/get.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,52 @@ +// get.h - get data from a characteristics +// +// Synopsis: +// +// Get data from a 'characteristic' into a 'data' variable +// +// get(characteristic,data) +// +// The 'get' function (overloaded function family) is implemented for all +// types defined in "bricks/types.h". +// +// See also: CHARACTERISTIC, SET +// +#ifndef _GET_H_ +#define _GET_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" +#include "ble/GattClient.h" +#include "bricks/o.h" +#include "bricks/types.h" +#include "bricks/characteristic.h" + + inline void get(O&o, Characteristic<Bool> &chr, Bool &data) + { + uint16_t size = sizeof(Bool)/sizeof(uint8_t); + o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size); + } + + inline void get(O&o, Characteristic<ObjectId> &chr, ObjectId &data) + { + uint16_t size = sizeof(ObjectId)/sizeof(uint8_t); + o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size); + } + + inline void get(O&o, Characteristic<Buffer> &chr, Buffer &data) + { + uint16_t size = sizeof(Buffer)/sizeof(uint8_t); + o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data,&size); + } + +// we provide also some GET methods for GattCharacteristics. However the use +// of these methods are more dangerous, because a GattCharacteristics can be +// of any type and the compiler cannot help us to check !!! + + inline void get(O&o,GattCharacteristic &chr, Bool &data) + { + uint16_t size = sizeof(Bool)/sizeof(uint8_t); + o.gattServer().read(chr.getValueHandle(), (uint8_t*)&data, &size); + } + +#endif // _GET_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/print.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/print.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,49 @@ +// print.h - print value of a characteristic +// +// Synopsis: +// +// See also: CHARACTERISTIC, GET, SET +// +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#include "ble/Gap.h" +#include "bricks/o.h" +#include "bricks/types.h" +#include "bricks/characteristic.h" + +//============================================================================== +// Some Callbacks +//============================================================================== + + inline void print(O&o, Characteristic<Buffer> &chr, const char *name) + { + Serial out(USBTX, USBRX); // serial port to PC terminal + + Buffer data; uint8_t *p = data; + get(o,chr,data); + + out.printf("%s: %02x-%02x-%02x-%02x-%02x-",name,(int)(p[0]),(int)(p[1]),(int)(p[2]),(int)(p[3]),(int)(p[4])); + out.printf("%02x-%02x-%02x-%02x-%02x\r\n",(int)(p[5]),(int)(p[6]),(int)(p[7]),(int)(p[8]),(int)(p[9])); + } + + inline void print(O&o, Characteristic<Bool> &chr, const char *name) + { + Serial out(USBTX, USBRX); // serial port to PC terminal + Bool data; + + get(o,chr,data); + out.printf("%s: %02x\r\n",name,(int)data); + } + +// we provide also some PRINT methods for non Characteristics. If the value of +// a characteristic needs to be printed the value must be fetched before with +// the GET function. + + inline void print(O&o, Bool data, const char *name) + { + Serial out(USBTX, USBRX); // serial port to PC terminal + out.printf("%s: %02x\r\n",(int)&data); + } + +#endif // _PRINT_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/service.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/service.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,85 @@ +// service.h - declaring services and definitions +// +// Synopsis +// +// 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); // use 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 +// { +// Blob blue; +// blue.service(presenceDetection); // use service +// } +// }; +// +#ifndef _SERVICE_H_ +#define _SERVICE_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" +#include "bricks/blob.h" +#include "bricks/collection.h" + + // the following #define is helpful if a service is defined on base of the + // BLE API (the tedios way) + +#define GattListLength(list) (sizeof(list)/sizeof(GattCharacteristic*)) + + // Service classs definition + + class Service + { + public: // public properties + Collection collection; // collection of characteristics + uint16_t uuid; // UUID of service + const char *name; // name of service + + public: // public methods + Service(uint16_t _uuid, const char* _name = NULL) : collection() + { + uuid = _uuid; + name = _name; + } + + void add(GattCharacteristic *pChr) // add a characteristic to collection + { + collection.add(pChr); + } + }; + +#endif // _SERVICE_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/set.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/set.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,46 @@ +// set.h - set data from a characteristics +// +// Synopsis: +// +// Set data from a 'characteristic' based on 'data' variable +// +// set(characteristic,data) +// +// The 'set' function (overloaded function family) is implemented for all +// types defined in "bricks/types.h". +// +// See also: CHARACTERISTIC, GET +// +#ifndef _SET_H_ +#define _SET_H_ + +#include "ble/BLE.h" +#include "ble/Gap.h" +#include "ble/GattServer.h" +#include "bricks/o.h" +#include "bricks/types.h" +#include "bricks/characteristic.h" + + inline void set(O&o, Characteristic<Bool> &chr, const Bool &data) + { + uint16_t size = sizeof(Bool)/sizeof(uint8_t); + o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size); + } + + inline void set(O&o, Characteristic<ObjectId> &chr, const ObjectId &data) + { + uint16_t size = sizeof(ObjectId)/sizeof(uint8_t); + o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size); + } + +// we provide also some SET methods for GattCharacteristics. However the use +// of these methods are more dangerous, because a GattCharacteristics can be +// of any type and the compiler cannot help us to check !!! + + inline void set(O&o,GattCharacteristic &chr,Bool data) + { + uint16_t size = sizeof(Bool)/sizeof(uint8_t); + o.gattServer().write(chr.getValueHandle(), (uint8_t*)&data,size); + } + +#endif // _SET_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/trace.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/trace.cpp Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,53 @@ +// trace.cpp - trace a message depending on verbose level +// + +#include "bricks/trace.h" + + static Serial pc(USBTX, USBRX); // serial port to PC terminal + +//============================================================================== +// Managing the Verbose Lewvel +//============================================================================== + + static int threshold = 0; // verbose threshold, no verbose messages + + void verbose(O&o, int level) // setup verbose level + { + threshold = level; // update verbose threshold + } + +//============================================================================== +// Printing Trace Messages +//============================================================================== + + void trace(O&o, int level, const char *msg) // trace a message + { + if (level <= threshold) // update verbose threshold + { char buf[2] = " "; // must be terminated + + for (; *msg; msg++) + { buf[0] = *msg; + pc.printf(buf); + if (*msg == '\n') + { buf[0] = '\r'; // auto adding carriage return + pc.printf(buf); + } + } + } + } + + void trace(O&o, int level, const char*format, int value) + { + char buf[80]; + if (strlen(format) > 70) + trace(o,level," *** buffer overflow *** "); + else + { sprintf(buf,format,value); + trace(o,level,buf); + } + } + + void traceln(O&o, int level, const char*msg) // trace with CR & LF + { + trace(o,level,msg); trace(o,level,"\r\n"); + }
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/trace.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/trace.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,15 @@ +// trace.h - tracing +#ifndef _TRACE_H_ +#define _TRACE_H_ + +#include <mbed.h> +#include "bricks/o.h" + + void trace(O&o, int level, const char *msg); // trace a message + void trace(O&o, int level, const char*, int); // trace an int value + + void traceln(O&o, int level, const char*msg); // trace with CR & LF + + void verbose(O&o, int level = 9999); // setup verbose level + +#endif // _TRACE_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/types.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,24 @@ +// types.h - declaring some common types +// +// The type identifiers are all begining with capital letter in order to leave +// the lower capital identifiers free for 'overloaded' variable or characteristic +// identifiers. +// + +#ifndef _TYPES_H_ +#define _TYPES_H_ + +#define SIZE_OBJECTNAME 40 +#define SIZE_INIBUFFER SIZE_OBJECTNAME + + typedef uint8_t ObjectId[6]; + typedef char ObjectName[SIZE_OBJECTNAME]; // use UTF8S coded characters + typedef uint8_t Bool; + typedef uint8_t Digital; + typedef uint8_t DateTime[10]; + typedef uint8_t Buffer[10]; + + typedef uint8_t IniBuffer[SIZE_INIBUFFER]; + + +#endif // _TYPES_H_ \ No newline at end of file
diff -r 0d0ca44397dd -r 0563f1aa6a75 bricks/updated.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/updated.h Sat Oct 21 19:56:15 2017 +0000 @@ -0,0 +1,25 @@ +// updated.h - check whether a characteristic has been updated +// note: can only used within 'onWritten' callback +// +// Synopsis: +// +// See also: CHARACTERISTIC, GET, SET, ONWRITTEN +// +#ifndef _UPDATED_H_ +#define _UPDATED_H_ + +#include "ble/Gap.h" +#include "bricks/blob.h" + + inline int updated(Blob &o,GattCharacteristic &chr) // has char. been updated? + { + const GattWriteCallbackParams *p = o.pWritten; + if (!p) + return 0; // no update! + else if(p->handle == chr.getValueHandle()) + return 1; + else + return 0; + } + +#endif // _SET_H_ \ No newline at end of file