Merge branch 'develop'
This commit is contained in:
commit
9c001d2772
18 changed files with 434 additions and 140 deletions
7
CONTRIBUTING.md
Normal file
7
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Hello!
|
||||
We are an open source project of [ARM mbed](www.mbed.com). Contributions via [pull request](https://github.com/armmbed/yotta/pulls), and [bug reports](https://github.com/armmbed/yotta/issues) are welcome!
|
||||
|
||||
Please submit your pull request to the 'develop' branch of this module. Commits to develop will merge into master at the time of the next release.
|
||||
|
||||
# Contributor agreement
|
||||
For your pull request to be accepted, we will need you to agree to our [contributor agreement](http://developer.mbed.org/contributor_agreement/) to give us the necessary rights to use and distribute your contributions. (To click through the agreement create an account on mbed.com and log in.)
|
139
ble/BLE.h
139
ble/BLE.h
|
@ -21,9 +21,15 @@
|
|||
#include "Gap.h"
|
||||
#include "GattServer.h"
|
||||
#include "GattClient.h"
|
||||
#include "BLEInstanceBase.h"
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed_error.h"
|
||||
#else
|
||||
#include "mbed_error.h"
|
||||
#endif
|
||||
|
||||
/* forward declaration for the implementation class */
|
||||
class BLEInstanceBase;
|
||||
|
||||
/**
|
||||
* The base class used to abstract away BLE capable radio transceivers or SOCs,
|
||||
|
@ -32,6 +38,20 @@
|
|||
class BLE
|
||||
{
|
||||
public:
|
||||
typedef unsigned InstanceID_t; /** The type returned by BLE::getInstanceID(). */
|
||||
|
||||
/**
|
||||
* The function signature for callbacks for initialization completion.
|
||||
* @param ble
|
||||
* A reference to the BLE instance being initialized.
|
||||
* @param error
|
||||
* This captures the result of initialization. It is set to
|
||||
* BLE_ERROR_NONE if initialization completed successfully. Else
|
||||
* the error value is implementation specific.
|
||||
*
|
||||
*/
|
||||
typedef void (*InitializationCompleteCallback_t)(BLE &ble, ble_error_t error);
|
||||
|
||||
/**
|
||||
* Initialize the BLE controller. This should be called before using
|
||||
* anything else in the BLE_API.
|
||||
|
@ -42,21 +62,44 @@ public:
|
|||
* system startup. It may not be safe to call init() from global static
|
||||
* context where ordering is compiler specific and can't be guaranteed--it
|
||||
* is safe to call BLE::init() from within main().
|
||||
*
|
||||
* @param callback
|
||||
* A callback for when initialization completes for a BLE
|
||||
* instance. This is an optional parameter, if no callback is
|
||||
* setup the application can still determine the status of
|
||||
* initialization using BLE::hasInitialized() (see below).
|
||||
*
|
||||
* @return BLE_ERROR_NONE if the initialization procedure was started
|
||||
* successfully.
|
||||
*
|
||||
* @note The underlying stack must invoke the initialization completion
|
||||
* callback in response to init(). In some cases, initialization is
|
||||
* instantaneous (or blocking); if so, it is acceptable for the stack-
|
||||
* specific implementation of init() to invoke the completion callback
|
||||
* directly--i.e. within its own context.
|
||||
*
|
||||
* @note Nearly all BLE APIs would return
|
||||
* BLE_ERROR_INITIALIZATION_INCOMPLETE if used on an instance before the
|
||||
* corresponding transport is initialized.
|
||||
*/
|
||||
ble_error_t init();
|
||||
ble_error_t init(InitializationCompleteCallback_t callback = NULL);
|
||||
|
||||
/**
|
||||
* @return true if initialization has completed for the underlying BLE
|
||||
* transport.
|
||||
*
|
||||
* The application can setup a callback to signal completion of
|
||||
* initialization when using init(). Otherwise, this method can be used to
|
||||
* poll the state of initialization.
|
||||
*/
|
||||
bool hasInitialized(void) const;
|
||||
|
||||
/**
|
||||
* Purge the BLE stack of GATT and GAP state. init() must be called
|
||||
* afterwards to re-instate services and GAP state. This API offers a way to
|
||||
* repopulate the GATT database with new services and characteristics.
|
||||
*/
|
||||
ble_error_t shutdown(void) {
|
||||
clearAdvertisingPayload();
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->shutdown();
|
||||
}
|
||||
ble_error_t shutdown(void);
|
||||
|
||||
/**
|
||||
* This call allows the application to get the BLE stack version information.
|
||||
|
@ -64,81 +107,36 @@ public:
|
|||
* @return A pointer to a const string representing the version.
|
||||
* Note: The string is owned by the BLE_API.
|
||||
*/
|
||||
const char *getVersion(void) {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getVersion();
|
||||
}
|
||||
const char *getVersion(void);
|
||||
|
||||
/*
|
||||
* Accessors to GAP. Please refer to Gap.h. All GAP related functionality requires
|
||||
* going through this accessor.
|
||||
*/
|
||||
const Gap &gap() const {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGap();
|
||||
}
|
||||
Gap &gap() {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGap();
|
||||
}
|
||||
const Gap &gap() const;
|
||||
Gap &gap();
|
||||
|
||||
/*
|
||||
* Accessors to GATT Server. Please refer to GattServer.h. All GATTServer related
|
||||
* functionality requires going through this accessor.
|
||||
*/
|
||||
const GattServer& gattServer() const {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGattServer();
|
||||
}
|
||||
GattServer& gattServer() {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGattServer();
|
||||
}
|
||||
const GattServer& gattServer() const;
|
||||
GattServer& gattServer();
|
||||
|
||||
/*
|
||||
* Accessors to GATT Client. Please refer to GattClient.h. All GATTClient related
|
||||
* functionality requires going through this accessor.
|
||||
*/
|
||||
const GattClient& gattClient() const {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGattClient();
|
||||
}
|
||||
GattClient& gattClient() {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getGattClient();
|
||||
}
|
||||
const GattClient& gattClient() const;
|
||||
GattClient& gattClient();
|
||||
|
||||
/*
|
||||
* Accessors to Security Manager. Please refer to SecurityManager.h. All
|
||||
* SecurityManager related functionality requires going through this
|
||||
* accessor.
|
||||
*/
|
||||
const SecurityManager& securityManager() const {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
SecurityManager& securityManager() {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
const SecurityManager& securityManager() const;
|
||||
SecurityManager& securityManager();
|
||||
|
||||
/**
|
||||
* Yield control to the BLE stack or to other tasks waiting for events. This
|
||||
|
@ -147,15 +145,9 @@ public:
|
|||
* returning (to service the stack). This is not always interchangeable with
|
||||
* WFE().
|
||||
*/
|
||||
void waitForEvent(void) {
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
transport->waitForEvent();
|
||||
}
|
||||
void waitForEvent(void);
|
||||
|
||||
public:
|
||||
typedef unsigned InstanceID_t;
|
||||
static const InstanceID_t DEFAULT_INSTANCE = 0;
|
||||
#ifndef YOTTA_CFG_BLE_INSTANCES_COUNT
|
||||
static const InstanceID_t NUM_INSTANCES = 1;
|
||||
|
@ -190,6 +182,12 @@ public:
|
|||
*/
|
||||
BLE(InstanceID_t instanceID = DEFAULT_INSTANCE);
|
||||
|
||||
/**
|
||||
* Fetch the ID of a BLE instance. Typically there would only be the DEFAULT_INSTANCE.
|
||||
*/
|
||||
InstanceID_t getInstanceID(void) const {
|
||||
return instanceID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deprecation alert!
|
||||
|
@ -1394,6 +1392,7 @@ private:
|
|||
BLE &operator=(const BLE &);
|
||||
|
||||
private:
|
||||
InstanceID_t instanceID;
|
||||
BLEInstanceBase *transport; /* the device specific backend */
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#define __BLE_DEVICE_INSTANCE_BASE__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/* forward declarations */
|
||||
class GattServer;
|
||||
|
@ -30,17 +32,18 @@ class GattClient;
|
|||
class BLEInstanceBase
|
||||
{
|
||||
public:
|
||||
virtual ble_error_t init(void) = 0;
|
||||
virtual ble_error_t shutdown(void) = 0;
|
||||
virtual const char *getVersion(void) = 0;
|
||||
virtual Gap& getGap() = 0;
|
||||
virtual const Gap& getGap() const = 0;
|
||||
virtual GattServer& getGattServer() = 0;
|
||||
virtual const GattServer& getGattServer() const = 0;
|
||||
virtual GattClient& getGattClient() = 0;
|
||||
virtual SecurityManager& getSecurityManager() = 0;
|
||||
virtual ble_error_t init(BLE::InstanceID_t instanceID, BLE::InitializationCompleteCallback_t) = 0;
|
||||
virtual bool hasInitialized(void) const = 0;
|
||||
virtual ble_error_t shutdown(void) = 0;
|
||||
virtual const char * getVersion(void) = 0;
|
||||
virtual Gap& getGap() = 0;
|
||||
virtual const Gap& getGap() const = 0;
|
||||
virtual GattServer& getGattServer() = 0;
|
||||
virtual const GattServer& getGattServer() const = 0;
|
||||
virtual GattClient& getGattClient() = 0;
|
||||
virtual SecurityManager& getSecurityManager() = 0;
|
||||
virtual const SecurityManager& getSecurityManager() const = 0;
|
||||
virtual void waitForEvent(void) = 0;
|
||||
virtual void waitForEvent(void) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member void function
|
||||
* which takes a context.
|
||||
*/
|
||||
|
@ -34,7 +35,7 @@ public:
|
|||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointerWithContext(void (*function)(ContextType context) = NULL) :
|
||||
_function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
|
||||
_function(NULL), _caller(NULL), _next(NULL) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
|
@ -45,7 +46,7 @@ public:
|
|||
*/
|
||||
template<typename T>
|
||||
FunctionPointerWithContext(T *object, void (T::*member)(ContextType context)) :
|
||||
_function(NULL), _object(NULL), _member(), _membercaller(NULL), _next(NULL) {
|
||||
_memberFunctionAndPointer(), _caller(NULL), _next(NULL) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
|
@ -55,6 +56,7 @@ public:
|
|||
*/
|
||||
void attach(void (*function)(ContextType context) = NULL) {
|
||||
_function = function;
|
||||
_caller = functioncaller;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
|
@ -64,9 +66,9 @@ public:
|
|||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, void (T::*member)(ContextType context)) {
|
||||
_object = static_cast<void *>(object);
|
||||
memcpy(_member, (char *)&member, sizeof(member));
|
||||
_membercaller = &FunctionPointerWithContext::membercaller<T>;
|
||||
_memberFunctionAndPointer._object = static_cast<void *>(object);
|
||||
memcpy(_memberFunctionAndPointer._memberFunction, (char*) &member, sizeof(member));
|
||||
_caller = &FunctionPointerWithContext::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function; and if there are chained
|
||||
|
@ -74,11 +76,7 @@ public:
|
|||
* @Note: all chained callbacks stack up; so hopefully there won't be too
|
||||
* many FunctionPointers in a chain. */
|
||||
void call(ContextType context) {
|
||||
if (_function) {
|
||||
_function(context);
|
||||
} else if (_object && _membercaller) {
|
||||
_membercaller(_object, _member, context);
|
||||
}
|
||||
_caller(this, context);
|
||||
|
||||
/* Propagate the call to next in the chain. */
|
||||
if (_next) {
|
||||
|
@ -107,19 +105,49 @@ public:
|
|||
|
||||
private:
|
||||
template<typename T>
|
||||
static void membercaller(void *object, char *member, ContextType context) {
|
||||
T *o = static_cast<T *>(object);
|
||||
void (T::*m)(ContextType);
|
||||
memcpy((char *)&m, member, sizeof(m));
|
||||
(o->*m)(context);
|
||||
static void membercaller(pFunctionPointerWithContext_t self, ContextType context) {
|
||||
if (self->_memberFunctionAndPointer._object) {
|
||||
T *o = static_cast<T *>(self->_memberFunctionAndPointer._object);
|
||||
void (T::*m)(ContextType);
|
||||
memcpy((char*) &m, self->_memberFunctionAndPointer._memberFunction, sizeof(m));
|
||||
(o->*m)(context);
|
||||
}
|
||||
}
|
||||
|
||||
void (*_function)(ContextType context); /**< static function pointer - NULL if none attached */
|
||||
void *_object; /**< object this pointer - NULL if none attached */
|
||||
char _member[16]; /**< raw member function pointer storage - converted back by
|
||||
* registered _membercaller */
|
||||
void (*_membercaller)(void *, char *, ContextType); /**< registered membercaller function to convert back and call
|
||||
* _member on _object passing the context. */
|
||||
static void functioncaller(pFunctionPointerWithContext_t self, ContextType context) {
|
||||
if (self->_function) {
|
||||
self->_function(context);
|
||||
}
|
||||
}
|
||||
|
||||
struct MemberFunctionAndPtr {
|
||||
/*
|
||||
* forward declaration of a class and a member function to this class.
|
||||
* Because the compiler doesn't know anything about the forwarded member
|
||||
* function, it will always use the biggest size and the biggest alignment
|
||||
* that a member function can take for objects of type UndefinedMemberFunction.
|
||||
*/
|
||||
class UndefinedClass;
|
||||
typedef void (UndefinedClass::*UndefinedMemberFunction)(ContextType);
|
||||
|
||||
void* _object;
|
||||
union {
|
||||
char _memberFunction[sizeof(UndefinedMemberFunction)];
|
||||
UndefinedMemberFunction _alignment;
|
||||
};
|
||||
};
|
||||
|
||||
union {
|
||||
pvoidfcontext_t _function; /**< static function pointer - NULL if none attached */
|
||||
/**
|
||||
* object this pointer and pointer to member -
|
||||
* _memberFunctionAndPointer._object will be NULL if none attached
|
||||
*/
|
||||
MemberFunctionAndPtr _memberFunctionAndPointer;
|
||||
};
|
||||
|
||||
void (*_caller)(FunctionPointerWithContext*, ContextType);
|
||||
|
||||
pFunctionPointerWithContext_t _next; /**< Optional link to make a chain out of functionPointers; this
|
||||
* allows chaining function pointers without requiring
|
||||
* external memory to manage the chain. Also refer to
|
||||
|
|
|
@ -867,8 +867,8 @@ private:
|
|||
}
|
||||
|
||||
private:
|
||||
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &) = 0;
|
||||
virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0;
|
||||
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &advData, const GapAdvertisingData &scanResponse) = 0;
|
||||
virtual ble_error_t startAdvertising(const GapAdvertisingParams &) = 0;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,7 @@ public:
|
|||
UUID_HEART_RATE_MEASUREMENT_CHAR = 0x2A37,
|
||||
UUID_HID_CONTROL_POINT_CHAR = 0x2A4C,
|
||||
UUID_HID_INFORMATION_CHAR = 0x2A4A,
|
||||
UUID_HUMIDITY_CHAR = 0x2A6F,
|
||||
UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR = 0x2A2A,
|
||||
UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR = 0x2A36,
|
||||
UUID_INTERMEDIATE_TEMPERATURE_CHAR = 0x2A1E,
|
||||
|
@ -67,6 +68,7 @@ public:
|
|||
UUID_UNREAD_ALERT_CHAR = 0x2A45,
|
||||
UUID_NEW_ALERT_CHAR = 0x2A46,
|
||||
UUID_PNP_ID_CHAR = 0x2A50,
|
||||
UUID_PRESSURE_CHAR = 0x2A6D,
|
||||
UUID_PROTOCOL_MODE_CHAR = 0x2A4E,
|
||||
UUID_RECORD_ACCESS_CONTROL_POINT_CHAR = 0x2A52,
|
||||
UUID_REFERENCE_TIME_INFORMATION_CHAR = 0x2A14,
|
||||
|
@ -81,6 +83,7 @@ public:
|
|||
UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR = 0x2A47,
|
||||
UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR = 0x2A48,
|
||||
UUID_SYSTEM_ID_CHAR = 0x2A23,
|
||||
UUID_TEMPERATURE_CHAR = 0x2A6E,
|
||||
UUID_TEMPERATURE_MEASUREMENT_CHAR = 0x2A1C,
|
||||
UUID_TEMPERATURE_TYPE_CHAR = 0x2A1D,
|
||||
UUID_TIME_ACCURACY_CHAR = 0x2A12,
|
||||
|
@ -93,7 +96,7 @@ public:
|
|||
UUID_CSC_FEATURE_CHAR = 0x2A5C,
|
||||
UUID_CSC_MEASUREMENT_CHAR = 0x2A5B,
|
||||
UUID_RSC_FEATURE_CHAR = 0x2A54,
|
||||
UUID_RSC_MEASUREMENT_CHAR = 0x2A53,
|
||||
UUID_RSC_MEASUREMENT_CHAR = 0x2A53
|
||||
};
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
UUID_CURRENT_TIME_SERVICE = 0x1805,
|
||||
UUID_CYCLING_SPEED_AND_CADENCE = 0x1816,
|
||||
UUID_DEVICE_INFORMATION_SERVICE = 0x180A,
|
||||
UUID_ENVIRONMENTAL_SERVICE = 0x181A,
|
||||
UUID_GLUCOSE_SERVICE = 0x1808,
|
||||
UUID_HEALTH_THERMOMETER_SERVICE = 0x1809,
|
||||
UUID_HEART_RATE_SERVICE = 0x180D,
|
||||
|
|
|
@ -74,7 +74,7 @@ public:
|
|||
*
|
||||
* @note we don't yet support 32-bit shortened UUIDs.
|
||||
*/
|
||||
UUID(ShortUUIDBytes_t shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(shortUUID) {
|
||||
UUID(ShortUUIDBytes_t _shortUUID) : type(UUID_TYPE_SHORT), baseUUID(), shortUUID(_shortUUID) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
|
|
|
@ -114,16 +114,18 @@ enum {
|
|||
*/
|
||||
/**************************************************************************/
|
||||
enum ble_error_t {
|
||||
BLE_ERROR_NONE = 0, /**< No error */
|
||||
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */
|
||||
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */
|
||||
BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */
|
||||
BLE_STACK_BUSY = 5, /**< The stack is busy */
|
||||
BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */
|
||||
BLE_ERROR_NO_MEM = 7, /**< Out of Memory */
|
||||
BLE_ERROR_OPERATION_NOT_PERMITTED = 8,
|
||||
BLE_ERROR_UNSPECIFIED = 9, /**< Unknown error. */
|
||||
BLE_ERROR_NONE = 0, /**< No error */
|
||||
BLE_ERROR_BUFFER_OVERFLOW = 1, /**< The requested action would cause a buffer overflow and has been aborted */
|
||||
BLE_ERROR_NOT_IMPLEMENTED = 2, /**< Requested a feature that isn't yet implement or isn't supported by the target HW */
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE = 3, /**< One of the supplied parameters is outside the valid range */
|
||||
BLE_ERROR_INVALID_PARAM = 4, /**< One of the supplied parameters is invalid */
|
||||
BLE_STACK_BUSY = 5, /**< The stack is busy */
|
||||
BLE_ERROR_INVALID_STATE = 6, /**< Invalid state. */
|
||||
BLE_ERROR_NO_MEM = 7, /**< Out of Memory */
|
||||
BLE_ERROR_OPERATION_NOT_PERMITTED = 8,
|
||||
BLE_ERROR_INITIALIZATION_INCOMPLETE = 9,
|
||||
BLE_ERROR_ALREADY_INITIALIZED = 10,
|
||||
BLE_ERROR_UNSPECIFIED = 11, /**< Unknown error. */
|
||||
};
|
||||
|
||||
/** @brief Default MTU size. */
|
||||
|
|
|
@ -285,7 +285,7 @@ public:
|
|||
ble.setTxPower(radioPowerLevels[params.txPowerMode]);
|
||||
ble.setDeviceName(reinterpret_cast<const uint8_t *>(&DEVICE_NAME));
|
||||
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
|
||||
ble.setAdvertisingInterval(GapAdvertisingParams::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC));
|
||||
ble.setAdvertisingInterval(ADVERTISING_INTERVAL_MSEC);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -306,7 +306,7 @@ public:
|
|||
eddyServ.setTLMFrameData(params.tlmVersion, params.tlmBeaconPeriod);
|
||||
}
|
||||
if (params.uriEnabled) {
|
||||
eddyServ.setURLFrameData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriBeaconPeriod);
|
||||
eddyServ.setURLFrameEncodedData(params.advPowerLevels[params.txPowerMode], (const char *) params.uriData, params.uriDataLength, params.uriBeaconPeriod);
|
||||
}
|
||||
if (params.uidEnabled) {
|
||||
eddyServ.setUIDFrameData(params.advPowerLevels[params.txPowerMode],
|
||||
|
@ -340,7 +340,7 @@ private:
|
|||
} else if (handle == uriDataChar.getValueHandle()) {
|
||||
params.uriDataLength = writeParams->len;
|
||||
memset(params.uriData, 0x00, URI_DATA_MAX); // clear URI string
|
||||
memcpy(params.uriData, writeParams->data, params.uriDataLength); // set URI string
|
||||
memcpy(params.uriData, writeParams->data, writeParams->len); // set URI string
|
||||
params.uriEnabled = true;
|
||||
INFO("URI = %s, URILen = %d", writeParams->data, writeParams->len);
|
||||
} else if (handle == flagsChar.getValueHandle()) {
|
||||
|
|
|
@ -175,16 +175,40 @@ public:
|
|||
urlIsSet = false;
|
||||
return false;
|
||||
}
|
||||
defaultUrlPower = power;
|
||||
encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return true; // error, URL is too big
|
||||
}
|
||||
defaultUrlPower = power;
|
||||
urlAdvPeriod = urlAdvPeriodIn;
|
||||
urlIsSet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Eddystone URL Frame information.
|
||||
* @param[in] power TX Power in dB measured at 0 meters from the device.
|
||||
* @param[in] encodedUrlIn Encoded URL
|
||||
* @param[in] encodedUrlInLength Length of the encoded URL
|
||||
* @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods)
|
||||
* @return false on success, true on failure.
|
||||
*/
|
||||
bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, uint32_t urlAdvPeriodIn) {
|
||||
if (0 == urlAdvPeriodIn) {
|
||||
urlIsSet = false;
|
||||
return false;
|
||||
}
|
||||
memcpy(defaultUriData, encodedUrlIn, encodedUrlInLength);
|
||||
if (defaultUriDataLength > URI_DATA_MAX) {
|
||||
return true; // error, URL is too big
|
||||
}
|
||||
defaultUrlPower = power;
|
||||
defaultUriDataLength = encodedUrlInLength;
|
||||
urlAdvPeriod = urlAdvPeriodIn;
|
||||
urlIsSet = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct URL frame from private variables
|
||||
* @param[in/out] Data pointer to array to store constructed frame in
|
||||
|
@ -236,6 +260,10 @@ public:
|
|||
* @return number of bytes used. negative number indicates error message.
|
||||
*/
|
||||
int constructTLMFrame(uint8_t *Data, uint8_t maxSize) {
|
||||
uint32_t now = timeSinceBootTimer.read_ms();
|
||||
TlmTimeSinceBoot += (now - lastBootTimerRead) / 100;
|
||||
lastBootTimerRead = now;
|
||||
|
||||
int index = 0;
|
||||
Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry
|
||||
Data[index++] = TlmVersion; // TLM Version Number
|
||||
|
@ -291,14 +319,6 @@ public:
|
|||
TlmTimeSinceBoot = timeSinceBoot;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback function, called every 0.1s, incriments the TimeSinceBoot field in the TLM frame
|
||||
* @return nothing
|
||||
*/
|
||||
void tsbCallback(void) {
|
||||
TlmTimeSinceBoot++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update advertising data
|
||||
* @return true on success, false on failure
|
||||
|
@ -500,7 +520,8 @@ public:
|
|||
// Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset
|
||||
updateTlmPduCount(0);
|
||||
updateTlmTimeSinceBoot(0);
|
||||
timeSinceBootTick.attach(this, &EddystoneService::tsbCallback, 0.1); // incriment the TimeSinceBoot ticker every 0.1s
|
||||
lastBootTimerRead = 0;
|
||||
timeSinceBootTimer.start();
|
||||
tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod);
|
||||
DBG("attached tlmCallback every %d seconds", TlmAdvPeriod);
|
||||
}
|
||||
|
@ -519,7 +540,8 @@ private:
|
|||
BLEDevice &ble;
|
||||
uint16_t advPeriodus;
|
||||
uint8_t txPower;
|
||||
Ticker timeSinceBootTick; // counter that counts time since boot
|
||||
Timer timeSinceBootTimer;
|
||||
volatile uint32_t lastBootTimerRead;
|
||||
volatile bool advLock;
|
||||
volatile FrameTypes frameIndex;
|
||||
Timeout stopAdv;
|
||||
|
|
106
ble/services/EnvironmentalService.h
Normal file
106
ble/services/EnvironmentalService.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __BLE_ENVIRONMENTAL_SERVICE_H__
|
||||
#define __BLE_ENVIRONMENTAL_SERVICE_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class EnvironmentalService
|
||||
* @brief BLE Environmental Service. This service provides the location of the thermometer and the temperature. <br>
|
||||
* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.environmental_sensing.xml <br>
|
||||
* Temperature: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.temperature.xml <br>
|
||||
* Humidity: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.humidity.xml <br>
|
||||
* Pressure: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.pressure.xml
|
||||
*/
|
||||
class EnvironmentalService {
|
||||
public:
|
||||
typedef int16_t TemperatureType_t;
|
||||
typedef uint16_t HumidityType_t;
|
||||
typedef uint32_t PressureType_t;
|
||||
|
||||
/**
|
||||
* @brief EnvironmentalService constructor.
|
||||
* @param ble Reference to BLE device.
|
||||
* @param temperature_en Enable this characteristic.
|
||||
* @param humidity_en Enable this characteristic.
|
||||
* @param pressure_en Enable this characteristic.
|
||||
*/
|
||||
EnvironmentalService(BLE& _ble) :
|
||||
ble(_ble),
|
||||
temperatureCharacteristic(GattCharacteristic::UUID_TEMPERATURE_CHAR, &temperature),
|
||||
humidityCharacteristic(GattCharacteristic::UUID_HUMIDITY_CHAR, &humidity),
|
||||
pressureCharacteristic(GattCharacteristic::UUID_PRESSURE_CHAR, &pressure)
|
||||
{
|
||||
static bool serviceAdded = false; /* We should only ever need to add the information service once. */
|
||||
if (serviceAdded) {
|
||||
return;
|
||||
}
|
||||
|
||||
GattCharacteristic *charTable[] = { &humidityCharacteristic,
|
||||
&pressureCharacteristic,
|
||||
&temperatureCharacteristic };
|
||||
|
||||
GattService environmentalService(GattService::UUID_ENVIRONMENTAL_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.gattServer().addService(environmentalService);
|
||||
serviceAdded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update humidity characteristic.
|
||||
* @param newHumidityVal New humidity measurement.
|
||||
*/
|
||||
void updateHumidity(HumidityType_t newHumidityVal)
|
||||
{
|
||||
humidity = (HumidityType_t) (newHumidityVal * 100);
|
||||
ble.gattServer().write(humidityCharacteristic.getValueHandle(), (uint8_t *) &humidity, sizeof(HumidityType_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update pressure characteristic.
|
||||
* @param newPressureVal New pressure measurement.
|
||||
*/
|
||||
void updatePressure(PressureType_t newPressureVal)
|
||||
{
|
||||
pressure = (PressureType_t) (newPressureVal * 10);
|
||||
ble.gattServer().write(pressureCharacteristic.getValueHandle(), (uint8_t *) &pressure, sizeof(PressureType_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update temperature characteristic.
|
||||
* @param newTemperatureVal New temperature measurement.
|
||||
*/
|
||||
void updateTemperature(float newTemperatureVal)
|
||||
{
|
||||
temperature = (TemperatureType_t) (newTemperatureVal * 100);
|
||||
ble.gattServer().write(temperatureCharacteristic.getValueHandle(), (uint8_t *) &temperature, sizeof(TemperatureType_t));
|
||||
}
|
||||
|
||||
private:
|
||||
BLE& ble;
|
||||
|
||||
TemperatureType_t temperature;
|
||||
HumidityType_t humidity;
|
||||
PressureType_t pressure;
|
||||
|
||||
ReadOnlyGattCharacteristic<TemperatureType_t> temperatureCharacteristic;
|
||||
ReadOnlyGattCharacteristic<HumidityType_t> humidityCharacteristic;
|
||||
ReadOnlyGattCharacteristic<PressureType_t> pressureCharacteristic;
|
||||
};
|
||||
|
||||
#endif /* #ifndef __BLE_ENVIRONMENTAL_SERVICE_H__*/
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef __BLE_HEALTH_THERMOMETER_SERVICE_H__
|
||||
#define __BLE_HEALTH_THERMOMETER_SERVICE_H__
|
||||
|
||||
#include "BLE.h"
|
||||
#include "ble/BLE.h"
|
||||
|
||||
/**
|
||||
* @class HealthThermometerService
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef __BLE_LINK_LOSS_SERVICE_H__
|
||||
#define __BLE_LINK_LOSS_SERVICE_H__
|
||||
|
||||
#include "Gap.h"
|
||||
#include "ble/Gap.h"
|
||||
|
||||
/**
|
||||
* @class LinkLossService
|
||||
|
@ -52,11 +52,11 @@ public:
|
|||
GattCharacteristic *charTable[] = {&alertLevelChar};
|
||||
GattService linkLossService(GattService::UUID_LINK_LOSS_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
|
||||
|
||||
ble.addService(linkLossService);
|
||||
ble.gattServer().addService(linkLossService);
|
||||
serviceAdded = true;
|
||||
|
||||
ble.addToDisconnectionCallChain(this, &LinkLossService::onDisconnectionFilter);
|
||||
ble.onDataWritten(this, &LinkLossService::onDataWritten);
|
||||
ble.gap().onDisconnection(this, &LinkLossService::onDisconnectionFilter);
|
||||
ble.gattServer().onDataWritten(this, &LinkLossService::onDataWritten);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +86,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
void onDisconnectionFilter(void) {
|
||||
void onDisconnectionFilter(const Gap::DisconnectionCallbackParams_t *params) {
|
||||
if (alertLevel != NO_ALERT) {
|
||||
callback(alertLevel);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,13 @@
|
|||
#ifndef __BLE_UART_SERVICE_H__
|
||||
#define __BLE_UART_SERVICE_H__
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#include "mbed-drivers/Stream.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#include "Stream.h"
|
||||
#endif
|
||||
|
||||
#include "ble/UUID.h"
|
||||
#include "ble/BLE.h"
|
||||
|
|
|
@ -18,7 +18,12 @@
|
|||
#define SERVICES_URIBEACONCONFIGSERVICE_H_
|
||||
|
||||
#include "ble/BLE.h"
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
|
||||
extern const uint8_t UUID_URI_BEACON_SERVICE[UUID::LENGTH_OF_LONG_UUID];
|
||||
extern const uint8_t UUID_LOCK_STATE_CHAR[UUID::LENGTH_OF_LONG_UUID];
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ble",
|
||||
"version": "1.0.0",
|
||||
"version": "2.0.0",
|
||||
"description": "The BLE module offers a high level abstraction for using Bluetooth Low Energy on multiple platforms.",
|
||||
"keywords": [
|
||||
"Bluetooth",
|
||||
|
@ -26,7 +26,10 @@
|
|||
"x-nucleo-idb0xa1": "ARMmbed/ble-x-nucleo-idb0xa1"
|
||||
},
|
||||
"nrf51822": {
|
||||
"ble-nrf51822": "^1.0.0"
|
||||
"ble-nrf51822": "^2.0.0"
|
||||
},
|
||||
"cordio": {
|
||||
"ble-wicentric": "~0.0.4"
|
||||
},
|
||||
"mbed-classic": {
|
||||
"mbed-classic": "~0.0.1"
|
||||
|
|
116
source/BLE.cpp
116
source/BLE.cpp
|
@ -15,15 +15,16 @@
|
|||
*/
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
|
||||
#if defined(TARGET_OTA_ENABLED)
|
||||
#include "ble/services/DFUService.h"
|
||||
#endif
|
||||
|
||||
ble_error_t
|
||||
BLE::init()
|
||||
BLE::init(BLE::InitializationCompleteCallback_t callback)
|
||||
{
|
||||
ble_error_t err = transport->init();
|
||||
ble_error_t err = transport->init(instanceID, callback);
|
||||
if (err != BLE_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
|
@ -105,7 +106,7 @@ BLE::Instance(InstanceID_t id)
|
|||
return badSingleton;
|
||||
}
|
||||
|
||||
BLE::BLE(InstanceID_t instanceID) : transport()
|
||||
BLE::BLE(InstanceID_t instanceIDIn) : instanceID(instanceIDIn), transport()
|
||||
{
|
||||
static BLEInstanceBase *transportInstances[NUM_INSTANCES];
|
||||
|
||||
|
@ -118,3 +119,112 @@ BLE::BLE(InstanceID_t instanceID) : transport()
|
|||
transport = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool BLE::hasInitialized(void) const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->hasInitialized();
|
||||
}
|
||||
|
||||
ble_error_t BLE::shutdown(void)
|
||||
{
|
||||
clearAdvertisingPayload();
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->shutdown();
|
||||
}
|
||||
|
||||
const char *BLE::getVersion(void)
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getVersion();
|
||||
}
|
||||
|
||||
const Gap &BLE::gap() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGap();
|
||||
}
|
||||
|
||||
Gap &BLE::gap()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGap();
|
||||
}
|
||||
|
||||
const GattServer& BLE::gattServer() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattServer();
|
||||
}
|
||||
|
||||
GattServer& BLE::gattServer()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattServer();
|
||||
}
|
||||
|
||||
const GattClient& BLE::gattClient() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattClient();
|
||||
}
|
||||
|
||||
GattClient& BLE::gattClient()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getGattClient();
|
||||
}
|
||||
|
||||
const SecurityManager& BLE::securityManager() const
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
|
||||
SecurityManager& BLE::securityManager()
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
return transport->getSecurityManager();
|
||||
}
|
||||
|
||||
void BLE::waitForEvent(void)
|
||||
{
|
||||
if (!transport) {
|
||||
error("bad handle to underlying transport");
|
||||
}
|
||||
|
||||
transport->waitForEvent();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue