Preliminary main mbed library for nexpaq development

Committer:
nexpaq
Date:
Fri Nov 04 20:27:58 2016 +0000
Revision:
0:6c56fb4bc5f0
Moving to library for sharing updates

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nexpaq 0:6c56fb4bc5f0 1 /* mbed Microcontroller Library
nexpaq 0:6c56fb4bc5f0 2 * Copyright (c) 2006-2015 ARM Limited
nexpaq 0:6c56fb4bc5f0 3 *
nexpaq 0:6c56fb4bc5f0 4 * Licensed under the Apache License, Version 2.0 (the "License");
nexpaq 0:6c56fb4bc5f0 5 * you may not use this file except in compliance with the License.
nexpaq 0:6c56fb4bc5f0 6 * You may obtain a copy of the License at
nexpaq 0:6c56fb4bc5f0 7 *
nexpaq 0:6c56fb4bc5f0 8 * http://www.apache.org/licenses/LICENSE-2.0
nexpaq 0:6c56fb4bc5f0 9 *
nexpaq 0:6c56fb4bc5f0 10 * Unless required by applicable law or agreed to in writing, software
nexpaq 0:6c56fb4bc5f0 11 * distributed under the License is distributed on an "AS IS" BASIS,
nexpaq 0:6c56fb4bc5f0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
nexpaq 0:6c56fb4bc5f0 13 * See the License for the specific language governing permissions and
nexpaq 0:6c56fb4bc5f0 14 * limitations under the License.
nexpaq 0:6c56fb4bc5f0 15 */
nexpaq 0:6c56fb4bc5f0 16
nexpaq 0:6c56fb4bc5f0 17 #ifndef SERVICES_EDDYSTONEBEACON_H_
nexpaq 0:6c56fb4bc5f0 18 #define SERVICES_EDDYSTONEBEACON_H_
nexpaq 0:6c56fb4bc5f0 19
nexpaq 0:6c56fb4bc5f0 20 #warning ble/services/EddystoneService.h is deprecated. Please use the example in 'github.com/ARMmbed/ble-examples/tree/master/BLE_EddystoneService'.
nexpaq 0:6c56fb4bc5f0 21
nexpaq 0:6c56fb4bc5f0 22 #include "ble/BLE.h"
nexpaq 0:6c56fb4bc5f0 23 #include "mbed.h"
nexpaq 0:6c56fb4bc5f0 24 #include "CircularBuffer.h"
nexpaq 0:6c56fb4bc5f0 25 static const uint8_t BEACON_EDDYSTONE[] = {0xAA, 0xFE};
nexpaq 0:6c56fb4bc5f0 26
nexpaq 0:6c56fb4bc5f0 27 //Debug is disabled by default
nexpaq 0:6c56fb4bc5f0 28 #if 0
nexpaq 0:6c56fb4bc5f0 29 #define DBG(MSG, ...) printf("[EddyStone: DBG]" MSG " \t[%s,%d]\r\n", \
nexpaq 0:6c56fb4bc5f0 30 ## __VA_ARGS__, \
nexpaq 0:6c56fb4bc5f0 31 __FILE__, \
nexpaq 0:6c56fb4bc5f0 32 __LINE__);
nexpaq 0:6c56fb4bc5f0 33 #define WARN(MSG, ...) printf("[EddyStone: WARN]" MSG " \t[%s,%d]\r\n", \
nexpaq 0:6c56fb4bc5f0 34 ## __VA_ARGS__, \
nexpaq 0:6c56fb4bc5f0 35 __FILE__, \
nexpaq 0:6c56fb4bc5f0 36 __LINE__);
nexpaq 0:6c56fb4bc5f0 37 #define ERR(MSG, ...) printf("[EddyStone: ERR]" MSG " \t[%s,%d]\r\n", \
nexpaq 0:6c56fb4bc5f0 38 ## __VA_ARGS__, \
nexpaq 0:6c56fb4bc5f0 39 __FILE__, \
nexpaq 0:6c56fb4bc5f0 40 __LINE__);
nexpaq 0:6c56fb4bc5f0 41 #else // if 0
nexpaq 0:6c56fb4bc5f0 42 #define DBG(x, ...) //wait_us(10);
nexpaq 0:6c56fb4bc5f0 43 #define WARN(x, ...) //wait_us(10);
nexpaq 0:6c56fb4bc5f0 44 #define ERR(x, ...)
nexpaq 0:6c56fb4bc5f0 45 #endif // if 0
nexpaq 0:6c56fb4bc5f0 46
nexpaq 0:6c56fb4bc5f0 47 #if 0
nexpaq 0:6c56fb4bc5f0 48 #define INFO(x, ...) printf("[EddyStone: INFO]"x " \t[%s,%d]\r\n", \
nexpaq 0:6c56fb4bc5f0 49 ## __VA_ARGS__, \
nexpaq 0:6c56fb4bc5f0 50 __FILE__, \
nexpaq 0:6c56fb4bc5f0 51 __LINE__);
nexpaq 0:6c56fb4bc5f0 52 #else // if 0
nexpaq 0:6c56fb4bc5f0 53 #define INFO(x, ...)
nexpaq 0:6c56fb4bc5f0 54 #endif // if 0
nexpaq 0:6c56fb4bc5f0 55
nexpaq 0:6c56fb4bc5f0 56 /**
nexpaq 0:6c56fb4bc5f0 57 * @class Eddystone
nexpaq 0:6c56fb4bc5f0 58 * @brief Eddystone Configuration Service. Can be used to set URL, adjust power levels, and set flags.
nexpaq 0:6c56fb4bc5f0 59 * See https://github.com/google/eddystone
nexpaq 0:6c56fb4bc5f0 60 *
nexpaq 0:6c56fb4bc5f0 61 */
nexpaq 0:6c56fb4bc5f0 62 class EddystoneService
nexpaq 0:6c56fb4bc5f0 63 {
nexpaq 0:6c56fb4bc5f0 64 public:
nexpaq 0:6c56fb4bc5f0 65 enum FrameTypes {
nexpaq 0:6c56fb4bc5f0 66 NONE,
nexpaq 0:6c56fb4bc5f0 67 url,
nexpaq 0:6c56fb4bc5f0 68 uid,
nexpaq 0:6c56fb4bc5f0 69 tlm
nexpaq 0:6c56fb4bc5f0 70 };
nexpaq 0:6c56fb4bc5f0 71
nexpaq 0:6c56fb4bc5f0 72 static const int SERVICE_DATA_MAX = 31; // Maximum size of service data in ADV packets
nexpaq 0:6c56fb4bc5f0 73
nexpaq 0:6c56fb4bc5f0 74 // There are currently 3 subframes defined, URI, UID, and TLM
nexpaq 0:6c56fb4bc5f0 75 #define EDDYSTONE_MAX_FRAMETYPE 3
nexpaq 0:6c56fb4bc5f0 76 void (*frames[EDDYSTONE_MAX_FRAMETYPE])(uint8_t *, uint32_t);
nexpaq 0:6c56fb4bc5f0 77 static const int URI_DATA_MAX = 18;
nexpaq 0:6c56fb4bc5f0 78 typedef uint8_t UriData_t[URI_DATA_MAX];
nexpaq 0:6c56fb4bc5f0 79 CircularBuffer<FrameTypes, EDDYSTONE_MAX_FRAMETYPE> overflow;
nexpaq 0:6c56fb4bc5f0 80
nexpaq 0:6c56fb4bc5f0 81 // UID Frame Type subfields
nexpaq 0:6c56fb4bc5f0 82 static const int UID_NAMESPACEID_SIZE = 10;
nexpaq 0:6c56fb4bc5f0 83 typedef uint8_t UIDNamespaceID_t[UID_NAMESPACEID_SIZE];
nexpaq 0:6c56fb4bc5f0 84 static const int UID_INSTANCEID_SIZE = 6;
nexpaq 0:6c56fb4bc5f0 85 typedef uint8_t UIDInstanceID_t[UID_INSTANCEID_SIZE];
nexpaq 0:6c56fb4bc5f0 86
nexpaq 0:6c56fb4bc5f0 87 // Eddystone Frame Type ID
nexpaq 0:6c56fb4bc5f0 88 static const uint8_t FRAME_TYPE_UID = 0x00;
nexpaq 0:6c56fb4bc5f0 89 static const uint8_t FRAME_TYPE_URL = 0x10;
nexpaq 0:6c56fb4bc5f0 90 static const uint8_t FRAME_TYPE_TLM = 0x20;
nexpaq 0:6c56fb4bc5f0 91
nexpaq 0:6c56fb4bc5f0 92 static const uint8_t FRAME_SIZE_TLM = 14; // TLM frame is a constant 14Bytes
nexpaq 0:6c56fb4bc5f0 93 static const uint8_t FRAME_SIZE_UID = 20; // includes RFU bytes
nexpaq 0:6c56fb4bc5f0 94
nexpaq 0:6c56fb4bc5f0 95 /**
nexpaq 0:6c56fb4bc5f0 96 * Set Eddystone UID Frame information.
nexpaq 0:6c56fb4bc5f0 97 *
nexpaq 0:6c56fb4bc5f0 98 * @param[in] power TX Power in dB measured at 0 meters from the device. Range of -100 to +20 dB.
nexpaq 0:6c56fb4bc5f0 99 * @param[in] namespaceID 10B namespace ID
nexpaq 0:6c56fb4bc5f0 100 * @param[in] instanceID 6B instance ID
nexpaq 0:6c56fb4bc5f0 101 * @param[in] RFU 2B of RFU, initialized to 0x0000 and not broadcast, included for future reference.
nexpaq 0:6c56fb4bc5f0 102 */
nexpaq 0:6c56fb4bc5f0 103 void setUIDFrameData(int8_t power,
nexpaq 0:6c56fb4bc5f0 104 UIDNamespaceID_t namespaceID,
nexpaq 0:6c56fb4bc5f0 105 UIDInstanceID_t instanceID,
nexpaq 0:6c56fb4bc5f0 106 float uidAdvPeriodIn,
nexpaq 0:6c56fb4bc5f0 107 uint16_t RFU = 0x0000) {
nexpaq 0:6c56fb4bc5f0 108 if (0.0f == uidAdvPeriodIn) {
nexpaq 0:6c56fb4bc5f0 109 uidIsSet = false;
nexpaq 0:6c56fb4bc5f0 110 return;
nexpaq 0:6c56fb4bc5f0 111 }
nexpaq 0:6c56fb4bc5f0 112 if (power > 20) {
nexpaq 0:6c56fb4bc5f0 113 power = 20;
nexpaq 0:6c56fb4bc5f0 114 }
nexpaq 0:6c56fb4bc5f0 115 if (power < -100) {
nexpaq 0:6c56fb4bc5f0 116 power = -100;
nexpaq 0:6c56fb4bc5f0 117 }
nexpaq 0:6c56fb4bc5f0 118
nexpaq 0:6c56fb4bc5f0 119 defaultUidPower = power;
nexpaq 0:6c56fb4bc5f0 120 memcpy(defaultUidNamespaceID, namespaceID, UID_NAMESPACEID_SIZE);
nexpaq 0:6c56fb4bc5f0 121 memcpy(defaultUidInstanceID, instanceID, UID_INSTANCEID_SIZE);
nexpaq 0:6c56fb4bc5f0 122 uidRFU = (uint16_t)RFU; // this is probably bad form, but it doesn't really matter yet.
nexpaq 0:6c56fb4bc5f0 123 uidAdvPeriod = uidAdvPeriodIn;
nexpaq 0:6c56fb4bc5f0 124 uidIsSet = true; // set toggle to advertise UID frames
nexpaq 0:6c56fb4bc5f0 125 }
nexpaq 0:6c56fb4bc5f0 126
nexpaq 0:6c56fb4bc5f0 127 /*
nexpaq 0:6c56fb4bc5f0 128 * Construct UID frame from private variables
nexpaq 0:6c56fb4bc5f0 129 * @param[in/out] Data pointer to array to store constructed frame in
nexpaq 0:6c56fb4bc5f0 130 * @param[in] maxSize number of bytes left in array, effectively how much empty space is available to write to
nexpaq 0:6c56fb4bc5f0 131 * @return number of bytes used. negative number indicates error message.
nexpaq 0:6c56fb4bc5f0 132 */
nexpaq 0:6c56fb4bc5f0 133 unsigned constructUIDFrame(uint8_t *Data, uint8_t maxSize) {
nexpaq 0:6c56fb4bc5f0 134 unsigned index = 0;
nexpaq 0:6c56fb4bc5f0 135
nexpaq 0:6c56fb4bc5f0 136 Data[index++] = FRAME_TYPE_UID; // 1B Type
nexpaq 0:6c56fb4bc5f0 137
nexpaq 0:6c56fb4bc5f0 138 if (defaultUidPower > 20) {
nexpaq 0:6c56fb4bc5f0 139 defaultUidPower = 20; // enforce range of vaild values.
nexpaq 0:6c56fb4bc5f0 140 }
nexpaq 0:6c56fb4bc5f0 141 if (defaultUidPower < -100) {
nexpaq 0:6c56fb4bc5f0 142 defaultUidPower = -100;
nexpaq 0:6c56fb4bc5f0 143 }
nexpaq 0:6c56fb4bc5f0 144 Data[index++] = defaultUidPower; // 1B Power @ 0meter
nexpaq 0:6c56fb4bc5f0 145
nexpaq 0:6c56fb4bc5f0 146 DBG("UID NamespaceID = '0x");
nexpaq 0:6c56fb4bc5f0 147 for (size_t x = 0; x < UID_NAMESPACEID_SIZE; x++) { // 10B Namespace ID
nexpaq 0:6c56fb4bc5f0 148 Data[index++] = defaultUidNamespaceID[x];
nexpaq 0:6c56fb4bc5f0 149 DBG("%x,", defaultUidNamespaceID[x]);
nexpaq 0:6c56fb4bc5f0 150 }
nexpaq 0:6c56fb4bc5f0 151 DBG("'\r\n");
nexpaq 0:6c56fb4bc5f0 152
nexpaq 0:6c56fb4bc5f0 153 DBG("UID InstanceID = '0x");
nexpaq 0:6c56fb4bc5f0 154 for (size_t x = 0; x< UID_INSTANCEID_SIZE; x++) { // 6B Instance ID
nexpaq 0:6c56fb4bc5f0 155 Data[index++] = defaultUidInstanceID[x];
nexpaq 0:6c56fb4bc5f0 156 DBG("%x,", defaultUidInstanceID[x]);
nexpaq 0:6c56fb4bc5f0 157 }
nexpaq 0:6c56fb4bc5f0 158 DBG("'\r\n");
nexpaq 0:6c56fb4bc5f0 159
nexpaq 0:6c56fb4bc5f0 160 if (0 != uidRFU) { // 2B RFU, include if non-zero, otherwise ignore
nexpaq 0:6c56fb4bc5f0 161 Data[index++] = (uint8_t)(uidRFU >> 0);
nexpaq 0:6c56fb4bc5f0 162 Data[index++] = (uint8_t)(uidRFU >> 8);
nexpaq 0:6c56fb4bc5f0 163 }
nexpaq 0:6c56fb4bc5f0 164 DBG("construcUIDFrame %d, %d", maxSize, index);
nexpaq 0:6c56fb4bc5f0 165 return index;
nexpaq 0:6c56fb4bc5f0 166 }
nexpaq 0:6c56fb4bc5f0 167
nexpaq 0:6c56fb4bc5f0 168 /**
nexpaq 0:6c56fb4bc5f0 169 * Set Eddystone URL Frame information.
nexpaq 0:6c56fb4bc5f0 170 * @param[in] power TX Power in dB measured at 0 meters from the device.
nexpaq 0:6c56fb4bc5f0 171 * @param[in] url URL to encode
nexpaq 0:6c56fb4bc5f0 172 * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods)
nexpaq 0:6c56fb4bc5f0 173 * @return false on success, true on failure.
nexpaq 0:6c56fb4bc5f0 174 */
nexpaq 0:6c56fb4bc5f0 175 bool setURLFrameData(int8_t power, const char *urlIn, float urlAdvPeriodIn) {
nexpaq 0:6c56fb4bc5f0 176 if (0.0f == urlAdvPeriodIn) {
nexpaq 0:6c56fb4bc5f0 177 urlIsSet = false;
nexpaq 0:6c56fb4bc5f0 178 return false;
nexpaq 0:6c56fb4bc5f0 179 }
nexpaq 0:6c56fb4bc5f0 180 encodeURL(urlIn, defaultUriData, defaultUriDataLength); // encode URL to URL Formatting
nexpaq 0:6c56fb4bc5f0 181 if (defaultUriDataLength > URI_DATA_MAX) {
nexpaq 0:6c56fb4bc5f0 182 return true; // error, URL is too big
nexpaq 0:6c56fb4bc5f0 183 }
nexpaq 0:6c56fb4bc5f0 184 defaultUrlPower = power;
nexpaq 0:6c56fb4bc5f0 185 urlAdvPeriod = urlAdvPeriodIn;
nexpaq 0:6c56fb4bc5f0 186 urlIsSet = true;
nexpaq 0:6c56fb4bc5f0 187 return false;
nexpaq 0:6c56fb4bc5f0 188 }
nexpaq 0:6c56fb4bc5f0 189
nexpaq 0:6c56fb4bc5f0 190 /**
nexpaq 0:6c56fb4bc5f0 191 * Set Eddystone URL Frame information.
nexpaq 0:6c56fb4bc5f0 192 * @param[in] power TX Power in dB measured at 0 meters from the device.
nexpaq 0:6c56fb4bc5f0 193 * @param[in] encodedUrlIn Encoded URL
nexpaq 0:6c56fb4bc5f0 194 * @param[in] encodedUrlInLength Length of the encoded URL
nexpaq 0:6c56fb4bc5f0 195 * @param[in] urlAdvPeriodIn How long to advertise the URL frame (measured in # of adv periods)
nexpaq 0:6c56fb4bc5f0 196 * @return false on success, true on failure.
nexpaq 0:6c56fb4bc5f0 197 */
nexpaq 0:6c56fb4bc5f0 198 bool setURLFrameEncodedData(int8_t power, const char *encodedUrlIn, uint8_t encodedUrlInLength, float urlAdvPeriodIn) {
nexpaq 0:6c56fb4bc5f0 199 if (0.0f == urlAdvPeriodIn) {
nexpaq 0:6c56fb4bc5f0 200 urlIsSet = false;
nexpaq 0:6c56fb4bc5f0 201 return false;
nexpaq 0:6c56fb4bc5f0 202 }
nexpaq 0:6c56fb4bc5f0 203 memcpy(defaultUriData, encodedUrlIn, encodedUrlInLength);
nexpaq 0:6c56fb4bc5f0 204 if (defaultUriDataLength > URI_DATA_MAX) {
nexpaq 0:6c56fb4bc5f0 205 return true; // error, URL is too big
nexpaq 0:6c56fb4bc5f0 206 }
nexpaq 0:6c56fb4bc5f0 207 defaultUrlPower = power;
nexpaq 0:6c56fb4bc5f0 208 defaultUriDataLength = encodedUrlInLength;
nexpaq 0:6c56fb4bc5f0 209 urlAdvPeriod = urlAdvPeriodIn;
nexpaq 0:6c56fb4bc5f0 210 urlIsSet = true;
nexpaq 0:6c56fb4bc5f0 211 return false;
nexpaq 0:6c56fb4bc5f0 212 }
nexpaq 0:6c56fb4bc5f0 213
nexpaq 0:6c56fb4bc5f0 214 /*
nexpaq 0:6c56fb4bc5f0 215 * Construct URL frame from private variables
nexpaq 0:6c56fb4bc5f0 216 * @param[in/out] Data pointer to array to store constructed frame in
nexpaq 0:6c56fb4bc5f0 217 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
nexpaq 0:6c56fb4bc5f0 218 * @return number of bytes used. negative number indicates error message.
nexpaq 0:6c56fb4bc5f0 219 */
nexpaq 0:6c56fb4bc5f0 220 int constructURLFrame(uint8_t *Data, uint8_t maxSize) {
nexpaq 0:6c56fb4bc5f0 221 int index = 0;
nexpaq 0:6c56fb4bc5f0 222 Data[index++] = FRAME_TYPE_URL; // 1B Type
nexpaq 0:6c56fb4bc5f0 223 Data[index++] = defaultUrlPower; // 1B TX Power
nexpaq 0:6c56fb4bc5f0 224 for (int x = 0; x < defaultUriDataLength; x++) { // 18B of URL Prefix + encoded URL
nexpaq 0:6c56fb4bc5f0 225 Data[index++] = defaultUriData[x];
nexpaq 0:6c56fb4bc5f0 226 }
nexpaq 0:6c56fb4bc5f0 227 DBG("constructURLFrame: %d, %d", maxSize, index);
nexpaq 0:6c56fb4bc5f0 228 return index;
nexpaq 0:6c56fb4bc5f0 229 }
nexpaq 0:6c56fb4bc5f0 230
nexpaq 0:6c56fb4bc5f0 231 /*
nexpaq 0:6c56fb4bc5f0 232 * Set Eddystone TLM Frame information.
nexpaq 0:6c56fb4bc5f0 233 * @param[in] Version of the TLM beacon data format
nexpaq 0:6c56fb4bc5f0 234 * @param[in] advPeriod how often to advertise the TLM frame for (in minutes)
nexpaq 0:6c56fb4bc5f0 235 * @param batteryVoltage in milivolts
nexpaq 0:6c56fb4bc5f0 236 * @param beaconTemp in 8.8 floating point notation
nexpaq 0:6c56fb4bc5f0 237 *
nexpaq 0:6c56fb4bc5f0 238 */
nexpaq 0:6c56fb4bc5f0 239 void setTLMFrameData(uint8_t version = 0,
nexpaq 0:6c56fb4bc5f0 240 float advPeriod = 60.0f,
nexpaq 0:6c56fb4bc5f0 241 uint16_t batteryVoltage = 0,
nexpaq 0:6c56fb4bc5f0 242 uint16_t beaconTemp = 0x8000,
nexpaq 0:6c56fb4bc5f0 243 uint32_t pduCount = 0,
nexpaq 0:6c56fb4bc5f0 244 uint32_t timeSinceBoot = 0) {
nexpaq 0:6c56fb4bc5f0 245 if (0.0f == advPeriod) {
nexpaq 0:6c56fb4bc5f0 246 tlmIsSet = false;
nexpaq 0:6c56fb4bc5f0 247 return;
nexpaq 0:6c56fb4bc5f0 248 }
nexpaq 0:6c56fb4bc5f0 249 TlmVersion = version;
nexpaq 0:6c56fb4bc5f0 250 TlmBatteryVoltage = batteryVoltage;
nexpaq 0:6c56fb4bc5f0 251 TlmBeaconTemp = beaconTemp;
nexpaq 0:6c56fb4bc5f0 252 TlmPduCount = pduCount; // reset
nexpaq 0:6c56fb4bc5f0 253 TlmTimeSinceBoot = timeSinceBoot; // reset
nexpaq 0:6c56fb4bc5f0 254 TlmAdvPeriod = advPeriod;
nexpaq 0:6c56fb4bc5f0 255 tlmIsSet = true; // TLM Data has been enabled
nexpaq 0:6c56fb4bc5f0 256 }
nexpaq 0:6c56fb4bc5f0 257
nexpaq 0:6c56fb4bc5f0 258 /*
nexpaq 0:6c56fb4bc5f0 259 * Construct TLM frame from private variables
nexpaq 0:6c56fb4bc5f0 260 * @param[in/out] Data pointer to array to store constructed frame in
nexpaq 0:6c56fb4bc5f0 261 * @param[in] maxSize number of bytes left in array, effectively how much emtpy space is available to write to
nexpaq 0:6c56fb4bc5f0 262 * @return number of bytes used. negative number indicates error message.
nexpaq 0:6c56fb4bc5f0 263 */
nexpaq 0:6c56fb4bc5f0 264 int constructTLMFrame(uint8_t *Data, uint8_t maxSize) {
nexpaq 0:6c56fb4bc5f0 265 uint32_t now = timeSinceBootTimer.read_ms();
nexpaq 0:6c56fb4bc5f0 266 TlmTimeSinceBoot += (now - lastBootTimerRead) / 100;
nexpaq 0:6c56fb4bc5f0 267 lastBootTimerRead = now;
nexpaq 0:6c56fb4bc5f0 268
nexpaq 0:6c56fb4bc5f0 269 int index = 0;
nexpaq 0:6c56fb4bc5f0 270 Data[index++] = FRAME_TYPE_TLM; // Eddystone frame type = Telemetry
nexpaq 0:6c56fb4bc5f0 271 Data[index++] = TlmVersion; // TLM Version Number
nexpaq 0:6c56fb4bc5f0 272 Data[index++] = (uint8_t)(TlmBatteryVoltage >> 8); // Battery Voltage[0]
nexpaq 0:6c56fb4bc5f0 273 Data[index++] = (uint8_t)(TlmBatteryVoltage >> 0); // Battery Voltage[1]
nexpaq 0:6c56fb4bc5f0 274 Data[index++] = (uint8_t)(TlmBeaconTemp >> 8); // Beacon Temp[0]
nexpaq 0:6c56fb4bc5f0 275 Data[index++] = (uint8_t)(TlmBeaconTemp >> 0); // Beacon Temp[1]
nexpaq 0:6c56fb4bc5f0 276 Data[index++] = (uint8_t)(TlmPduCount >> 24); // PDU Count [0]
nexpaq 0:6c56fb4bc5f0 277 Data[index++] = (uint8_t)(TlmPduCount >> 16); // PDU Count [1]
nexpaq 0:6c56fb4bc5f0 278 Data[index++] = (uint8_t)(TlmPduCount >> 8); // PDU Count [2]
nexpaq 0:6c56fb4bc5f0 279 Data[index++] = (uint8_t)(TlmPduCount >> 0); // PDU Count [3]
nexpaq 0:6c56fb4bc5f0 280 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 24); // Time Since Boot [0]
nexpaq 0:6c56fb4bc5f0 281 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 16); // Time Since Boot [1]
nexpaq 0:6c56fb4bc5f0 282 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 8); // Time Since Boot [2]
nexpaq 0:6c56fb4bc5f0 283 Data[index++] = (uint8_t)(TlmTimeSinceBoot >> 0); // Time Since Boot [3]
nexpaq 0:6c56fb4bc5f0 284 DBG("constructURLFrame: %d, %d", maxSize, index);
nexpaq 0:6c56fb4bc5f0 285 return index;
nexpaq 0:6c56fb4bc5f0 286 }
nexpaq 0:6c56fb4bc5f0 287
nexpaq 0:6c56fb4bc5f0 288 /*
nexpaq 0:6c56fb4bc5f0 289 * Update the TLM frame battery voltage value
nexpaq 0:6c56fb4bc5f0 290 * @param[in] voltagemv Voltage to update the TLM field battery voltage with (in mV)
nexpaq 0:6c56fb4bc5f0 291 * @return nothing
nexpaq 0:6c56fb4bc5f0 292 */
nexpaq 0:6c56fb4bc5f0 293 void updateTlmBatteryVoltage(uint16_t voltagemv) {
nexpaq 0:6c56fb4bc5f0 294 TlmBatteryVoltage = voltagemv;
nexpaq 0:6c56fb4bc5f0 295 }
nexpaq 0:6c56fb4bc5f0 296
nexpaq 0:6c56fb4bc5f0 297 /*
nexpaq 0:6c56fb4bc5f0 298 * Update the TLM frame beacon temperature
nexpaq 0:6c56fb4bc5f0 299 * @param[in] temp Temperature of beacon (in 8.8fpn)
nexpaq 0:6c56fb4bc5f0 300 * @return nothing
nexpaq 0:6c56fb4bc5f0 301 */
nexpaq 0:6c56fb4bc5f0 302 void updateTlmBeaconTemp(uint16_t temp) {
nexpaq 0:6c56fb4bc5f0 303 TlmBeaconTemp = temp;
nexpaq 0:6c56fb4bc5f0 304 }
nexpaq 0:6c56fb4bc5f0 305
nexpaq 0:6c56fb4bc5f0 306 /*
nexpaq 0:6c56fb4bc5f0 307 * Update the TLM frame PDU Count field
nexpaq 0:6c56fb4bc5f0 308 * @param[in] pduCount Number of Advertisiting frames sent since powerup
nexpaq 0:6c56fb4bc5f0 309 * @return nothing
nexpaq 0:6c56fb4bc5f0 310 */
nexpaq 0:6c56fb4bc5f0 311 void updateTlmPduCount(uint32_t pduCount) {
nexpaq 0:6c56fb4bc5f0 312 TlmPduCount = pduCount;
nexpaq 0:6c56fb4bc5f0 313 }
nexpaq 0:6c56fb4bc5f0 314
nexpaq 0:6c56fb4bc5f0 315 /*
nexpaq 0:6c56fb4bc5f0 316 * Update the TLM frame Time since boot in 0.1s incriments
nexpaq 0:6c56fb4bc5f0 317 * @param[in] timeSinceBoot Time since boot in 0.1s incriments
nexpaq 0:6c56fb4bc5f0 318 * @return nothing
nexpaq 0:6c56fb4bc5f0 319 */
nexpaq 0:6c56fb4bc5f0 320 void updateTlmTimeSinceBoot(uint32_t timeSinceBoot) {
nexpaq 0:6c56fb4bc5f0 321 TlmTimeSinceBoot = timeSinceBoot;
nexpaq 0:6c56fb4bc5f0 322 }
nexpaq 0:6c56fb4bc5f0 323
nexpaq 0:6c56fb4bc5f0 324 /*
nexpaq 0:6c56fb4bc5f0 325 * Update advertising data
nexpaq 0:6c56fb4bc5f0 326 * @return true on success, false on failure
nexpaq 0:6c56fb4bc5f0 327 */
nexpaq 0:6c56fb4bc5f0 328 bool updateAdvPacket(uint8_t serviceData[], unsigned serviceDataLen) {
nexpaq 0:6c56fb4bc5f0 329 // Fields from the Service
nexpaq 0:6c56fb4bc5f0 330 DBG("Updating AdvFrame: %d", serviceDataLen);
nexpaq 0:6c56fb4bc5f0 331
nexpaq 0:6c56fb4bc5f0 332 ble.clearAdvertisingPayload();
nexpaq 0:6c56fb4bc5f0 333 ble.setAdvertisingType(GapAdvertisingParams::ADV_NON_CONNECTABLE_UNDIRECTED);
nexpaq 0:6c56fb4bc5f0 334 ble.setAdvertisingInterval(100);
nexpaq 0:6c56fb4bc5f0 335 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
nexpaq 0:6c56fb4bc5f0 336 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, BEACON_EDDYSTONE, sizeof(BEACON_EDDYSTONE));
nexpaq 0:6c56fb4bc5f0 337 ble.accumulateAdvertisingPayload(GapAdvertisingData::SERVICE_DATA, serviceData, serviceDataLen);
nexpaq 0:6c56fb4bc5f0 338
nexpaq 0:6c56fb4bc5f0 339
nexpaq 0:6c56fb4bc5f0 340 return true;
nexpaq 0:6c56fb4bc5f0 341 }
nexpaq 0:6c56fb4bc5f0 342
nexpaq 0:6c56fb4bc5f0 343 /*
nexpaq 0:6c56fb4bc5f0 344 * State machine for switching out frames.
nexpaq 0:6c56fb4bc5f0 345 * This function is called by the radioNotificationCallback when a frame needs to get swapped out.
nexpaq 0:6c56fb4bc5f0 346 * This function exists because of time constraints in the radioNotificationCallback, so it is effectively
nexpaq 0:6c56fb4bc5f0 347 * broken up into two functions.
nexpaq 0:6c56fb4bc5f0 348 */
nexpaq 0:6c56fb4bc5f0 349 void swapOutFrames(FrameTypes frameType) {
nexpaq 0:6c56fb4bc5f0 350 uint8_t serviceData[SERVICE_DATA_MAX];
nexpaq 0:6c56fb4bc5f0 351 unsigned serviceDataLen = 0;
nexpaq 0:6c56fb4bc5f0 352 //hard code in the eddystone UUID
nexpaq 0:6c56fb4bc5f0 353 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[0];
nexpaq 0:6c56fb4bc5f0 354 serviceData[serviceDataLen++] = BEACON_EDDYSTONE[1];
nexpaq 0:6c56fb4bc5f0 355
nexpaq 0:6c56fb4bc5f0 356 // if certain frames are not enabled, then skip them. Worst case TLM is always enabled
nexpaq 0:6c56fb4bc5f0 357 switch (frameType) {
nexpaq 0:6c56fb4bc5f0 358 case tlm:
nexpaq 0:6c56fb4bc5f0 359 // TLM frame
nexpaq 0:6c56fb4bc5f0 360 if (tlmIsSet) {
nexpaq 0:6c56fb4bc5f0 361 DBG("Swapping in TLM Frame: version=%x, Batt=%d, Temp = %d, PDUCnt = %d, TimeSinceBoot=%d",
nexpaq 0:6c56fb4bc5f0 362 TlmVersion,
nexpaq 0:6c56fb4bc5f0 363 TlmBatteryVoltage,
nexpaq 0:6c56fb4bc5f0 364 TlmBeaconTemp,
nexpaq 0:6c56fb4bc5f0 365 TlmPduCount,
nexpaq 0:6c56fb4bc5f0 366 TlmTimeSinceBoot);
nexpaq 0:6c56fb4bc5f0 367 serviceDataLen += constructTLMFrame(serviceData + serviceDataLen, 20);
nexpaq 0:6c56fb4bc5f0 368 DBG("\t Swapping in TLM Frame: len=%d", serviceDataLen);
nexpaq 0:6c56fb4bc5f0 369 updateAdvPacket(serviceData, serviceDataLen);
nexpaq 0:6c56fb4bc5f0 370 }
nexpaq 0:6c56fb4bc5f0 371 break;
nexpaq 0:6c56fb4bc5f0 372 case url:
nexpaq 0:6c56fb4bc5f0 373 // URL Frame
nexpaq 0:6c56fb4bc5f0 374 if (urlIsSet) {
nexpaq 0:6c56fb4bc5f0 375 DBG("Swapping in URL Frame: Power: %d", defaultUrlPower);
nexpaq 0:6c56fb4bc5f0 376 serviceDataLen += constructURLFrame(serviceData + serviceDataLen, 20);
nexpaq 0:6c56fb4bc5f0 377 DBG("\t Swapping in URL Frame: len=%d ", serviceDataLen);
nexpaq 0:6c56fb4bc5f0 378 updateAdvPacket(serviceData, serviceDataLen);
nexpaq 0:6c56fb4bc5f0 379 //switchFlag = false;
nexpaq 0:6c56fb4bc5f0 380 }
nexpaq 0:6c56fb4bc5f0 381 break;
nexpaq 0:6c56fb4bc5f0 382 case uid:
nexpaq 0:6c56fb4bc5f0 383 // UID Frame
nexpaq 0:6c56fb4bc5f0 384 if (uidIsSet) {
nexpaq 0:6c56fb4bc5f0 385 DBG("Swapping in UID Frame: Power: %d", defaultUidPower);
nexpaq 0:6c56fb4bc5f0 386 serviceDataLen += constructUIDFrame(serviceData + serviceDataLen, 20);
nexpaq 0:6c56fb4bc5f0 387 DBG("\t Swapping in UID Frame: len=%d", serviceDataLen);
nexpaq 0:6c56fb4bc5f0 388 updateAdvPacket(serviceData, serviceDataLen);
nexpaq 0:6c56fb4bc5f0 389 //switchFlag = false;
nexpaq 0:6c56fb4bc5f0 390 }
nexpaq 0:6c56fb4bc5f0 391 break;
nexpaq 0:6c56fb4bc5f0 392 default:
nexpaq 0:6c56fb4bc5f0 393 ERR("You have not initialized a Frame yet, please initialize one before starting a beacon");
nexpaq 0:6c56fb4bc5f0 394 ERR("uidIsSet = %d, urlIsSet = %d, tlmIsSet = %d", uidIsSet, urlIsSet, tlmIsSet);
nexpaq 0:6c56fb4bc5f0 395 }
nexpaq 0:6c56fb4bc5f0 396 }
nexpaq 0:6c56fb4bc5f0 397
nexpaq 0:6c56fb4bc5f0 398 /*
nexpaq 0:6c56fb4bc5f0 399 * Callback to swap in URL frame
nexpaq 0:6c56fb4bc5f0 400 */
nexpaq 0:6c56fb4bc5f0 401 void urlCallback(void) {
nexpaq 0:6c56fb4bc5f0 402 DBG("urlCallback");
nexpaq 0:6c56fb4bc5f0 403 if (false == advLock) {
nexpaq 0:6c56fb4bc5f0 404 advLock = true;
nexpaq 0:6c56fb4bc5f0 405 DBG("advLock = url")
nexpaq 0:6c56fb4bc5f0 406 frameIndex = url;
nexpaq 0:6c56fb4bc5f0 407 swapOutFrames(frameIndex);
nexpaq 0:6c56fb4bc5f0 408 ble.startAdvertising();
nexpaq 0:6c56fb4bc5f0 409 } else {
nexpaq 0:6c56fb4bc5f0 410 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
nexpaq 0:6c56fb4bc5f0 411 INFO("URI(%d) cannot complete, %d is currently broadcasting", url, frameIndex);
nexpaq 0:6c56fb4bc5f0 412 FrameTypes x = url;
nexpaq 0:6c56fb4bc5f0 413 overflow.push(x);
nexpaq 0:6c56fb4bc5f0 414 }
nexpaq 0:6c56fb4bc5f0 415 }
nexpaq 0:6c56fb4bc5f0 416
nexpaq 0:6c56fb4bc5f0 417 /*
nexpaq 0:6c56fb4bc5f0 418 * Callback to swap in UID frame
nexpaq 0:6c56fb4bc5f0 419 */
nexpaq 0:6c56fb4bc5f0 420 void uidCallback(void) {
nexpaq 0:6c56fb4bc5f0 421 DBG("uidCallback");
nexpaq 0:6c56fb4bc5f0 422 if (false == advLock) {
nexpaq 0:6c56fb4bc5f0 423 advLock = true;
nexpaq 0:6c56fb4bc5f0 424 DBG("advLock = uid")
nexpaq 0:6c56fb4bc5f0 425 frameIndex = uid;
nexpaq 0:6c56fb4bc5f0 426 swapOutFrames(frameIndex);
nexpaq 0:6c56fb4bc5f0 427 ble.startAdvertising();
nexpaq 0:6c56fb4bc5f0 428 } else {
nexpaq 0:6c56fb4bc5f0 429 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
nexpaq 0:6c56fb4bc5f0 430 INFO("UID(%d) cannot complete, %d is currently broadcasting", uid, frameIndex);
nexpaq 0:6c56fb4bc5f0 431 FrameTypes x = uid; // have to do this to satisfy cont vs volatile keywords... sigh...
nexpaq 0:6c56fb4bc5f0 432 overflow.push(x);
nexpaq 0:6c56fb4bc5f0 433 }
nexpaq 0:6c56fb4bc5f0 434 }
nexpaq 0:6c56fb4bc5f0 435
nexpaq 0:6c56fb4bc5f0 436 /*
nexpaq 0:6c56fb4bc5f0 437 * Callback to swap in TLM frame
nexpaq 0:6c56fb4bc5f0 438 */
nexpaq 0:6c56fb4bc5f0 439 void tlmCallback(void) {
nexpaq 0:6c56fb4bc5f0 440 DBG("tlmCallback");
nexpaq 0:6c56fb4bc5f0 441 if (false == advLock) {
nexpaq 0:6c56fb4bc5f0 442 // OK to broadcast
nexpaq 0:6c56fb4bc5f0 443 advLock = true;
nexpaq 0:6c56fb4bc5f0 444 DBG("advLock = tlm")
nexpaq 0:6c56fb4bc5f0 445 frameIndex = tlm;
nexpaq 0:6c56fb4bc5f0 446 swapOutFrames(frameIndex);
nexpaq 0:6c56fb4bc5f0 447 ble.startAdvertising();
nexpaq 0:6c56fb4bc5f0 448 } else {
nexpaq 0:6c56fb4bc5f0 449 // Someone else is broadcasting, toss it into the overflow buffer to retransmit when free
nexpaq 0:6c56fb4bc5f0 450 INFO("TLM(%d) cannot complete, %d is currently broadcasting", tlm, frameIndex);
nexpaq 0:6c56fb4bc5f0 451 FrameTypes x = tlm;
nexpaq 0:6c56fb4bc5f0 452 overflow.push(x);
nexpaq 0:6c56fb4bc5f0 453 }
nexpaq 0:6c56fb4bc5f0 454 }
nexpaq 0:6c56fb4bc5f0 455
nexpaq 0:6c56fb4bc5f0 456 void stopAdvCallback(void) {
nexpaq 0:6c56fb4bc5f0 457 if (overflow.empty()) {
nexpaq 0:6c56fb4bc5f0 458 // if nothing left to transmit, stop
nexpaq 0:6c56fb4bc5f0 459 ble.stopAdvertising();
nexpaq 0:6c56fb4bc5f0 460 advLock = false; // unlock lock
nexpaq 0:6c56fb4bc5f0 461 } else {
nexpaq 0:6c56fb4bc5f0 462 // transmit other packets at current time index
nexpaq 0:6c56fb4bc5f0 463 FrameTypes x = NONE;
nexpaq 0:6c56fb4bc5f0 464 overflow.pop(x);
nexpaq 0:6c56fb4bc5f0 465 INFO("Re-Transmitting %d", x);
nexpaq 0:6c56fb4bc5f0 466 swapOutFrames(x);
nexpaq 0:6c56fb4bc5f0 467 }
nexpaq 0:6c56fb4bc5f0 468 }
nexpaq 0:6c56fb4bc5f0 469
nexpaq 0:6c56fb4bc5f0 470 /*
nexpaq 0:6c56fb4bc5f0 471 * Callback from onRadioNotification(), used to update the PDUCounter and process next state.
nexpaq 0:6c56fb4bc5f0 472 */
nexpaq 0:6c56fb4bc5f0 473 #define EDDYSTONE_SWAPFRAME_DELAYMS 1
nexpaq 0:6c56fb4bc5f0 474 void radioNotificationCallback(bool radioActive) {
nexpaq 0:6c56fb4bc5f0 475 // Update PDUCount
nexpaq 0:6c56fb4bc5f0 476 TlmPduCount++;
nexpaq 0:6c56fb4bc5f0 477 // True just before an frame is sent, false just after a frame is sent
nexpaq 0:6c56fb4bc5f0 478 if (radioActive) {
nexpaq 0:6c56fb4bc5f0 479 // Do Nothing
nexpaq 0:6c56fb4bc5f0 480 } else {
nexpaq 0:6c56fb4bc5f0 481 // Packet has been sent, disable advertising
nexpaq 0:6c56fb4bc5f0 482 stopAdv.attach_us(this, &EddystoneService::stopAdvCallback, 1);
nexpaq 0:6c56fb4bc5f0 483 }
nexpaq 0:6c56fb4bc5f0 484 }
nexpaq 0:6c56fb4bc5f0 485
nexpaq 0:6c56fb4bc5f0 486 /*
nexpaq 0:6c56fb4bc5f0 487 * This function explicityly sets the parameters used by the Eddystone beacon.
nexpaq 0:6c56fb4bc5f0 488 * this function should be used in leu of the config service.
nexpaq 0:6c56fb4bc5f0 489 *
nexpaq 0:6c56fb4bc5f0 490 * @param bleIn ble object used to broadcast eddystone information
nexpaq 0:6c56fb4bc5f0 491 * @param beaconPeriodus is how often ble broadcasts are mde, in mili seconds
nexpaq 0:6c56fb4bc5f0 492 * @param txPowerLevel sets the broadcasting power level.
nexpaq 0:6c56fb4bc5f0 493 *
nexpaq 0:6c56fb4bc5f0 494 */
nexpaq 0:6c56fb4bc5f0 495 EddystoneService(BLEDevice &bleIn,
nexpaq 0:6c56fb4bc5f0 496 uint16_t beaconPeriodus = 100,
nexpaq 0:6c56fb4bc5f0 497 uint8_t txPowerIn = 0) :
nexpaq 0:6c56fb4bc5f0 498 ble(bleIn),
nexpaq 0:6c56fb4bc5f0 499 advPeriodus(beaconPeriodus),
nexpaq 0:6c56fb4bc5f0 500 txPower(txPowerIn),
nexpaq 0:6c56fb4bc5f0 501 advLock(false),
nexpaq 0:6c56fb4bc5f0 502 frameIndex(NONE) {
nexpaq 0:6c56fb4bc5f0 503 }
nexpaq 0:6c56fb4bc5f0 504
nexpaq 0:6c56fb4bc5f0 505 /*
nexpaq 0:6c56fb4bc5f0 506 * @breif this function starts eddystone advertising based on configured frames.
nexpaq 0:6c56fb4bc5f0 507 */
nexpaq 0:6c56fb4bc5f0 508 void start(void) {
nexpaq 0:6c56fb4bc5f0 509 // Initialize Frame transition, start with URL to pass eddystone validator app on first try
nexpaq 0:6c56fb4bc5f0 510 if (urlIsSet) {
nexpaq 0:6c56fb4bc5f0 511 frameIndex = url;
nexpaq 0:6c56fb4bc5f0 512 urlTicker.attach(this, &EddystoneService::urlCallback, (float) advPeriodus / 1000.0f);
nexpaq 0:6c56fb4bc5f0 513 DBG("attached urlCallback every %d seconds", urlAdvPeriod);
nexpaq 0:6c56fb4bc5f0 514 }
nexpaq 0:6c56fb4bc5f0 515 if (uidIsSet) {
nexpaq 0:6c56fb4bc5f0 516 frameIndex = uid;
nexpaq 0:6c56fb4bc5f0 517 uidTicker.attach(this, &EddystoneService::uidCallback, uidAdvPeriod);
nexpaq 0:6c56fb4bc5f0 518 DBG("attached uidCallback every %d seconds", uidAdvPeriod);
nexpaq 0:6c56fb4bc5f0 519 }
nexpaq 0:6c56fb4bc5f0 520 if (tlmIsSet) {
nexpaq 0:6c56fb4bc5f0 521 frameIndex = tlm;
nexpaq 0:6c56fb4bc5f0 522 // Make double sure the PDUCount and TimeSinceBoot fields are set to zero at reset
nexpaq 0:6c56fb4bc5f0 523 updateTlmPduCount(0);
nexpaq 0:6c56fb4bc5f0 524 updateTlmTimeSinceBoot(0);
nexpaq 0:6c56fb4bc5f0 525 lastBootTimerRead = 0;
nexpaq 0:6c56fb4bc5f0 526 timeSinceBootTimer.start();
nexpaq 0:6c56fb4bc5f0 527 tlmTicker.attach(this, &EddystoneService::tlmCallback, TlmAdvPeriod);
nexpaq 0:6c56fb4bc5f0 528 DBG("attached tlmCallback every %d seconds", TlmAdvPeriod);
nexpaq 0:6c56fb4bc5f0 529 }
nexpaq 0:6c56fb4bc5f0 530 if (NONE == frameIndex) {
nexpaq 0:6c56fb4bc5f0 531 error("No Frames were Initialized! Please initialize a frame before starting an eddystone beacon.");
nexpaq 0:6c56fb4bc5f0 532 }
nexpaq 0:6c56fb4bc5f0 533 //uidRFU = 0;
nexpaq 0:6c56fb4bc5f0 534
nexpaq 0:6c56fb4bc5f0 535 ble.setTxPower(txPower);
nexpaq 0:6c56fb4bc5f0 536 ble.gap().onRadioNotification(this, &EddystoneService::radioNotificationCallback);
nexpaq 0:6c56fb4bc5f0 537 }
nexpaq 0:6c56fb4bc5f0 538
nexpaq 0:6c56fb4bc5f0 539 private:
nexpaq 0:6c56fb4bc5f0 540
nexpaq 0:6c56fb4bc5f0 541 // Eddystone Variables
nexpaq 0:6c56fb4bc5f0 542 BLEDevice &ble;
nexpaq 0:6c56fb4bc5f0 543 uint16_t advPeriodus;
nexpaq 0:6c56fb4bc5f0 544 uint8_t txPower;
nexpaq 0:6c56fb4bc5f0 545 Timer timeSinceBootTimer;
nexpaq 0:6c56fb4bc5f0 546 volatile uint32_t lastBootTimerRead;
nexpaq 0:6c56fb4bc5f0 547 volatile bool advLock;
nexpaq 0:6c56fb4bc5f0 548 volatile FrameTypes frameIndex;
nexpaq 0:6c56fb4bc5f0 549 Timeout stopAdv;
nexpaq 0:6c56fb4bc5f0 550
nexpaq 0:6c56fb4bc5f0 551
nexpaq 0:6c56fb4bc5f0 552 // URI Frame Variables
nexpaq 0:6c56fb4bc5f0 553 uint8_t defaultUriDataLength;
nexpaq 0:6c56fb4bc5f0 554 UriData_t defaultUriData;
nexpaq 0:6c56fb4bc5f0 555 int8_t defaultUrlPower;
nexpaq 0:6c56fb4bc5f0 556 bool urlIsSet; // flag that enables / disable URI Frames
nexpaq 0:6c56fb4bc5f0 557 float urlAdvPeriod; // how long the url frame will be advertised for
nexpaq 0:6c56fb4bc5f0 558 Ticker urlTicker;
nexpaq 0:6c56fb4bc5f0 559
nexpaq 0:6c56fb4bc5f0 560 // UID Frame Variables
nexpaq 0:6c56fb4bc5f0 561 UIDNamespaceID_t defaultUidNamespaceID;
nexpaq 0:6c56fb4bc5f0 562 UIDInstanceID_t defaultUidInstanceID;
nexpaq 0:6c56fb4bc5f0 563 int8_t defaultUidPower;
nexpaq 0:6c56fb4bc5f0 564 uint16_t uidRFU;
nexpaq 0:6c56fb4bc5f0 565 bool uidIsSet; // flag that enables / disable UID Frames
nexpaq 0:6c56fb4bc5f0 566 float uidAdvPeriod; // how long the uid frame will be advertised for
nexpaq 0:6c56fb4bc5f0 567 Ticker uidTicker;
nexpaq 0:6c56fb4bc5f0 568
nexpaq 0:6c56fb4bc5f0 569 // TLM Frame Variables
nexpaq 0:6c56fb4bc5f0 570 uint8_t TlmVersion;
nexpaq 0:6c56fb4bc5f0 571 volatile uint16_t TlmBatteryVoltage;
nexpaq 0:6c56fb4bc5f0 572 volatile uint16_t TlmBeaconTemp;
nexpaq 0:6c56fb4bc5f0 573 volatile uint32_t TlmPduCount;
nexpaq 0:6c56fb4bc5f0 574 volatile uint32_t TlmTimeSinceBoot;
nexpaq 0:6c56fb4bc5f0 575 bool tlmIsSet; // flag that enables / disables TLM frames
nexpaq 0:6c56fb4bc5f0 576 float TlmAdvPeriod; // number of minutes between adv frames
nexpaq 0:6c56fb4bc5f0 577 Ticker tlmTicker;
nexpaq 0:6c56fb4bc5f0 578
nexpaq 0:6c56fb4bc5f0 579 public:
nexpaq 0:6c56fb4bc5f0 580 /*
nexpaq 0:6c56fb4bc5f0 581 * Encode a human-readable URI into the binary format defined by URIBeacon spec (https://github.com/google/uribeacon/tree/master/specification).
nexpaq 0:6c56fb4bc5f0 582 */
nexpaq 0:6c56fb4bc5f0 583 static void encodeURL(const char *uriDataIn, UriData_t uriDataOut, uint8_t &sizeofURIDataOut) {
nexpaq 0:6c56fb4bc5f0 584 DBG("Encode URL = %s", uriDataIn);
nexpaq 0:6c56fb4bc5f0 585 const char *prefixes[] = {
nexpaq 0:6c56fb4bc5f0 586 "http://www.",
nexpaq 0:6c56fb4bc5f0 587 "https://www.",
nexpaq 0:6c56fb4bc5f0 588 "http://",
nexpaq 0:6c56fb4bc5f0 589 "https://",
nexpaq 0:6c56fb4bc5f0 590 };
nexpaq 0:6c56fb4bc5f0 591 const size_t NUM_PREFIXES = sizeof(prefixes) / sizeof(char *);
nexpaq 0:6c56fb4bc5f0 592 const char *suffixes[] = {
nexpaq 0:6c56fb4bc5f0 593 ".com/",
nexpaq 0:6c56fb4bc5f0 594 ".org/",
nexpaq 0:6c56fb4bc5f0 595 ".edu/",
nexpaq 0:6c56fb4bc5f0 596 ".net/",
nexpaq 0:6c56fb4bc5f0 597 ".info/",
nexpaq 0:6c56fb4bc5f0 598 ".biz/",
nexpaq 0:6c56fb4bc5f0 599 ".gov/",
nexpaq 0:6c56fb4bc5f0 600 ".com",
nexpaq 0:6c56fb4bc5f0 601 ".org",
nexpaq 0:6c56fb4bc5f0 602 ".edu",
nexpaq 0:6c56fb4bc5f0 603 ".net",
nexpaq 0:6c56fb4bc5f0 604 ".info",
nexpaq 0:6c56fb4bc5f0 605 ".biz",
nexpaq 0:6c56fb4bc5f0 606 ".gov"
nexpaq 0:6c56fb4bc5f0 607 };
nexpaq 0:6c56fb4bc5f0 608 const size_t NUM_SUFFIXES = sizeof(suffixes) / sizeof(char *);
nexpaq 0:6c56fb4bc5f0 609
nexpaq 0:6c56fb4bc5f0 610 sizeofURIDataOut = 0;
nexpaq 0:6c56fb4bc5f0 611 memset(uriDataOut, 0, sizeof(UriData_t));
nexpaq 0:6c56fb4bc5f0 612
nexpaq 0:6c56fb4bc5f0 613 if ((uriDataIn == NULL) || (strlen(uriDataIn) == 0)) {
nexpaq 0:6c56fb4bc5f0 614 return;
nexpaq 0:6c56fb4bc5f0 615 }
nexpaq 0:6c56fb4bc5f0 616
nexpaq 0:6c56fb4bc5f0 617 /*
nexpaq 0:6c56fb4bc5f0 618 * handle prefix
nexpaq 0:6c56fb4bc5f0 619 */
nexpaq 0:6c56fb4bc5f0 620 for (unsigned i = 0; i < NUM_PREFIXES; i++) {
nexpaq 0:6c56fb4bc5f0 621 size_t prefixLen = strlen(prefixes[i]);
nexpaq 0:6c56fb4bc5f0 622 if (strncmp(uriDataIn, prefixes[i], prefixLen) == 0) {
nexpaq 0:6c56fb4bc5f0 623 uriDataOut[sizeofURIDataOut++] = i;
nexpaq 0:6c56fb4bc5f0 624 uriDataIn += prefixLen;
nexpaq 0:6c56fb4bc5f0 625 break;
nexpaq 0:6c56fb4bc5f0 626 }
nexpaq 0:6c56fb4bc5f0 627 }
nexpaq 0:6c56fb4bc5f0 628
nexpaq 0:6c56fb4bc5f0 629 /*
nexpaq 0:6c56fb4bc5f0 630 * handle suffixes
nexpaq 0:6c56fb4bc5f0 631 */
nexpaq 0:6c56fb4bc5f0 632 while (*uriDataIn && (sizeofURIDataOut < URI_DATA_MAX)) {
nexpaq 0:6c56fb4bc5f0 633 /* check for suffix match */
nexpaq 0:6c56fb4bc5f0 634 unsigned i;
nexpaq 0:6c56fb4bc5f0 635 for (i = 0; i < NUM_SUFFIXES; i++) {
nexpaq 0:6c56fb4bc5f0 636 size_t suffixLen = strlen(suffixes[i]);
nexpaq 0:6c56fb4bc5f0 637 if (strncmp(uriDataIn, suffixes[i], suffixLen) == 0) {
nexpaq 0:6c56fb4bc5f0 638 uriDataOut[sizeofURIDataOut++] = i;
nexpaq 0:6c56fb4bc5f0 639 uriDataIn += suffixLen;
nexpaq 0:6c56fb4bc5f0 640 break; /* from the for loop for checking against suffixes */
nexpaq 0:6c56fb4bc5f0 641 }
nexpaq 0:6c56fb4bc5f0 642 }
nexpaq 0:6c56fb4bc5f0 643 /* This is the default case where we've got an ordinary character which doesn't match a suffix. */
nexpaq 0:6c56fb4bc5f0 644 INFO("Encoding URI: No Suffix Found");
nexpaq 0:6c56fb4bc5f0 645 if (i == NUM_SUFFIXES) {
nexpaq 0:6c56fb4bc5f0 646 uriDataOut[sizeofURIDataOut++] = *uriDataIn;
nexpaq 0:6c56fb4bc5f0 647 ++uriDataIn;
nexpaq 0:6c56fb4bc5f0 648 }
nexpaq 0:6c56fb4bc5f0 649 }
nexpaq 0:6c56fb4bc5f0 650 }
nexpaq 0:6c56fb4bc5f0 651 };
nexpaq 0:6c56fb4bc5f0 652
nexpaq 0:6c56fb4bc5f0 653 #endif // SERVICES_EDDYSTONEBEACON_H_