Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API LIS3DH mbed nRF51822 BMC050 nRF51_LowPwr nRF51_Vdd
Fork of BLE_EddystoneBeacon_Service by
Revision 15:af8c24f34a9f, committed 2015-07-20
- Comitter:
- mbedAustin
- Date:
- Mon Jul 20 19:31:40 2015 +0000
- Parent:
- 14:5a2a104a21a8
- Child:
- 16:a7d07ea94b31
- Commit message:
- [[Testing]] - confirmed all packets are being encoded correctly. Currently using Ticker to switch payloads. Need to add stuff to BLE library to enable callbacks to object functions.;
Changed in this revision
| ZipBeaconConfigService.h | Show annotated file Show diff for this revision Revisions of this file |
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/ZipBeaconConfigService.h Mon Jul 20 04:29:07 2015 +0000
+++ b/ZipBeaconConfigService.h Mon Jul 20 19:31:40 2015 +0000
@@ -43,8 +43,9 @@
* See http://uribeacon.org
*
*/
-class ZipBeaconConfigService {
- public:
+class ZipBeaconConfigService
+{
+public:
/**
* @brief Transmission Power Modes for UriBeacon
*/
@@ -60,12 +61,13 @@
typedef uint8_t Lock_t[16]; /* 128 bits */
typedef int8_t PowerLevels_t[NUM_POWER_MODES];
- #define EDDYSTONE_MAX_FRAMETYPE 3
+ // There are currently 3 subframes defined, URI, UID, and TLM
+#define EDDYSTONE_MAX_FRAMETYPE 3
void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
uint8_t frameIndex;
static const int URI_DATA_MAX = 18;
typedef uint8_t UriData_t[URI_DATA_MAX];
-
+
// UID Frame Type subfields
static const int UID_NAMESPACEID_SIZE = 10;
typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
@@ -76,7 +78,7 @@
static const uint8_t FRAME_TYPE_UID = 0x00;
static const uint8_t FRAME_TYPE_URL = 0x10;
static const uint8_t FRAME_TYPE_TLM = 0x20;
-
+
static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
@@ -92,7 +94,7 @@
UIDNamespaceID_t uidNamespaceID; // UUID type, Namespace ID, 10B
UIDInstanceID_t uidInstanceID; // UUID type, Instance ID, 6B
};
-
+
/**
* @param[ref] ble
* BLEDevice object for the underlying controller.
@@ -179,8 +181,7 @@
/* Start out by advertising the configService for a limited time after
* startup; and switch to the normal non-connectible beacon functionality
* afterwards. */
- void setupZipBeaconConfigAdvertisements()
- {
+ void setupZipBeaconConfigAdvertisements() {
const char DEVICE_NAME[] = "eddystone Config";
ble.clearAdvertisingPayload();
@@ -205,59 +206,56 @@
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADVERTISING_INTERVAL_MSEC));
}
-
+
/*
- * Set Eddystone UID Frame information.
+ * Set Eddystone UID Frame information.
* @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB.
* @param namespaceID 10B namespace ID
* @param instanceID 6B instance ID
- * @param RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
+ * @param RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
*
*/
- void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, uint16_t RFU = 0x00)
- {
+ void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, uint16_t RFU = 0x0000) {
defaultUidPower = power;
memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
- uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesnt really matter yet.
+ uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesnt really matter yet.
return;
}
-
+
/*
* Construct UID frame from private variables
* @param[in/out] Data pointer to array to store constructed frame in
* @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
- * @return number of bytes used. negative number indicates error message.
+ * @return number of bytes used. negative number indicates error message.
*/
- int constructUIDFrame(uint8_t * Data, uint8_t maxSize)
- {
- if(maxSize < FRAME_SIZE_UID){
- return -1; // not enough space to encode UIDframe in advertising packet.
+ int constructUIDFrame(uint8_t * Data, uint8_t maxSize) {
+ if(maxSize < FRAME_SIZE_UID) {
+ return -1; // not enough space to encode UIDframe in advertising packet.
}
int index = 0;
Data[index++] = FRAME_TYPE_UID; // 1B Type
Data[index++] = defaultUidPower; // 1B Power @ 0meter
- for(int x = 0; x < UID_NAMESPACEID_SIZE; x++){ // 10B Namespce ID
+ for(int x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespce ID
Data[index++] = defaultUidNamespaceID[x];
- }
- for(int x = 0; x< UID_INSTANCEID_SIZE; x++){ // 6B Instance ID
+ }
+ for(int x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID
Data[index++] = defaultUidInstanceID[x];
- }
- if(0x00 != uidRFU){ // 2B RFU, include if non-zero, otherwise ignore
+ }
+ if(0x00 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore
Data[index++] = (uint8_t)(uidRFU >> 8);
Data[index++] = (uint8_t)uidRFU;
}
return index;
}
-
+
/*
- * Set Eddystone URL Frame information.
+ * Set Eddystone URL Frame information.
* @param[in] power TX Power in dB measured at 0 meters from the device.
- * @param url URL to encode
+ * @param url URL to encode
* @return false on success, true on failure.
*/
- bool setURLFrameData(int8_t power, const char * url)
- {
+ bool setURLFrameData(int8_t power, const char * url) {
defaultUrlPower = power;
encodeURI(url, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
if (defaultUriDataLength > URI_DATA_MAX) {
@@ -265,53 +263,50 @@
}
return false;
}
-
+
/*
* Construct URL frame from private variables
* @param[in/out] Data pointer to array to store constructed frame in
* @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
- * @return number of bytes used. negative number indicates error message.
+ * @return number of bytes used. negative number indicates error message.
*/
- int constructURLFrame(uint8_t * Data, uint8_t maxSize)
- {
- if(maxSize < (2 + defaultUriDataLength)){
- return -1; // not enough space to encode URL frame in advertising packet.
+ int constructURLFrame(uint8_t * Data, uint8_t maxSize) {
+ if(maxSize < (2 + defaultUriDataLength)) {
+ return -1; // not enough space to encode URL frame in advertising packet.
}
int index = 0;
Data[index++] = FRAME_TYPE_URL; // 1B Type
- Data[index++] = defaultUrlPower; // 1B TX Power
- for(int x = 0; x < defaultUriDataLength; x++){ // 18B of URL Prefix + encoded URL
+ Data[index++] = params.txPowerMode; // 1B TX Power
+ for(int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL
Data[index++] = defaultUriData[x];
}
- return index;
+ return index;
}
-
+
/*
- * Set Eddystone TLM Frame information.
+ * Set Eddystone TLM Frame information.
* @param[in] Version of the TLM beacon data format
* @param batteryVoltage in milivolts
* @param beaconTemp in 8.8 floating point notation
*
*/
- void setTLMFrameData(uint8_t version, uint16_t batteryVoltage, uint16_t beaconTemp, uint32_t pduCount = 0, uint32_t timeSinceBoot = 0)
- {
+ void setTLMFrameData(uint8_t version, uint16_t batteryVoltage, uint16_t beaconTemp, uint32_t pduCount = 0, uint32_t timeSinceBoot = 0) {
TlmVersion = version;
TlmBatteryVoltage = batteryVoltage;
TlmBeaconTemp = beaconTemp;
TlmPduCount = pduCount; // reset
TlmTimeSinceBoot = timeSinceBoot; // reset
- return;
+ return;
}
-
+
/*
* Construct TLM frame from private variables
* @param[in/out] Data pointer to array to store constructed frame in
* @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
- * @return number of bytes used. negative number indicates error message.
+ * @return number of bytes used. negative number indicates error message.
*/
- int constructTLMFrame(uint8_t * Data, uint8_t maxSize)
- {
- if(maxSize < FRAME_SIZE_TLM){ // error, not enough space to add TLM frame. 14B, every time
+ int constructTLMFrame(uint8_t * Data, uint8_t maxSize) {
+ if(maxSize < FRAME_SIZE_TLM) { // error, not enough space to add TLM frame. 14B, every time
return -1;
}
int index = 0;
@@ -329,93 +324,102 @@
Data[index++] = (uint8_t)(TlmTimeSinceBoot>>8); // Time Since Boot [1]
Data[index++] = (uint8_t)(TlmTimeSinceBoot>>16); // Time Since Boot [2]
Data[index++] = (uint8_t)(TlmTimeSinceBoot>>24); // Time Since Boot [3]
-
+
return index;
}
-
+
/*
* Update the TLM frame battery voltage value
* @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV)
* @return nothing
*/
- void updateTlmBatteryVoltage(uint16_t voltagemv){
+ void updateTlmBatteryVoltage(uint16_t voltagemv) {
TlmBatteryVoltage = voltagemv;
- return;
+ return;
}
-
+
/*
- * Update the TLM frame beacon temperature
+ * Update the TLM frame beacon temperature
* @param[in] temp Temperature of beacon (in 8.8fpn)
* @return nothing
*/
- void updateTlmBeaconTemp(uint16_t temp){
+ void updateTlmBeaconTemp(uint16_t temp) {
TlmBeaconTemp = temp;
- return;
+ return;
}
-
+
/*
* Update the TLM frame PDU Count field
* @param[in] pduCount Number of Advertisiting frames sent since powerup
* @return nothing
*/
- void updateTlmPduCount(uint32_t pduCount){
+ void updateTlmPduCount(uint32_t pduCount) {
TlmPduCount = pduCount;
- return;
+ return;
}
-
+
/*
* Update the TLM frame Time since boot in 0.1s incriments
* @param[in] timeSinceBoot Time since boot in 0.1s incriments
* @return nothing
*/
- void updateTlmTimeSinceBoot(uint32_t timeSinceBoot){
+ void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) {
TlmTimeSinceBoot = timeSinceBoot;
- return;
+ return;
}
-
+
/*
* Callback from onRadioNotification(), used to update the PDUCounter and maybe other stuff eventually?
*
*
*/
- void pduCountCallback(){
+ //void radioNotificationCallback(bool radioActive){
+ void radioNotificationCallback(void) {
// Update Time and PDUCount
TlmPduCount++;
- TlmTimeSinceBoot += 10;
-
+ TlmTimeSinceBoot++;
+
// Every 1 second switch the frame types
- if((TlmPduCount % 10) == 1){
+ if((TlmPduCount % 10) == 1) {
frameIndex = frameIndex % EDDYSTONE_MAX_FRAMETYPE;
uint8_t serviceData[SERVICE_DATA_MAX];
unsigned serviceDataLen = 0;
//switch payloads
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
- switch(frameIndex){
+ switch(frameIndex) {
case 0:
- constructTLMFrame(serviceData+serviceDataLen,20);
+ printf("constructing TLM Frame: ");
+ serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,20);
break;
case 1:
- constructURLFrame(serviceData+serviceDataLen,20);
+ printf("constructing URL Frame: ");
+ serviceDataLen += constructURLFrame(serviceData+serviceDataLen,20);
break;
case 2:
- constructUIDFrame(serviceData+serviceDataLen,20);
+ printf("constructing UID Frame: ");
+ serviceDataLen += constructUIDFrame(serviceData+serviceDataLen,20);
break;
- }
+ }
ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
+ for(int x = 0; x<serviceDataLen; x++) {
+ printf("%2.2x:",serviceData[x]);
+ }
+ printf("\r\n");
}
//TODO: add bit to keep timer / update time
frameIndex++;
- return;
+ return;
}
/* Helper function to switch to the non-connectible normal mode for ZipBeacon. This gets called after a timeout. */
- void setupZipBeaconAdvertisements()
- {
+ void setupZipBeaconAdvertisements() {
+ printf("Switching Config -> adv\r\n");
uint8_t serviceData[SERVICE_DATA_MAX];
unsigned serviceDataLen = 0;
// Initialize Frame transition
frameIndex = 0;
+ uidRFU = 0;
/* Reinitialize the BLE stack. This will clear away the existing services and advertising state. */
ble.shutdown();
@@ -438,12 +442,12 @@
ble.setAdvertisingInterval(beaconPeriod);
ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE));
-
+
setTLMFrameData(0x00,22,33,0,0); // Initialize TLM Data, for testing, remove for release
updateTlmPduCount(0);
updateTlmTimeSinceBoot(0);
-
- // Construct TLM Frame in initial advertising.
+
+ // Construct TLM Frame in initial advertising.
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
constructTLMFrame(serviceData+serviceDataLen,20);
@@ -454,12 +458,13 @@
// }
// attach callback to count number of sent packets
- //TODO: ble.gap().onRadioNotification(pduCountCallback);
+ //ble.gap().onRadioNotification(this,&ZipBeaconConfigService::radioNotificationCallback);
ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
- //callbackTick.attach(&pduCountCallback,2.0); // switch services every 2 seconds
+ callbackTick.attach(this,&ZipBeaconConfigService::radioNotificationCallback, 0.1); // switch services every 2 seconds
+ //callbackTick.attach(stupidWrapperFn,2.0);
}
- private:
+private:
// True if the lock bits are non-zero
bool isLocked() {
Lock_t testLock;
@@ -548,7 +553,7 @@
reinterpret_cast<uint8_t *>(params.advPowerLevels), sizeof(PowerLevels_t));
}
- private:
+private:
void lockAuthorizationCallback(GattWriteAuthCallbackParams *authParams) {
if (lockedState) {
authParams->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INSUF_AUTHORIZATION;
@@ -629,7 +634,7 @@
uint8_t lockedState;
bool initSucceeded;
uint8_t resetFlag;
-
+
// Private Variables for Telemetry Data
uint8_t TlmVersion;
volatile uint16_t TlmBatteryVoltage;
@@ -647,7 +652,7 @@
ReadWriteGattCharacteristic<uint16_t> beaconPeriodChar;
WriteOnlyGattCharacteristic<uint8_t> resetChar;
- public:
+public:
/*
* Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
*/
--- a/main.cpp Mon Jul 20 04:29:07 2015 +0000
+++ b/main.cpp Mon Jul 20 19:31:40 2015 +0000
@@ -23,7 +23,7 @@
BLE ble;
ZipBeaconConfigService *zipBeaconConfig;
-InterruptIn button(p17);
+//InterruptIn button(p17);
/**
* URIBeaconConfig service can operate in two modes: a configuration mode which
@@ -34,14 +34,14 @@
*
* The following help with this switch.
*/
-static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 60; // Duration after power-on that config service is available.
+static const int CONFIG_ADVERTISEMENT_TIMEOUT_SECONDS = 5; // Duration after power-on that config service is available.
Ticker configAdvertisementTimeoutTicker;
//
// Have to use this to add a interrupt, because C++ is stupid.
//
void stupidWrapperFn(){
- zipBeaconConfig->pduCountCallback();
+ zipBeaconConfig->radioNotificationCallback();
}
/**
@@ -56,6 +56,7 @@
ble.gap().startAdvertising();
configAdvertisementTimeoutTicker.detach(); /* disable the callback from the timeout Ticker. */
+ printf("removing config service\r\n");
}
}
@@ -65,10 +66,12 @@
void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
{
ble.gap().startAdvertising();
+ printf("disconnect CB\r\n");
}
int main(void)
{
+ printf("Starting Example\r\n");
ble.init();
ble.gap().onDisconnection(disconnectionCallback);
@@ -84,7 +87,7 @@
/* Initialize a zipBeaconConfig service providing config params, default URI, and power levels. */
static ZipBeaconConfigService::PowerLevels_t defaultAdvPowerLevels = {-20, -4, 0, 10}; // Values for ADV packets related to firmware levels
- zipBeaconConfig = new ZipBeaconConfigService(ble, params, !fetchedFromPersistentStorage, "http://uribeacon.org", defaultAdvPowerLevels);
+ zipBeaconConfig = new ZipBeaconConfigService(ble, params, !fetchedFromPersistentStorage, "http://mbed.org", defaultAdvPowerLevels);
if (!zipBeaconConfig->configuredSuccessfully()) {
error("failed to accommodate URI");
}
@@ -96,8 +99,8 @@
ble.gap().startAdvertising(); /* Set the whole thing in motion. After this call a GAP central can scan the zipBeaconConfig
* service. This can then be switched to the normal URIBeacon functionality after a timeout. */
-
- button.rise(&stupidWrapperFn);
+ printf("Running...\r\n");
+ //button.rise(&stupidWrapperFn);
while (true) {
ble.waitForEvent();
}
