Button initiated config service

Dependencies:   BLE_API_EddystoneConfigService_2 mbed nRF51822

Fork of BLE_EddystoneBeaconConfigService_3 by URIBeacon

Committer:
mbedAustin
Date:
Fri Jul 24 04:07:34 2015 +0000
Revision:
30:6c2db8bf5b17
Parent:
29:dfb7fb5a971b
[[Working]] Updated main program to periodically update the temperature and battery voltage.

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