diff --git a/examples/fatBeacon/index.html b/examples/fatBeacon/index.html
new file mode 100644
index 0000000..3ab5790
--- /dev/null
+++ b/examples/fatBeacon/index.html
@@ -0,0 +1,11 @@
+
+
+ Fat Beacon Demo
+
+
+
+
+ HelloWorld
+
+
+
\ No newline at end of file
diff --git a/examples/fatBeacon/simple.js b/examples/fatBeacon/simple.js
new file mode 100644
index 0000000..4f3239b
--- /dev/null
+++ b/examples/fatBeacon/simple.js
@@ -0,0 +1,12 @@
+// Simplest way to create a Eddystone-FatBeacon
+
+// might want to include something like this https://www.npmjs.com/package/html-minify
+
+var eddystoneBeacon = require('./../../index');
+var fs = require('fs');
+
+fs.readFile('index.html', function(err, data){
+ if (!err) {
+ eddystoneBeacon.advertiseFatBeacon('Fat Beacon Demo', {html: data});
+ }
+});
diff --git a/lib/HTMLCharacteristic.js b/lib/HTMLCharacteristic.js
new file mode 100644
index 0000000..4c63bc5
--- /dev/null
+++ b/lib/HTMLCharacteristic.js
@@ -0,0 +1,60 @@
+/**
+* Copyright 2016 IBM Corp.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+**/
+var bleno = require('bleno');
+var util = require('util');
+
+function HTMLCharacteristic(html) {
+ this._currentMTU = 0;
+ this._queueOffset = 0;
+ this._html = html;
+ this._buffer = new Buffer(this._html, 'utf8');
+ bleno.Characteristic.call(this, {
+ uuid: 'd1a517f0249946ca9ccc809bc1c966fa',
+ properties: ['read'],
+ descriptors: [
+ new bleno.Descriptor({
+ uuid: '2901',
+ value: 'HTML'
+ })
+ ]
+ });
+
+ bleno.on('mtuChange', function(mtu) {
+ this._currentMTU = mtu;
+ }.bind(this));
+
+ bleno.on('disconnect', function(){
+ this._queueOffset = 0;
+ }.bind(this));
+}
+
+util.inherits(HTMLCharacteristic,bleno.Characteristic);
+
+HTMLCharacteristic.prototype.onReadRequest = function(offset, callback) {
+ if (this._queueOffset < this._buffer.length) {
+ var transfer = this._currentMTU - 5;
+ var end = this._queueOffset + transfer >= this._buffer.length ? this._buffer.length: this._queueOffset + transfer;
+ var slice = this._buffer.slice(this._queueOffset, end);
+ callback(this.RESULT_SUCCESS, slice);
+ this._queueOffset = end;
+ } else if (this._queueOffset === this._buffer.length) {
+ callback(this.RESULT_SUCCESS, new Buffer());
+ this._queueOffset++;
+ }
+
+}
+
+module.exports = HTMLCharacteristic;
diff --git a/lib/beacon.js b/lib/beacon.js
index 5df8193..6483946 100644
--- a/lib/beacon.js
+++ b/lib/beacon.js
@@ -4,6 +4,8 @@ var bleno = require('bleno');
var AdvertisementData = require('./util/advertisement-data');
+var HTMLCharacteristic = require('./HTMLCharacteristic');
+
var TICK_INTERVAL = 100; // ms
var DEFAULT_TX_POWER_LEVEL = -21; // dBm
@@ -19,6 +21,7 @@ function Beacon() {
this._temperature = -128;
this._secCnt = 0;
this._advCnt = 0;
+ this._html = null;
setInterval(this._tick.bind(this), TICK_INTERVAL);
}
@@ -45,6 +48,38 @@ Beacon.prototype.advertiseUrl = function(url, options) {
this._advertiseWhenPoweredOn();
};
+Beacon.prototype.advertiseFatBeacon = function(title, options) {
+
+ this._parseOptions(options);
+
+ var htmlCharacteristic = new HTMLCharacteristic(this._html);
+ var fatBeaconService = new bleno.PrimaryService({
+ uuid: 'ae5946d4e5874ba8b6a5a97cca6affd3',
+ characteristics: [htmlCharacteristic]
+ });
+
+ var services = [fatBeaconService];
+
+ if (options.services) {
+ services = services.concat(options.services);
+ }
+
+ bleno.once('advertisingStart', function(err) {
+ if (err) {
+ throw err;
+ }
+
+ bleno.setServices(services);
+ });
+
+ this._advertisementData = AdvertisementData.makeFatBeaconBuffer(title, this._txPowerLevel);
+ this._removeFlagsIfOsX();
+
+ this._mainAdvertisementData = this._advertisementData;
+
+ this._advertiseWhenPoweredOn();
+};
+
Beacon.prototype.advertiseTlm = function() {
this._advertisementData = AdvertisementData.makeTlmBuffer(this._batteryVoltage, this._temperature, this._advCnt, this._secCnt);
@@ -76,6 +111,13 @@ Beacon.prototype._parseOptions = function(options) {
this._parseTxPowerLevelOption(options.txPowerLevel);
this._parseTlmOptions(options);
this._parseNameOption(options.name);
+ this._parseFatBeaconOption(options.html);
+};
+
+Beacon.prototype._parseFatBeaconOption = function(html) {
+ if (html) {
+ this._html = html;
+ }
};
Beacon.prototype._parseNameOption = function(name) {
diff --git a/lib/util/advertisement-data.js b/lib/util/advertisement-data.js
index f541224..f6c453d 100644
--- a/lib/util/advertisement-data.js
+++ b/lib/util/advertisement-data.js
@@ -52,6 +52,19 @@ var makeUrlBuffer = function (url, txPowerLevel) {
return makeEddystoneBuffer(URL_FRAME_TYPE, data);
};
+var makeFatBeaconBuffer = function (title, txPowerLevel) {
+ var txPowerLevelData = makeTxPowerLevelBuffer(txPowerLevel);
+
+ var data = Buffer.concat([
+ txPowerLevelData,
+ new Buffer([0x0E]),
+ new Buffer(title)
+ ]);
+
+ return makeEddystoneBuffer(URL_FRAME_TYPE, data);
+};
+
+
var makeTlmBuffer = function (vBatt, temp, advCnt, secCnt) {
var tlmData = new Buffer(13);
@@ -99,5 +112,6 @@ var hexStringIdToBuffer = function(hexStringId) {
module.exports = {
makeUidBuffer: makeUidBuffer,
makeUrlBuffer: makeUrlBuffer,
- makeTlmBuffer: makeTlmBuffer
+ makeTlmBuffer: makeTlmBuffer,
+ makeFatBeaconBuffer: makeFatBeaconBuffer
};