Scott Jenson / Mbed 2 deprecated BLE_EddystoneBeaconConfigService_Button

Dependencies:   BLE_API_EddystoneConfigService_2 mbed nRF51822

Fork of BLE_EddystoneBeaconConfigService_3 by URIBeacon

Committer:
mbedAustin
Date:
Fri Jul 24 03:36:45 2015 +0000
Revision:
29:dfb7fb5a971b
Parent:
28:af37cebcb583
Child:
30:6c2db8bf5b17
[[Working]] Eddystone beacon working with URI, UID and TLM packets being sent correctly.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedAustin 26:2896fbdd0450 1 /* mbed Microcontroller Library
mbedAustin 26:2896fbdd0450 2 * Copyright (c) 2006-2013 ARM Limited
mbedAustin 26:2896fbdd0450 3 *
mbedAustin 26:2896fbdd0450 4 * Licensed under the Apache License, Version 2.0 (the "License");
mbedAustin 26:2896fbdd0450 5 * you may not use this file except in compliance with the License.
mbedAustin 26:2896fbdd0450 6 * You may obtain a copy of the License at
mbedAustin 26:2896fbdd0450 7 *
mbedAustin 26:2896fbdd0450 8 * http://www.apache.org/licenses/LICENSE-2.0
mbedAustin 26:2896fbdd0450 9 *
mbedAustin 26:2896fbdd0450 10 * Unless required by applicable law or agreed to in writing, software
mbedAustin 26:2896fbdd0450 11 * distributed under the License is distributed on an "AS IS" BASIS,
mbedAustin 26:2896fbdd0450 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbedAustin 26:2896fbdd0450 13 * See the License for the specific language governing permissions and
mbedAustin 26:2896fbdd0450 14 * limitations under the License.
mbedAustin 26:2896fbdd0450 15 */
mbedAustin 26:2896fbdd0450 16
mbedAustin 26:2896fbdd0450 17 #ifndef SERVICES_EDDYSTONEBEACON_H_
mbedAustin 26:2896fbdd0450 18 #define SERVICES_EDDYSTONEBEACON_H_
mbedAustin 26:2896fbdd0450 19
mbedAustin 26:2896fbdd0450 20 #include "ble/BLE.h"
mbedAustin 26:2896fbdd0450 21 #include "mbed.h"
mbedAustin 26:2896fbdd0450 22
mbedAustin 26:2896fbdd0450 23 static const uint8_t BEACON_EDDYSTONE[] = {0xAA, 0xFE};
mbedAustin 26:2896fbdd0450 24
mbedAustin 26:2896fbdd0450 25 //Debug is disabled by default
mbedAustin 28:af37cebcb583 26 #if 1
mbedAustin 26:2896fbdd0450 27 #define DBG(x, ...) printf("[EddyStone: DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
mbedAustin 26:2896fbdd0450 28 #define WARN(x, ...) printf("[EddyStone: WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
mbedAustin 26:2896fbdd0450 29 #define ERR(x, ...) printf("[EddyStone: ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
mbedAustin 29:dfb7fb5a971b 30 #define INFO(x, ...) printf("[EddyStone: INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__);
mbedAustin 26:2896fbdd0450 31 #else
mbedAustin 26:2896fbdd0450 32 #define DBG(x, ...) //wait_us(10);
mbedAustin 26:2896fbdd0450 33 #define WARN(x, ...) //wait_us(10);
mbedAustin 26:2896fbdd0450 34 #define ERR(x, ...)
mbedAustin 29:dfb7fb5a971b 35 #define INFO(x, ...)
mbedAustin 26:2896fbdd0450 36 #endif
mbedAustin 26:2896fbdd0450 37
mbedAustin 26:2896fbdd0450 38 /**
mbedAustin 26:2896fbdd0450 39 * @class Eddystone
mbedAustin 26:2896fbdd0450 40 * @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags.
mbedAustin 26:2896fbdd0450 41 * See https://github.com/google/eddystone
mbedAustin 26:2896fbdd0450 42 *
mbedAustin 26:2896fbdd0450 43 */
mbedAustin 28:af37cebcb583 44 class EddystoneService
mbedAustin 26:2896fbdd0450 45 {
mbedAustin 26:2896fbdd0450 46 public:
mbedAustin 26:2896fbdd0450 47 /**
mbedAustin 26:2896fbdd0450 48 * @brief Transmission Power Modes for UriBeacon
mbedAustin 26:2896fbdd0450 49 */
mbedAustin 26:2896fbdd0450 50
mbedAustin 26:2896fbdd0450 51 static const int ADVERTISING_INTERVAL_MSEC = 1000; // Advertising interval for config service.
mbedAustin 26:2896fbdd0450 52 static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets
mbedAustin 26:2896fbdd0450 53
mbedAustin 26:2896fbdd0450 54 // There are currently 3 subframes defined, URI, UID, and TLM
mbedAustin 26:2896fbdd0450 55 #define EDDYSTONE_MAX_FRAMETYPE 3
mbedAustin 26:2896fbdd0450 56 void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
mbedAustin 26:2896fbdd0450 57 uint8_t frameIndex;
mbedAustin 26:2896fbdd0450 58 static const int URI_DATA_MAX = 18;
mbedAustin 26:2896fbdd0450 59 typedef uint8_t UriData_t[URI_DATA_MAX];
mbedAustin 26:2896fbdd0450 60
mbedAustin 26:2896fbdd0450 61 // UID Frame Type subfields
mbedAustin 26:2896fbdd0450 62 static const int UID_NAMESPACEID_SIZE = 10;
mbedAustin 26:2896fbdd0450 63 typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
mbedAustin 26:2896fbdd0450 64 static const int UID_INSTANCEID_SIZE = 6;
mbedAustin 26:2896fbdd0450 65 typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
mbedAustin 26:2896fbdd0450 66
mbedAustin 26:2896fbdd0450 67 // Eddystone Frame Type ID
mbedAustin 26:2896fbdd0450 68 static const uint8_t FRAME_TYPE_UID = 0x00;
mbedAustin 26:2896fbdd0450 69 static const uint8_t FRAME_TYPE_URL = 0x10;
mbedAustin 26:2896fbdd0450 70 static const uint8_t FRAME_TYPE_TLM = 0x20;
mbedAustin 26:2896fbdd0450 71
mbedAustin 26:2896fbdd0450 72 static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
mbedAustin 26:2896fbdd0450 73 static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
mbedAustin 26:2896fbdd0450 74
mbedAustin 26:2896fbdd0450 75 /*
mbedAustin 26:2896fbdd0450 76 * Set Eddystone UID Frame information.
mbedAustin 26:2896fbdd0450 77 * @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB.
mbedAustin 26:2896fbdd0450 78 * @param namespaceID 10B namespace ID
mbedAustin 26:2896fbdd0450 79 * @param instanceID 6B instance ID
mbedAustin 26:2896fbdd0450 80 * @param RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
mbedAustin 26:2896fbdd0450 81 *
mbedAustin 26:2896fbdd0450 82 */
mbedAustin 26:2896fbdd0450 83 void setUIDFrameData(int8_t power, UIDNamespaceID_t namespaceID, UIDInstanceID_t instanceID, uint16_t RFU = 0x0000) {
mbedAustin 26:2896fbdd0450 84 if(power > 20) {
mbedAustin 26:2896fbdd0450 85 power = 20;
mbedAustin 26:2896fbdd0450 86 }
mbedAustin 26:2896fbdd0450 87 if(power < -100) {
mbedAustin 26:2896fbdd0450 88 power = -100;
mbedAustin 26:2896fbdd0450 89 }
mbedAustin 26:2896fbdd0450 90 defaultUidPower = power;
mbedAustin 26:2896fbdd0450 91 memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
mbedAustin 26:2896fbdd0450 92 memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
mbedAustin 26:2896fbdd0450 93 uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesnt really matter yet.
mbedAustin 26:2896fbdd0450 94 return;
mbedAustin 26:2896fbdd0450 95 }
mbedAustin 26:2896fbdd0450 96
mbedAustin 26:2896fbdd0450 97 /*
mbedAustin 26:2896fbdd0450 98 * Construct UID frame from private variables
mbedAustin 26:2896fbdd0450 99 * @param[in/out] Data pointer to array to store constructed frame in
mbedAustin 26:2896fbdd0450 100 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
mbedAustin 26:2896fbdd0450 101 * @return number of bytes used. negative number indicates error message.
mbedAustin 26:2896fbdd0450 102 */
mbedAustin 26:2896fbdd0450 103 int constructUIDFrame(uint8_t * Data, uint8_t maxSize) {
mbedAustin 26:2896fbdd0450 104
mbedAustin 26:2896fbdd0450 105 int index = 0;
mbedAustin 26:2896fbdd0450 106 Data[index++] = FRAME_TYPE_UID; // 1B Type
mbedAustin 26:2896fbdd0450 107 if(defaultUidPower > 20) {
mbedAustin 26:2896fbdd0450 108 defaultUidPower = 20; // enforce range of vaild values.
mbedAustin 26:2896fbdd0450 109 }
mbedAustin 26:2896fbdd0450 110 if(defaultUidPower < -100) {
mbedAustin 26:2896fbdd0450 111 defaultUidPower = -100;
mbedAustin 26:2896fbdd0450 112 }
mbedAustin 26:2896fbdd0450 113 Data[index++] = defaultUidPower; // 1B Power @ 0meter
mbedAustin 26:2896fbdd0450 114 for(int x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespce ID
mbedAustin 26:2896fbdd0450 115 Data[index++] = defaultUidNamespaceID[x];
mbedAustin 26:2896fbdd0450 116 }
mbedAustin 26:2896fbdd0450 117 for(int x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID
mbedAustin 26:2896fbdd0450 118 Data[index++] = defaultUidInstanceID[x];
mbedAustin 26:2896fbdd0450 119 }
mbedAustin 26:2896fbdd0450 120 if(0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore
mbedAustin 26:2896fbdd0450 121 Data[index++] = (uint8_t)(uidRFU >> 0);
mbedAustin 26:2896fbdd0450 122 Data[index++] = (uint8_t)(uidRFU >> 8);
mbedAustin 26:2896fbdd0450 123 }
mbedAustin 26:2896fbdd0450 124 DBG("construcUIDFrame %d, %d",maxSize,index);
mbedAustin 26:2896fbdd0450 125 return index;
mbedAustin 26:2896fbdd0450 126 }
mbedAustin 26:2896fbdd0450 127
mbedAustin 26:2896fbdd0450 128 /*
mbedAustin 26:2896fbdd0450 129 * Set Eddystone URL Frame information.
mbedAustin 26:2896fbdd0450 130 * @param[in] power TX Power in dB measured at 0 meters from the device.
mbedAustin 26:2896fbdd0450 131 * @param url URL to encode
mbedAustin 26:2896fbdd0450 132 * @return false on success, true on failure.
mbedAustin 26:2896fbdd0450 133 */
mbedAustin 26:2896fbdd0450 134 bool setURLFrameData(int8_t power, const char * url) {
mbedAustin 26:2896fbdd0450 135 defaultUrlPower = power;
mbedAustin 29:dfb7fb5a971b 136 encodeURL(url, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
mbedAustin 26:2896fbdd0450 137 if (defaultUriDataLength > URI_DATA_MAX) {
mbedAustin 26:2896fbdd0450 138 return true; // error, URL is too big
mbedAustin 26:2896fbdd0450 139 }
mbedAustin 26:2896fbdd0450 140 return false;
mbedAustin 26:2896fbdd0450 141 }
mbedAustin 26:2896fbdd0450 142
mbedAustin 26:2896fbdd0450 143 /*
mbedAustin 26:2896fbdd0450 144 * Construct URL frame from private variables
mbedAustin 26:2896fbdd0450 145 * @param[in/out] Data pointer to array to store constructed frame in
mbedAustin 26:2896fbdd0450 146 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
mbedAustin 26:2896fbdd0450 147 * @return number of bytes used. negative number indicates error message.
mbedAustin 26:2896fbdd0450 148 */
mbedAustin 26:2896fbdd0450 149 int constructURLFrame(uint8_t * Data, uint8_t maxSize) {
mbedAustin 26:2896fbdd0450 150 int index = 0;
mbedAustin 26:2896fbdd0450 151 Data[index++] = FRAME_TYPE_URL; // 1B Type
mbedAustin 26:2896fbdd0450 152 Data[index++] = defaultUrlPower; // 1B TX Power
mbedAustin 26:2896fbdd0450 153 for(int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL
mbedAustin 26:2896fbdd0450 154 Data[index++] = defaultUriData[x];
mbedAustin 26:2896fbdd0450 155 }
mbedAustin 26:2896fbdd0450 156 DBG("constructURLFrame: %d, %d",maxSize,index);
mbedAustin 26:2896fbdd0450 157 return index;
mbedAustin 26:2896fbdd0450 158 }
mbedAustin 26:2896fbdd0450 159
mbedAustin 26:2896fbdd0450 160 /*
mbedAustin 26:2896fbdd0450 161 * Set Eddystone TLM Frame information.
mbedAustin 26:2896fbdd0450 162 * @param[in] Version of the TLM beacon data format
mbedAustin 26:2896fbdd0450 163 * @param batteryVoltage in milivolts
mbedAustin 26:2896fbdd0450 164 * @param beaconTemp in 8.8 floating point notation
mbedAustin 26:2896fbdd0450 165 *
mbedAustin 26:2896fbdd0450 166 */
mbedAustin 26:2896fbdd0450 167 void setTLMFrameData(uint8_t version, uint16_t batteryVoltage, uint16_t beaconTemp, uint32_t pduCount = 0, uint32_t timeSinceBoot = 0) {
mbedAustin 26:2896fbdd0450 168 TlmVersion = version;
mbedAustin 26:2896fbdd0450 169 TlmBatteryVoltage = batteryVoltage;
mbedAustin 26:2896fbdd0450 170 TlmBeaconTemp = beaconTemp;
mbedAustin 26:2896fbdd0450 171 TlmPduCount = pduCount; // reset
mbedAustin 26:2896fbdd0450 172 TlmTimeSinceBoot = timeSinceBoot; // reset
mbedAustin 26:2896fbdd0450 173 return;
mbedAustin 26:2896fbdd0450 174 }
mbedAustin 26:2896fbdd0450 175
mbedAustin 26:2896fbdd0450 176 /*
mbedAustin 26:2896fbdd0450 177 * Construct TLM frame from private variables
mbedAustin 26:2896fbdd0450 178 * @param[in/out] Data pointer to array to store constructed frame in
mbedAustin 26:2896fbdd0450 179 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
mbedAustin 26:2896fbdd0450 180 * @return number of bytes used. negative number indicates error message.
mbedAustin 26:2896fbdd0450 181 */
mbedAustin 26:2896fbdd0450 182 int constructTLMFrame(uint8_t * Data, uint8_t maxSize) {
mbedAustin 26:2896fbdd0450 183 int index = 0;
mbedAustin 26:2896fbdd0450 184 Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry
mbedAustin 26:2896fbdd0450 185 Data[index++] = TlmVersion; // TLM Version Number
mbedAustin 26:2896fbdd0450 186 Data[index++] = (uint8_t)(TlmBatteryVoltage>>8); // Battery Voltage[0]
mbedAustin 26:2896fbdd0450 187 Data[index++] = (uint8_t)(TlmBatteryVoltage>>0); // Battery Voltage[1]
mbedAustin 26:2896fbdd0450 188 Data[index++] = (uint8_t)(TlmBeaconTemp>>8); // Beacon Temp[0]
mbedAustin 26:2896fbdd0450 189 Data[index++] = (uint8_t)(TlmBeaconTemp>>0); // Beacon Temp[1]
mbedAustin 26:2896fbdd0450 190 Data[index++] = (uint8_t)(TlmPduCount>>24); // PDU Count [0]
mbedAustin 26:2896fbdd0450 191 Data[index++] = (uint8_t)(TlmPduCount>>16); // PDU Count [1]
mbedAustin 26:2896fbdd0450 192 Data[index++] = (uint8_t)(TlmPduCount>>8); // PDU Count [2]
mbedAustin 26:2896fbdd0450 193 Data[index++] = (uint8_t)(TlmPduCount>>0); // PDU Count [3]
mbedAustin 26:2896fbdd0450 194 Data[index++] = (uint8_t)(TlmTimeSinceBoot>>24); // Time Since Boot [0]
mbedAustin 26:2896fbdd0450 195 Data[index++] = (uint8_t)(TlmTimeSinceBoot>>16); // Time Since Boot [1]
mbedAustin 26:2896fbdd0450 196 Data[index++] = (uint8_t)(TlmTimeSinceBoot>>8); // Time Since Boot [2]
mbedAustin 26:2896fbdd0450 197 Data[index++] = (uint8_t)(TlmTimeSinceBoot>>0); // Time Since Boot [3]
mbedAustin 26:2896fbdd0450 198 DBG("constructURLFrame: %d, %d",maxSize,index);
mbedAustin 26:2896fbdd0450 199 return index;
mbedAustin 26:2896fbdd0450 200 }
mbedAustin 26:2896fbdd0450 201
mbedAustin 26:2896fbdd0450 202 /*
mbedAustin 26:2896fbdd0450 203 * Update the TLM frame battery voltage value
mbedAustin 26:2896fbdd0450 204 * @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV)
mbedAustin 26:2896fbdd0450 205 * @return nothing
mbedAustin 26:2896fbdd0450 206 */
mbedAustin 26:2896fbdd0450 207 void updateTlmBatteryVoltage(uint16_t voltagemv) {
mbedAustin 26:2896fbdd0450 208 TlmBatteryVoltage = voltagemv;
mbedAustin 26:2896fbdd0450 209 return;
mbedAustin 26:2896fbdd0450 210 }
mbedAustin 26:2896fbdd0450 211
mbedAustin 26:2896fbdd0450 212 /*
mbedAustin 26:2896fbdd0450 213 * Update the TLM frame beacon temperature
mbedAustin 26:2896fbdd0450 214 * @param[in] temp Temperature of beacon (in 8.8fpn)
mbedAustin 26:2896fbdd0450 215 * @return nothing
mbedAustin 26:2896fbdd0450 216 */
mbedAustin 26:2896fbdd0450 217 void updateTlmBeaconTemp(uint16_t temp) {
mbedAustin 26:2896fbdd0450 218 TlmBeaconTemp = temp;
mbedAustin 26:2896fbdd0450 219 return;
mbedAustin 26:2896fbdd0450 220 }
mbedAustin 26:2896fbdd0450 221
mbedAustin 26:2896fbdd0450 222 /*
mbedAustin 26:2896fbdd0450 223 * Update the TLM frame PDU Count field
mbedAustin 26:2896fbdd0450 224 * @param[in] pduCount Number of Advertisiting frames sent since powerup
mbedAustin 26:2896fbdd0450 225 * @return nothing
mbedAustin 26:2896fbdd0450 226 */
mbedAustin 26:2896fbdd0450 227 void updateTlmPduCount(uint32_t pduCount) {
mbedAustin 26:2896fbdd0450 228 TlmPduCount = pduCount;
mbedAustin 26:2896fbdd0450 229 return;
mbedAustin 26:2896fbdd0450 230 }
mbedAustin 26:2896fbdd0450 231
mbedAustin 26:2896fbdd0450 232 /*
mbedAustin 26:2896fbdd0450 233 * Update the TLM frame Time since boot in 0.1s incriments
mbedAustin 26:2896fbdd0450 234 * @param[in] timeSinceBoot Time since boot in 0.1s incriments
mbedAustin 26:2896fbdd0450 235 * @return nothing
mbedAustin 26:2896fbdd0450 236 */
mbedAustin 26:2896fbdd0450 237 void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) {
mbedAustin 26:2896fbdd0450 238 TlmTimeSinceBoot = timeSinceBoot;
mbedAustin 26:2896fbdd0450 239 return;
mbedAustin 26:2896fbdd0450 240 }
mbedAustin 26:2896fbdd0450 241
mbedAustin 26:2896fbdd0450 242 /*
mbedAustin 26:2896fbdd0450 243 * callback function, called every 0.1s, incriments the TimeSinceBoot field in the TLM frame
mbedAustin 26:2896fbdd0450 244 * @return nothing
mbedAustin 26:2896fbdd0450 245 */
mbedAustin 26:2896fbdd0450 246 void tsbCallback(void) {
mbedAustin 26:2896fbdd0450 247 TlmTimeSinceBoot++;
mbedAustin 26:2896fbdd0450 248 }
mbedAustin 26:2896fbdd0450 249
mbedAustin 26:2896fbdd0450 250 /*
mbedAustin 26:2896fbdd0450 251 * Update advertising data
mbedAustin 26:2896fbdd0450 252 * @return true on success, false on failure
mbedAustin 26:2896fbdd0450 253 */
mbedAustin 26:2896fbdd0450 254 bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) {
mbedAustin 26:2896fbdd0450 255 // Fields from the Service
mbedAustin 26:2896fbdd0450 256 DBG("Updating AdvFrame: %d", serviceDataLen);
mbedAustin 29:dfb7fb5a971b 257 printf("\r\n");
mbedAustin 29:dfb7fb5a971b 258 for(int x = 0; x<serviceDataLen; x++) {
mbedAustin 29:dfb7fb5a971b 259 printf("%2.2x:",serviceData[x]);
mbedAustin 29:dfb7fb5a971b 260 }
mbedAustin 29:dfb7fb5a971b 261 printf("\r\n");
mbedAustin 26:2896fbdd0450 262 ble.clearAdvertisingPayload();
mbedAustin 26:2896fbdd0450 263 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
mbedAustin 26:2896fbdd0450 264 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE));
mbedAustin 26:2896fbdd0450 265 ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
mbedAustin 26:2896fbdd0450 266
mbedAustin 26:2896fbdd0450 267 return true;
mbedAustin 26:2896fbdd0450 268 }
mbedAustin 26:2896fbdd0450 269
mbedAustin 26:2896fbdd0450 270 /*
mbedAustin 26:2896fbdd0450 271 * State machine for switching out frames.
mbedAustin 26:2896fbdd0450 272 * This function is called by the radioNotificationCallback when a frame needs to get swapped out.
mbedAustin 26:2896fbdd0450 273 * This function exists because of time constraints in the radioNotificationCallback, so it is effectively
mbedAustin 26:2896fbdd0450 274 * broken up into two functions.
mbedAustin 26:2896fbdd0450 275 */
mbedAustin 26:2896fbdd0450 276 void swapOutFrames(void) {
mbedAustin 26:2896fbdd0450 277 uint8_t serviceData[SERVICE_DATA_MAX];
mbedAustin 26:2896fbdd0450 278 unsigned serviceDataLen = 0;
mbedAustin 26:2896fbdd0450 279 //hard code in the eddystone UUID
mbedAustin 26:2896fbdd0450 280 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
mbedAustin 26:2896fbdd0450 281 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
mbedAustin 26:2896fbdd0450 282
mbedAustin 26:2896fbdd0450 283 // if certain frames are not enabled, then skip them. Worst case TLM is always enabled
mbedAustin 26:2896fbdd0450 284 switch(frameIndex) {
mbedAustin 26:2896fbdd0450 285 case 1:
mbedAustin 26:2896fbdd0450 286 // URL Frame
mbedAustin 29:dfb7fb5a971b 287 INFO("Swaping URL Frame: %d",urlIsSet);
mbedAustin 26:2896fbdd0450 288 if(urlIsSet) {
mbedAustin 26:2896fbdd0450 289 serviceDataLen += constructURLFrame(serviceData+serviceDataLen,20);
mbedAustin 26:2896fbdd0450 290 DBG("\t Swapping in URL Frame: len=%d ",serviceDataLen);
mbedAustin 26:2896fbdd0450 291 updateAdvPacket(serviceData,serviceDataLen);
mbedAustin 26:2896fbdd0450 292 switchFlag = false;
mbedAustin 26:2896fbdd0450 293 frameIndex++;
mbedAustin 26:2896fbdd0450 294 break;
mbedAustin 26:2896fbdd0450 295 }
mbedAustin 26:2896fbdd0450 296 case 2:
mbedAustin 26:2896fbdd0450 297 // UID Frame
mbedAustin 29:dfb7fb5a971b 298 INFO("Swaping UID Frame: %d",uidIsSet);
mbedAustin 26:2896fbdd0450 299 if(uidIsSet) {
mbedAustin 26:2896fbdd0450 300 serviceDataLen += constructUIDFrame(serviceData+serviceDataLen,20);
mbedAustin 26:2896fbdd0450 301 DBG("\t Swapping in UID Frame: len=%d",serviceDataLen);
mbedAustin 26:2896fbdd0450 302 updateAdvPacket(serviceData,serviceDataLen);
mbedAustin 26:2896fbdd0450 303 switchFlag = false;
mbedAustin 26:2896fbdd0450 304 frameIndex++;
mbedAustin 26:2896fbdd0450 305 break;
mbedAustin 26:2896fbdd0450 306 }
mbedAustin 26:2896fbdd0450 307 default:
mbedAustin 26:2896fbdd0450 308 // TLM frame
mbedAustin 29:dfb7fb5a971b 309 INFO("Swaping TLM Frame:");
mbedAustin 26:2896fbdd0450 310 serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,20);
mbedAustin 26:2896fbdd0450 311 DBG("\t Swapping in TLM Frame: len=%d",serviceDataLen);
mbedAustin 26:2896fbdd0450 312 updateAdvPacket(serviceData,serviceDataLen);
mbedAustin 26:2896fbdd0450 313 frameIndex++;
mbedAustin 26:2896fbdd0450 314 break;
mbedAustin 26:2896fbdd0450 315 }
mbedAustin 26:2896fbdd0450 316 }
mbedAustin 26:2896fbdd0450 317
mbedAustin 26:2896fbdd0450 318 /*
mbedAustin 26:2896fbdd0450 319 * Callback from onRadioNotification(), used to update the PDUCounter and process next state.
mbedAustin 26:2896fbdd0450 320 */
mbedAustin 26:2896fbdd0450 321 #define EDDYSTONE_SWAPFRAME_DELAYMS 1
mbedAustin 26:2896fbdd0450 322 void radioNotificationCallback(bool radioActive) {
mbedAustin 26:2896fbdd0450 323 //DBG("RadioNotificationCallback : %d, %d, %d, %d",radioActive,frameIndex,TlmPduCount,TlmTimeSinceBoot);
mbedAustin 26:2896fbdd0450 324 // Update PDUCount
mbedAustin 26:2896fbdd0450 325 TlmPduCount++;
mbedAustin 26:2896fbdd0450 326 frameIndex = frameIndex % EDDYSTONE_MAX_FRAMETYPE;
mbedAustin 26:2896fbdd0450 327
mbedAustin 26:2896fbdd0450 328
mbedAustin 26:2896fbdd0450 329 // True just before an frame is sent, fale just after a frame is sent
mbedAustin 26:2896fbdd0450 330 if(radioActive) {
mbedAustin 26:2896fbdd0450 331 // Do Nothing
mbedAustin 26:2896fbdd0450 332 } else {
mbedAustin 26:2896fbdd0450 333 // state machine to control which packet is being sent
mbedAustin 26:2896fbdd0450 334 switch(frameIndex) {
mbedAustin 26:2896fbdd0450 335 case 0: // TLM Frame
mbedAustin 28:af37cebcb583 336 switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
mbedAustin 26:2896fbdd0450 337 switchFlag = true;
mbedAustin 26:2896fbdd0450 338 break;
mbedAustin 26:2896fbdd0450 339 case 1: // URL Frame
mbedAustin 26:2896fbdd0450 340 // switch out packets
mbedAustin 26:2896fbdd0450 341 if(switchFlag) {
mbedAustin 28:af37cebcb583 342 switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
mbedAustin 26:2896fbdd0450 343 switchFlag = false;
mbedAustin 26:2896fbdd0450 344 } else {
mbedAustin 26:2896fbdd0450 345 if((TlmPduCount % 10) == 0) { // every 10 adv packets switch the frame
mbedAustin 26:2896fbdd0450 346 switchFlag = true;
mbedAustin 26:2896fbdd0450 347 }
mbedAustin 26:2896fbdd0450 348 }
mbedAustin 26:2896fbdd0450 349 break;
mbedAustin 26:2896fbdd0450 350 case 2: // UIDFrame
mbedAustin 26:2896fbdd0450 351 // switch out packets
mbedAustin 26:2896fbdd0450 352 if(switchFlag ) {
mbedAustin 28:af37cebcb583 353 switchFrame.attach_us(this, &EddystoneService::swapOutFrames, EDDYSTONE_SWAPFRAME_DELAYMS);
mbedAustin 26:2896fbdd0450 354 switchFlag = false;
mbedAustin 26:2896fbdd0450 355 } else {
mbedAustin 26:2896fbdd0450 356 if((TlmPduCount % 10) == 0) { // every 10 adv packets switch the frame
mbedAustin 26:2896fbdd0450 357 switchFlag = true;
mbedAustin 26:2896fbdd0450 358 }
mbedAustin 26:2896fbdd0450 359 }
mbedAustin 26:2896fbdd0450 360 break;
mbedAustin 26:2896fbdd0450 361 }
mbedAustin 26:2896fbdd0450 362 }
mbedAustin 26:2896fbdd0450 363
mbedAustin 26:2896fbdd0450 364 return;
mbedAustin 26:2896fbdd0450 365 }
mbedAustin 26:2896fbdd0450 366
mbedAustin 26:2896fbdd0450 367 /*
mbedAustin 26:2896fbdd0450 368 * This function explicityly sets the parameters used by the Eddystone beacon.
mbedAustin 26:2896fbdd0450 369 * this function should be used in leu of the config service.
mbedAustin 26:2896fbdd0450 370 *
mbedAustin 26:2896fbdd0450 371 * @param bleIn ble object used to broadcast eddystone information
mbedAustin 26:2896fbdd0450 372 * @oaram beaconPeriodus is how often ble broadcasts are mde, in mili seconds
mbedAustin 26:2896fbdd0450 373 * @param txPowerLevel sets the broadcasting power level.
mbedAustin 26:2896fbdd0450 374 * @param uidNamespaceID 10Byte Namespace UUID
mbedAustin 26:2896fbdd0450 375 * @param uidInstanceID 6Byte Instance UUID
mbedAustin 26:2896fbdd0450 376 * @param url shortened URL to broadcast (pass in as a string)
mbedAustin 26:2896fbdd0450 377 * @param urlLen length of shortened url
mbedAustin 26:2896fbdd0450 378 * @param tlmVersion version of telemetry data field to use (default to 0x00)
mbedAustin 26:2896fbdd0450 379 *
mbedAustin 26:2896fbdd0450 380 */
mbedAustin 28:af37cebcb583 381 EddystoneService(BLEDevice &bleIn,
mbedAustin 26:2896fbdd0450 382 uint16_t beaconPeriodus = 100,
mbedAustin 26:2896fbdd0450 383 uint8_t txPowerLevel = 0,
mbedAustin 26:2896fbdd0450 384 uint8_t * uidNamespaceID = NULL,
mbedAustin 26:2896fbdd0450 385 uint8_t * uidInstanceID = NULL,
mbedAustin 26:2896fbdd0450 386 const char * url = NULL,
mbedAustin 26:2896fbdd0450 387 uint8_t urlLen = 0,
mbedAustin 26:2896fbdd0450 388 uint8_t tlmVersion = 0) :
mbedAustin 26:2896fbdd0450 389 ble(bleIn)
mbedAustin 27:29c6d1bb462e 390 {
mbedAustin 26:2896fbdd0450 391 uint8_t serviceData[SERVICE_DATA_MAX];
mbedAustin 26:2896fbdd0450 392 unsigned serviceDataLen = 0;
mbedAustin 26:2896fbdd0450 393 ERR("This function is not fully implemented yet, dont use it!!");
mbedAustin 26:2896fbdd0450 394 // Check optional frames, set their 'isSet' flags appropriately
mbedAustin 26:2896fbdd0450 395 if((uidNamespaceID != NULL) & (uidInstanceID != NULL)) {
mbedAustin 26:2896fbdd0450 396 uidIsSet = true;
mbedAustin 26:2896fbdd0450 397 setUIDFrameData(txPowerLevel,uidNamespaceID, uidInstanceID);
mbedAustin 26:2896fbdd0450 398 } else {
mbedAustin 26:2896fbdd0450 399 uidIsSet = false;
mbedAustin 26:2896fbdd0450 400 }
mbedAustin 26:2896fbdd0450 401 if(url != NULL) {
mbedAustin 26:2896fbdd0450 402 urlIsSet = true;
mbedAustin 26:2896fbdd0450 403 setURLFrameData(txPowerLevel,url);
mbedAustin 26:2896fbdd0450 404 } else {
mbedAustin 26:2896fbdd0450 405 uidIsSet = false;
mbedAustin 26:2896fbdd0450 406 }
mbedAustin 26:2896fbdd0450 407 // Default TLM frame to version 0x00, start all values at zero to be spec compliant.
mbedAustin 26:2896fbdd0450 408 setTLMFrameData(tlmVersion, 0x00,0x00);
mbedAustin 26:2896fbdd0450 409
mbedAustin 26:2896fbdd0450 410 // Initialize Frame transition
mbedAustin 26:2896fbdd0450 411 frameIndex = 0;
mbedAustin 26:2896fbdd0450 412 uidRFU = 0;
mbedAustin 26:2896fbdd0450 413 switchFlag = true;
mbedAustin 26:2896fbdd0450 414
mbedAustin 26:2896fbdd0450 415 /* Reinitialize the BLE stack. This will clear away the existing services and advertising state. */
mbedAustin 26:2896fbdd0450 416 ble.shutdown();
mbedAustin 26:2896fbdd0450 417 ble.init();
mbedAustin 26:2896fbdd0450 418 ble.setTxPower(txPowerLevel);
mbedAustin 26:2896fbdd0450 419 ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
mbedAustin 26:2896fbdd0450 420 ble.setAdvertisingInterval(beaconPeriodus);
mbedAustin 26:2896fbdd0450 421
mbedAustin 26:2896fbdd0450 422 // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset
mbedAustin 26:2896fbdd0450 423 updateTlmPduCount(0);
mbedAustin 26:2896fbdd0450 424 updateTlmTimeSinceBoot(0);
mbedAustin 26:2896fbdd0450 425
mbedAustin 26:2896fbdd0450 426 // Construct TLM Frame in initial advertising.
mbedAustin 26:2896fbdd0450 427 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
mbedAustin 26:2896fbdd0450 428 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
mbedAustin 26:2896fbdd0450 429 serviceDataLen += constructTLMFrame(serviceData+serviceDataLen,SERVICE_DATA_MAX);
mbedAustin 26:2896fbdd0450 430
mbedAustin 26:2896fbdd0450 431 updateAdvPacket(serviceData, serviceDataLen);
mbedAustin 26:2896fbdd0450 432 ble.gap().startAdvertising();
mbedAustin 28:af37cebcb583 433 ble.gap().onRadioNotification(this,&EddystoneService::radioNotificationCallback);
mbedAustin 28:af37cebcb583 434 timeSinceBootTick.attach(this,&EddystoneService::tsbCallback,0.1); // incriment the TimeSinceBoot ticker every 0.1s
mbedAustin 26:2896fbdd0450 435
mbedAustin 26:2896fbdd0450 436 }
mbedAustin 26:2896fbdd0450 437
mbedAustin 26:2896fbdd0450 438 private:
mbedAustin 26:2896fbdd0450 439
mbedAustin 26:2896fbdd0450 440
mbedAustin 26:2896fbdd0450 441 BLEDevice &ble;
mbedAustin 26:2896fbdd0450 442 Ticker timeSinceBootTick;
mbedAustin 26:2896fbdd0450 443 Timeout switchFrame;
mbedAustin 26:2896fbdd0450 444 // Default value that is restored on reset
mbedAustin 26:2896fbdd0450 445 size_t defaultUriDataLength;
mbedAustin 26:2896fbdd0450 446 UriData_t defaultUriData;
mbedAustin 26:2896fbdd0450 447 UIDNamespaceID_t defaultUidNamespaceID;
mbedAustin 26:2896fbdd0450 448 UIDInstanceID_t defaultUidInstanceID;
mbedAustin 26:2896fbdd0450 449 int8_t defaultUidPower;
mbedAustin 26:2896fbdd0450 450 int8_t defaultUrlPower;
mbedAustin 26:2896fbdd0450 451 uint16_t uidRFU;
mbedAustin 26:2896fbdd0450 452 bool uidIsSet;
mbedAustin 26:2896fbdd0450 453 bool urlIsSet;
mbedAustin 26:2896fbdd0450 454 bool switchFlag;
mbedAustin 26:2896fbdd0450 455
mbedAustin 26:2896fbdd0450 456 // Private Variables for Telemetry Data
mbedAustin 26:2896fbdd0450 457 uint8_t TlmVersion;
mbedAustin 26:2896fbdd0450 458 volatile uint16_t TlmBatteryVoltage;
mbedAustin 26:2896fbdd0450 459 volatile uint16_t TlmBeaconTemp;
mbedAustin 26:2896fbdd0450 460 volatile uint32_t TlmPduCount;
mbedAustin 26:2896fbdd0450 461 volatile uint32_t TlmTimeSinceBoot;
mbedAustin 26:2896fbdd0450 462
mbedAustin 26:2896fbdd0450 463 public:
mbedAustin 26:2896fbdd0450 464 /*
mbedAustin 26:2896fbdd0450 465 * Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
mbedAustin 26:2896fbdd0450 466 */
mbedAustin 29:dfb7fb5a971b 467 static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, size_t &sizeofURIDataOut) {
mbedAustin 26:2896fbdd0450 468 const char *prefixes[] = {
mbedAustin 26:2896fbdd0450 469 "http://www.",
mbedAustin 26:2896fbdd0450 470 "https://www.",
mbedAustin 26:2896fbdd0450 471 "http://",
mbedAustin 26:2896fbdd0450 472 "https://",
mbedAustin 26:2896fbdd0450 473 };
mbedAustin 26:2896fbdd0450 474 const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
mbedAustin 26:2896fbdd0450 475 const char *suffixes[] = {
mbedAustin 26:2896fbdd0450 476 ".com/",
mbedAustin 26:2896fbdd0450 477 ".org/",
mbedAustin 26:2896fbdd0450 478 ".edu/",
mbedAustin 26:2896fbdd0450 479 ".net/",
mbedAustin 26:2896fbdd0450 480 ".info/",
mbedAustin 26:2896fbdd0450 481 ".biz/",
mbedAustin 26:2896fbdd0450 482 ".gov/",
mbedAustin 26:2896fbdd0450 483 ".com",
mbedAustin 26:2896fbdd0450 484 ".org",
mbedAustin 26:2896fbdd0450 485 ".edu",
mbedAustin 26:2896fbdd0450 486 ".net",
mbedAustin 26:2896fbdd0450 487 ".info",
mbedAustin 26:2896fbdd0450 488 ".biz",
mbedAustin 26:2896fbdd0450 489 ".gov"
mbedAustin 26:2896fbdd0450 490 };
mbedAustin 26:2896fbdd0450 491 const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
mbedAustin 26:2896fbdd0450 492
mbedAustin 26:2896fbdd0450 493 sizeofURIDataOut = 0;
mbedAustin 26:2896fbdd0450 494 memset(uriDataOut, 0, sizeof(UriData_t));
mbedAustin 26:2896fbdd0450 495
mbedAustin 26:2896fbdd0450 496 if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
mbedAustin 26:2896fbdd0450 497 return;
mbedAustin 26:2896fbdd0450 498 }
mbedAustin 26:2896fbdd0450 499
mbedAustin 26:2896fbdd0450 500 /*
mbedAustin 26:2896fbdd0450 501 * handle prefix
mbedAustin 26:2896fbdd0450 502 */
mbedAustin 26:2896fbdd0450 503 for (unsigned i = 0; i < NUM_PREFIXES; i++) {
mbedAustin 26:2896fbdd0450 504 size_t prefixLen = strlen(prefixes[i]);
mbedAustin 26:2896fbdd0450 505 if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
mbedAustin 26:2896fbdd0450 506 uriDataOut[sizeofURIDataOut++] = i;
mbedAustin 26:2896fbdd0450 507 uriDataIn += prefixLen;
mbedAustin 26:2896fbdd0450 508 break;
mbedAustin 26:2896fbdd0450 509 }
mbedAustin 26:2896fbdd0450 510 }
mbedAustin 26:2896fbdd0450 511
mbedAustin 26:2896fbdd0450 512 /*
mbedAustin 26:2896fbdd0450 513 * handle suffixes
mbedAustin 26:2896fbdd0450 514 */
mbedAustin 26:2896fbdd0450 515 while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
mbedAustin 26:2896fbdd0450 516 /* check for suffix match */
mbedAustin 26:2896fbdd0450 517 unsigned i;
mbedAustin 26:2896fbdd0450 518 for (i = 0; i < NUM_SUFFIXES; i++) {
mbedAustin 26:2896fbdd0450 519 size_t suffixLen = strlen(suffixes[i]);
mbedAustin 26:2896fbdd0450 520 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
mbedAustin 26:2896fbdd0450 521 uriDataOut[sizeofURIDataOut++] = i;
mbedAustin 26:2896fbdd0450 522 uriDataIn += suffixLen;
mbedAustin 26:2896fbdd0450 523 break; /* from the for loop for checking against suffixes */
mbedAustin 26:2896fbdd0450 524 }
mbedAustin 26:2896fbdd0450 525 }
mbedAustin 26:2896fbdd0450 526 /* This is the default case where we've got an ordinary character which doesn't match a suffix. */
mbedAustin 26:2896fbdd0450 527 if (i == NUM_SUFFIXES) {
mbedAustin 26:2896fbdd0450 528 uriDataOut[sizeofURIDataOut++] = *uriDataIn;
mbedAustin 26:2896fbdd0450 529 ++uriDataIn;
mbedAustin 26:2896fbdd0450 530 }
mbedAustin 26:2896fbdd0450 531 }
mbedAustin 26:2896fbdd0450 532 }
mbedAustin 26:2896fbdd0450 533 };
mbedAustin 26:2896fbdd0450 534
mbedAustin 26:2896fbdd0450 535 #endif // SERVICES_EDDYSTONEBEACON_H_