![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
TOF based Presence Detector
Dependencies: BLE_API X_NUCLEO_6180XA1 X_NUCLEO_IDB0XA1 mbed
Fork of BLE_HeartRate_IDB0XA1 by
Revision 29:eceecbe28088, committed 2018-08-20
- Comitter:
- hux
- Date:
- Mon Aug 20 16:43:10 2018 +0000
- Parent:
- 28:a23b16555909
- Commit message:
- made in Shanghai
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/advertise.h Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,114 @@ +// advertise.h - begin peripheral role and start advertising +// +// Synopsis: +// +// advertise(O&o); +// advertise(O&o, const char *mode, int ms = 100); +// +// payload(O&o,const char *mode) // set advertising payload +// +// Arguments: +// +// o: Blob object (to avoid name clashes) +// mode: String containing a sequence of mode characters defining both +// advertising type (upper case characters) and advertising flags +// (lower case characters), some of which have meaning, all others +// are ignored and can be used for spacing (e.g. ':', ' ', '-', ...) +// ms: Advertising interval in mili seconds (default 100 ms) +// +// Advertising Type +// +// C: ADV_CONNECTABLE_UNDIRECTED +// D: ADV_CONNECTABLE_DIRECTED +// S: ADV_SCANNABLE_UNDIRECTED +// N: ADV_NON_CONNECTABLE_UNDIRECTED +// +// Advertising Flags: +// +// l: LE Limited Discoverable Mode (value: 0x01) +// g: LE General Discoverable Mode (value: 0x02) +// n: BR/EDR Not Supported (value: 0x04) +// c: Controller: simultaneous LE & BR/EDR (value: 0x08) +// h: Host: Simultaneous LE & BR/EDR (value: 0x10) +// +// Examples 1: Start advertising in peripheral role with type 'connectable, uni- +// directed, and flags 'BR/EDR Not Supported', 'LE General Discoverable Mode' +// +// advertise(o,"C:ng",100); // start advertising @ 100 msec interval +// advertise(o,"Cng",100); // same as above +// advertise(o,"gCn",100); // same as above +// +// Examples 2: Start advertising in peripheral role with type 'connectable, +// directed, and flags 'LE Limited Discoverable Mode' +// +// advertise("D:l",100) // Connectable Directed, limited discoverable +// +// Examples 3: A typical peripheral advertising session starts with setup of +// device name, advertising name and advertising data. +// +// device(o,"Smart Button"); // setup device name +// name(o,"Smart Button #1"); // setup advertising name +// data(o,"My Home"); // setup advertising data +// advertise(o,"C:ng",100); // start advertising @ 100 msec interval +// +// Example 4: restart advertising based on pre-defined advertising payload +// +// +// See also: SERVICE +// +#ifndef _ADVERTISE_H_ +#define _ADVERTISE_H_ + +#include "bricks/blob.h" +#include "bricks/trace.h" + +#define _GADAT GapAdvertisingData +#define _GAPAR GapAdvertisingParams + + + inline void payload(O&o,const char *p) // Set advertising type and flags + { + _GAPAR::AdvertisingType_t typ = _GAPAR::ADV_CONNECTABLE_UNDIRECTED; + uint8_t mask = 0x00; + + for (;*p; p++) + { + switch (*p) + { + case 'l': mask = mask | _GADAT::LE_LIMITED_DISCOVERABLE; break; + case 'g': mask = mask | _GADAT::LE_GENERAL_DISCOVERABLE; break; + case 'n': mask = mask | _GADAT::BREDR_NOT_SUPPORTED; break; + case 'c': mask = mask | _GADAT::SIMULTANEOUS_LE_BREDR_C; break; + case 'h': mask = mask | _GADAT::SIMULTANEOUS_LE_BREDR_H; break; + + case 'C': typ = _GAPAR::ADV_CONNECTABLE_UNDIRECTED; break; + case 'D': typ = _GAPAR::ADV_CONNECTABLE_DIRECTED; break; + case 'S': typ = _GAPAR::ADV_SCANNABLE_UNDIRECTED; break; + case 'N': typ = _GAPAR::ADV_NON_CONNECTABLE_UNDIRECTED; break; + } + } + + o.gap().setAdvertisingType(typ); + o.gap().accumulateAdvertisingPayload(mask); + } + + + inline void advertise(O&o) // start advertising + { + o.gap().startAdvertising(); // start advertising + trace(o,2,"<advertising>\n"); + } + + inline void advertise(O&o, int ms) // start advertising (msec: periode) + { + o.gap().setAdvertisingInterval(ms); + advertise(o); // start advertising + } + + inline void advertise(Blob &o, const char *mode, int ms = 100) + { + payload(o,mode); // set advertising payload type & mask + advertise(o,ms); // start advertising + } + +#endif // _ADVERTISE_H_ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/blink.cpp Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,83 @@ +// blink.cpp - send a morse pattern to LED1 +// +// Function morse() is one way for running LED1 with a blinking sequence using +// a busy wait, until the sequence is completed. +// +// morse(o," x xxx x "); send one time morse sequence, interval = 0.2 +// morse(o," x xxx x ",0.5); send one time morse sequence, interval = 0.5 +// +// Function morse(o) got the additional feature to stop an ongoing timer based +// blinking sequence. +// +// The alternative is to setup an ever repeating blink sequence via LED1 using +// function blink(), which is non waiting. +// +// blink(o," x xxx x "); repeating blink sequence, interval = 0.2 +// blink(o," x xxx x ",0.5); repeating blink sequence, interval = 0.5 +// blink(o); stops blinking sequence +// + +#include "bricks/target.h" +#include "bricks/blink.h" + +#ifndef LED_INVERTED +# define LED_ON 1 +# define LED_OFF 0 +#else +# define LED_ON 0 +# define LED_OFF 1 +#endif + + static DigitalOut led(LED1); // LED1, being used for morse sequence + static Ticker ticker; // triggers periodic callbacks + static const char *pointer = 0; // 0 means morse activity disabled + static const char *sequence = 0; // next morse sequence for repeats + + + void morse(O&o,const char *pattern, double interval) + { + pointer = 0; // disable ticker based blinking + sequence = 0; // set also empty sequence + + for (; *pattern; pattern++) + { + led = (*pattern == ' ') ? LED_OFF : LED_ON; + wait(interval); // busy waiting for interval time + } + } + +// callback for LED1 ticker controlled blinking + + static void cbBlinker(void) // blinker callback + { + if (pointer != 0) + { + if (*pointer == 0) + { + pointer = sequence; // reset pointer to followup sequence + } + + if (*pointer) + { + led = (*pointer++ == ' ') ? LED_OFF : LED_ON; + } + } + } + + void blink(O&o,const char *pattern, const char* next, double interval) + { + pointer = 0; // stop current activities + led = LED_OFF; // reset led with LED_OFF + + sequence = next; // init morse sequence + + ticker.attach(cbBlinker,interval);// next LED state after every interval + pointer = pattern; // enable callback activty + } + + void blink(O&o, const char *pattern, double interval) + { + blink(o,pattern,pattern,interval); + } + + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/callback.cpp Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,83 @@ +// callback.cpp - deal with callbacks + +#include "bricks/blob.h" +#include "bricks/callback.h" +#include "bricks/trace.h" + +//============================================================================== +// Setup Data Written Callback +//============================================================================== + + static void (*cbWritten)(O&o) = 0; // where we have to follow up + + // default onDataWritten callback + + static void dfWritten(const GattWriteCallbackParams *params) + { + O o; // setup a blob + o.pWritten = params; // store to provide access + + trace(o,2,"<data written>\n"); + + if (cbWritten) + (*cbWritten)(o); // user callback follow-up + } + + + void onWritten(O&o, void (*fptr)(O&o)) // setup data written callback + { + cbWritten = fptr; // remember function to follow-up + o.gattServer().onDataWritten(dfWritten);// actual calback setup in GATT + } + +//============================================================================== +// Setup Connection Callback +//============================================================================== + + static void (*cbConnect)(Blob&) = 0;// where we have to follow up + + // default connection callback + + static void dfConnect(const Gap::ConnectionCallbackParams_t *params) + { + O o; // setup a blob object + o.pConnect = params; // store to provide access + + trace(o,2,"<connect>\n"); + + if (cbConnect) + (*cbConnect)(o); // user callback follow-up + } + + void onConnect(O&o,void(*fptr)(O&)) // setup connection callback + { + cbConnect = fptr; // remember function to follow-up + o.gap().onConnection(dfConnect); // actual callback setup in GAP + } + +//============================================================================== +// Setup Disconnection Callback +//============================================================================== + + static void (*cbDisconnect)(O&o) = 0; // where we have to follow up + + // default disconnection callback + + static void dfDisconnect(const Gap::DisconnectionCallbackParams_t *params) + { + Blob o; // setup a blob + o.pDisconnect = params; // store to provide access + + trace(o,2,"<disconnected>\n"); + + if (cbDisconnect) + (*cbDisconnect)(o); // user callback follow-up + } + + void onDisconnect(O&o,void(*fptr)(O&o)) // setup disconnection callback + { + cbDisconnect = fptr; // remember function to follow-up + + o.gap().onDisconnection(dfDisconnect);// actualcallback setup in GAP + } +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/callback.h Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,13 @@ +// callback.h - deal with callbacks +// +// +#ifndef _CALLBACK_H_ +#define _CALLBACK_H_ + +#include "bricks/o.h" + + void onConnect (O&o, void(*fptr)(O&o)); // setup connection callback + void onDisconnect(O&o, void(*fptr)(O&o)); // setup disconnect callback + void onWritten (O&o, void (*fptr)(O&)); // setup data written callback + +#endif // _CALLBACK_H_ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/characteristic.cpp Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,7 @@ +// characteristic.cpp - an easy to use overloaded characteristic class + +#include "bricks/characteristic.h" + + IniBuffer characteristicInidata; // to initialize a characteristic + +// eof \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/characteristic.h Mon Aug 20 16:43:10 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/collection.h Mon Aug 20 16:43:10 2018 +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_
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/get.h Mon Aug 20 16:43:10 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/init.cpp Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,55 @@ +// init.cpp - initialize BLE system + +#include "bricks/init.h" +#include "bricks/blink.h" +#include "bricks/trace.h" + + static void (*cbSetup)(O&o) = 0; // setup callback + static void (*cbError)(O&o) = 0; // error callback + + static void cbDefaultError(O&o) // default error handler + { + blinkError(o); // 'error' blink sequence + } + + static void initComplete(BLE::InitializationCompleteCallbackContext *params) + { + Blob o; // setup a blob + o.pComplete = params; // store to provide access + + // params->error = (ble_error_t)((int)BLE_ERROR_NONE+1); // uncomment for debug + + trace(o,2,"<initialized>\n"); + + if (params->error != BLE_ERROR_NONE) + { + trace(o,0,"error\n"); + if (cbError) + (*cbError)(o); // handle error in follow-up + + return; + } + + // Ensure that it is the default instance of BLE + + if(o.getInstanceID() != BLE::DEFAULT_INSTANCE) + { + return; + } + + (*cbSetup)(o); // followup with setup + } + + + void init(O&o, void (*scb)(O&o),void (*ecb)(O&o)) // init BLE system + { + cbSetup = scb; // store setup callback + cbError = ecb; // store error callback + o.init(initComplete); + } + + + void init(O&o, void (*scb)(O&o)) // initialize BLE system + { + init(o,scb,cbDefaultError); // continue with default error callback + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/init.h Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,74 @@ +// init.h - initialize BLE system +// +// Synopsis: +// +// void init(Blob &o, void (*scb)(Blob&),void (*ecb)(Blob&)) // init BLE +// void init(Blob &o, void (*scb)(Blob&)) // init BLE +// +// Arguments: +// +// o: Blob object (to avoid name clashes) +// scb: setup callback +// ecb: error callback +// +// Description: +// +// Initialize BLE system, providing a setup callback and optionally an error +// callback. The actual initializing happens in the setup callback. If an +// error occurs during initializin, the error callback will be consulted. If +// no error callback is provided an implicit error callback will be called. +// +// Example 1: simple BLE system setup +// +// void cbSetup(Blob &o) +// { +// device(o,"IoT node"); // setup device name +// name(o,"Node #1"); // setup advertising name +// advertise("C:ng"); // start advertising +// } +// +// main(void) +// { +// Blob o; // our Blob object +// init(o,cbSetup); // init BLE base layer, always do first +// while (true) // Infinite loop waiting for BLE events +// sleep(o); // low energy waiting +// } +// +// Example 2: Provide also error handler +// +// void cbError(Blob &o) +// { +// trace(0,"init error!"); +// } +// +// void cbSetup(Blob &o) +// { +// device(o,"IoT node"); // setup device name +// name(o,"Node #1"); // setup advertising name +// advertise("C:ng"); // start advertising +// } +// +// main(void) +// { +// Blob o; // our Blob object +// init(o,cbSetup,cbError); // init BLE base layer, always do first +// while (true) // Infinite loop waiting for BLE events +// sleep(o); // low energy waiting +// } +// +// See also: BLOB, INIT +// +#ifndef _INIT_H_ +#define _INIT_H_ + +#include "bricks/o.h" + +//============================================================================== +// Initializing +//============================================================================== + + void init(O&o, void (*scb)(O&o),void (*ecb)(O&o)); // init BLE + void init(O&o, void (*scb)(O&o)); // init BLE system + +#endif // _INIT_H_ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/o.h Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,9 @@ +// o.h - dealing with THE object 'O' +#ifndef _O_H_ +#define _O_H_ + +#define O Blob + +#include "bricks/blob.h" + +#endif // _O_H_ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/print.h Mon Aug 20 16:43:10 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/service.h Mon Aug 20 16:43:10 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/set.h Mon Aug 20 16:43:10 2018 +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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/sleep.h Mon Aug 20 16:43:10 2018 +0000 @@ -0,0 +1,50 @@ +// sleep.h - sleep for some time +// +// Synopsis: +// +// void sleep(Blob &o) // low energy sleep for some mili seconds +// void sleep(Blob &o, int ms) // low enery sleep, handle BLE events +// +// Arguments: +// +// o: Blob object (to avoid name clashes) +// msec: sleeping interval in miliseconds +// +// Description: +// +// +// Example 1: main function body to setup BLE functionality +// +// main(void) +// { +// Blob o; // our Blob object +// init(o,onSetup,onError); // init BLE base layer, always do first +// +// while (true) // Infinite loop waiting for BLE events +// sleep(o); // low power waiting for BLE events +// } +// +// Example 2: Turn LED on for 2 seconds miliseconds +// +// led = 1; // turn LED on +// sleep(o,2000); // wait 2000 miliseconds (in LE mode) +// led = 0; // turn LED off +// +// See also: BLOB, INIT +// +#ifndef _SLEEP_H_ +#define _SLEEP_H_ + +#include "bricks/blob.h" + + inline void sleep(Blob &o) // low power waiting for BLE events + { + o.waitForEvent(); // low power waiting for BLE events + } + + inline void sleep(Blob &o, int ms) // low power waiting for BLE events + { + wait_ms(ms); // low power waiting for some miliseconds + } + +#endif // _SLEEP_H_ \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bricks/trace.cpp Mon Aug 20 16:43:10 2018 +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"); + }