bleacon-fork
Version:
A Node.js library for creating, discovering, and configuring iBeacons
245 lines (182 loc) • 6.2 kB
JavaScript
var events = require('events');
var util = require('util');
var debug = require('debug')('radbeacon-tag');
var noble = require('@abandonware/noble');
var SERVICE_UUID = '248e4f81e46c4762bf3f84069c5c3f09';
var PIN_CODE_UUID = '4f82';
var COMMAND_UUID = '4f83';
var VALUE_UUID = '4f84';
var RESPONSE_UUID = '4f85';
var RadBeaconTag = function(peripheral) {
this._peripheral = peripheral;
this._services = {};
this._characteristics = {};
this.uuid = peripheral.uuid;
this.name = peripheral.advertisement.localName;
this._peripheral.on('disconnect', this.onDisconnect.bind(this));
};
util.inherits(RadBeaconTag, events.EventEmitter);
RadBeaconTag.is = function(peripheral) {
var localName = peripheral.advertisement.localName;
return (localName === 'RadBeacon' && peripheral.advertisement.manufacturerData);
};
RadBeaconTag.discover = function(callback) {
var startScanningOnPowerOn = function() {
if (noble.state === 'poweredOn') {
var onDiscover = function(peripheral) {
if (!RadBeaconTag.is(peripheral)) {
return;
}
noble.removeListener('discover', onDiscover);
noble.stopScanning();
var radbeaconTag = new RadBeaconTag(peripheral);
callback(radbeaconTag);
};
noble.on('discover', onDiscover);
noble.startScanning([]);
} else {
noble.once('stateChange', startScanningOnPowerOn);
}
};
startScanningOnPowerOn();
};
RadBeaconTag.prototype.toString = function() {
return JSON.stringify({
uuid: this.uuid,
name: this.name
});
};
RadBeaconTag.prototype.onDisconnect = function() {
this.emit('disconnect');
};
RadBeaconTag.prototype.connect = function(callback) {
this._peripheral.connect(callback);
};
RadBeaconTag.prototype.disconnect = function(callback) {
this._peripheral.disconnect(callback);
};
RadBeaconTag.prototype.discoverServicesAndCharacteristics = function(callback) {
this._peripheral.discoverAllServicesAndCharacteristics(function(error, services, characteristics) {
if (error === null) {
for (var i in services) {
var service = services[i];
this._services[service.uuid] = service;
}
for (var j in characteristics) {
var characteristic = characteristics[j];
this._characteristics[characteristic.uuid] = characteristic;
}
}
callback(error);
}.bind(this));
};
RadBeaconTag.prototype.readValue = function(command, callback) {
this._characteristics[COMMAND_UUID].write(new Buffer([command]), false, function() {
this._characteristics[RESPONSE_UUID].read(function(error, data) {
callback(data);
}.bind(this));
}.bind(this));
};
RadBeaconTag.prototype.writeValue = function(command, value, callback) {
this.readValue(command, function() {
this._characteristics[VALUE_UUID].write(value, false, function() {
this._characteristics[RESPONSE_UUID].read(function(error, data) {
callback();
}.bind(this));
}.bind(this));
}.bind(this));
};
RadBeaconTag.prototype.readName = function(callback) {
this.readValue(0x87, function(data) {
callback(data.toString());
}.bind(this));
};
RadBeaconTag.prototype.readUuid = function(callback) {
this.readValue(0x90, function(data) {
callback(data.toString('hex'));
}.bind(this));
};
RadBeaconTag.prototype.readMajor = function(callback) {
this.readValue(0x91, function(data) {
callback(data.readUInt16BE(0));
}.bind(this));
};
RadBeaconTag.prototype.readMinor = function(callback) {
this.readValue(0x92, function(data) {
callback(data.readUInt16BE(0));
}.bind(this));
};
RadBeaconTag.prototype.readMeasuredTxPower = function(callback) {
this.readValue(0x93, function(data) {
callback(data.readInt8(0));
}.bind(this));
};
RadBeaconTag.prototype.readTxPower = function(callback) {
this.readValue(0x84, function(data) {
callback(data.readInt8(0));
}.bind(this));
};
RadBeaconTag.prototype.readAdvertisementInterval = function(callback) {
this.readValue(0x82, function(data) {
callback(data.readUInt16BE(0));
}.bind(this));
};
RadBeaconTag.prototype.readBatteryLevel = function(callback) {
this.readValue(0xa0, function(data) {
callback(data.readUInt8(0));
}.bind(this));
};
RadBeaconTag.prototype.login = function(pin, callback) {
var data = new Buffer(4);
pin += '';
for (var i = 0; i < data.length; i++) {
data[i] = parseInt(pin.charAt(i), 10);
}
this._characteristics[PIN_CODE_UUID].write(data, false, function() {
this._characteristics[RESPONSE_UUID].read(function(error, data) {
callback(data.readInt8(0) === 1);
}.bind(this));
}.bind(this));
};
RadBeaconTag.prototype.writeName = function(name, callback) {
this.writeValue(0x07, new Buffer(name), callback);
};
RadBeaconTag.prototype.writeUuid = function(uuid, callback) {
this.writeValue(0x10, new Buffer(uuid, 'hex'), callback);
};
RadBeaconTag.prototype.writeMajor = function(major, callback) {
var data = new Buffer(2);
data.writeUInt16BE(major, 0);
this.writeValue(0x11, data, callback);
};
RadBeaconTag.prototype.writeMinor = function(minor, callback) {
var data = new Buffer(2);
data.writeUInt16BE(minor, 0);
this.writeValue(0x12, data, callback);
};
RadBeaconTag.prototype.writeMeasuredTxPower = function(measureTxPower, callback) {
var data = new Buffer(1);
data.writeInt8(measureTxPower, 0);
this.writeValue(0x13, data, callback);
};
RadBeaconTag.prototype.writeAdvertisementInterval = function(advertisementInterval, callback) {
var data = new Buffer(2);
data.writeUInt16BE(advertisementInterval, 0);
this.writeValue(0x02, data, callback);
};
RadBeaconTag.prototype.writeTxPower = function(txPower, callback) {
var data = new Buffer(1);
data.writeInt8(txPower, 0);
this.writeValue(0x04, data, callback);
};
RadBeaconTag.prototype.writePin = function(currentpin, newpin, callback) {
var data = new Buffer(4);
newpin += '';
for (var i = 0; i < data.length; i++) {
data[i] = parseInt(newpin.charAt(i), 10);
}
this.login(currentpin, function() {
this.writeValue(0x01, data, callback);
}.bind(this));
};
module.exports = RadBeaconTag;