diff --git a/lib/bleno.js b/lib/bleno.js index 0ec8b18e..9bd011e9 100644 --- a/lib/bleno.js +++ b/lib/bleno.js @@ -25,7 +25,7 @@ if (platform === 'darwin') { function Bleno() { this.initialized = false; this.platform = 'unknown'; - this.state = 'unknown'; + this._state = 'unknown'; this.address = 'unknown'; this.rssi = 0; this.mtu = 20; @@ -44,13 +44,26 @@ function Bleno() { this._bindings.on('rssiUpdate', this.onRssiUpdate.bind(this)); + //lazy init bindings on first new listener, should be on stateChange this.on('newListener', function(event) { if (event === 'stateChange' && !this.initialized) { this._bindings.init(); - this.initialized = true; } }.bind(this)); + + //or lazy init bindings if someone attempts to get state first + Object.defineProperties(this, { + state: { + get: function () { + if (!this.initialized) { + this._bindings.init(); + this.initialized = true; + } + return this._state; + } + } + }); } util.inherits(Bleno, events.EventEmitter); @@ -68,7 +81,7 @@ Bleno.prototype.onPlatform = function(platform) { Bleno.prototype.onStateChange = function(state) { debug('stateChange ' + state); - this.state = state; + this._state = state; this.emit('stateChange', state); }; @@ -98,61 +111,85 @@ Bleno.prototype.onDisconnect = function(clientAddress) { }; Bleno.prototype.startAdvertising = function(name, serviceUuids, callback) { - if (this.state !== 'poweredOn') { - var error = new Error('Could not start advertising, state is ' + this.state + ' (not poweredOn)'); + var advertise = function(state) { - if (typeof callback === 'function') { - callback(error); + if (state !== 'poweredOn') { + var error = new Error('Could not start advertising, state is ' + state + ' (not poweredOn)'); + + if (typeof callback === 'function') { + callback(error); + } else { + throw error; + } } else { - throw error; - } - } else { - if (callback) { - this.once('advertisingStart', callback); - } + if (callback) { + this.once('advertisingStart', callback); + } - var undashedServiceUuids = []; + var undashedServiceUuids = []; - if (serviceUuids && serviceUuids.length) { - for (var i = 0; i < serviceUuids.length; i++) { - undashedServiceUuids[i] = UuidUtil.removeDashes(serviceUuids[i]); + if (serviceUuids && serviceUuids.length) { + for (var i = 0; i < serviceUuids.length; i++) { + undashedServiceUuids[i] = UuidUtil.removeDashes(serviceUuids[i]); + } } + + this._bindings.startAdvertising(name, undashedServiceUuids); } + } - this._bindings.startAdvertising(name, undashedServiceUuids); + //if bindings still not init, do it now + if (!this.initialized) { + this._bindings.init(); + this.initialized = true; + this.once('stateChange', advertise.bind(this)); + }else{ + advertise.call(this, this._state); } }; Bleno.prototype.startAdvertisingIBeacon = function(uuid, major, minor, measuredPower, callback) { - if (this.state !== 'poweredOn') { - var error = new Error('Could not start advertising, state is ' + this.state + ' (not poweredOn)'); + var advertise = function(state) { + + if (state !== 'poweredOn') { + var error = new Error('Could not start advertising, state is ' + state + ' (not poweredOn)'); - if (typeof callback === 'function') { - callback(error); + if (typeof callback === 'function') { + callback(error); + } else { + throw error; + } } else { - throw error; - } - } else { - var undashedUuid = UuidUtil.removeDashes(uuid); - var uuidData = new Buffer(undashedUuid, 'hex'); - var uuidDataLength = uuidData.length; - var iBeaconData = new Buffer(uuidData.length + 5); - - for (var i = 0; i < uuidDataLength; i++) { - iBeaconData[i] = uuidData[i]; - } + var undashedUuid = UuidUtil.removeDashes(uuid); + var uuidData = new Buffer(undashedUuid, 'hex'); + var uuidDataLength = uuidData.length; + var iBeaconData = new Buffer(uuidData.length + 5); + + for (var i = 0; i < uuidDataLength; i++) { + iBeaconData[i] = uuidData[i]; + } - iBeaconData.writeUInt16BE(major, uuidDataLength); - iBeaconData.writeUInt16BE(minor, uuidDataLength + 2); - iBeaconData.writeInt8(measuredPower, uuidDataLength + 4); + iBeaconData.writeUInt16BE(major, uuidDataLength); + iBeaconData.writeUInt16BE(minor, uuidDataLength + 2); + iBeaconData.writeInt8(measuredPower, uuidDataLength + 4); - if (callback) { - this.once('advertisingStart', callback); - } + if (callback) { + this.once('advertisingStart', callback); + } + + debug('iBeacon data = ' + iBeaconData.toString('hex')); - debug('iBeacon data = ' + iBeaconData.toString('hex')); + this._bindings.startAdvertisingIBeacon(iBeaconData); + } + } - this._bindings.startAdvertisingIBeacon(iBeaconData); + //if bindings still not init, do it now + if (!this.initialized) { + this._bindings.init(); + this.initialized = true; + this.once('stateChange', advertise.bind(this)); + }else{ + advertise.call(this, this._state); } }; @@ -172,20 +209,32 @@ Bleno.prototype.startAdvertisingWithEIRData = function(advertisementData, scanDa scanData = null; } - if (this.state !== 'poweredOn') { - var error = new Error('Could not advertising scanning, state is ' + this.state + ' (not poweredOn)'); + var advertise = function(state) { - if (typeof callback === 'function') { - callback(error); + if (state !== 'poweredOn') { + var error = new Error('Could not advertising scanning, state is ' + state + ' (not poweredOn)'); + + if (typeof callback === 'function') { + callback(error); + } else { + throw error; + } } else { - throw error; - } - } else { - if (callback) { - this.once('advertisingStart', callback); + if (callback) { + this.once('advertisingStart', callback); + } + + this._bindings.startAdvertisingWithEIRData(advertisementData, scanData); } + } - this._bindings.startAdvertisingWithEIRData(advertisementData, scanData); + //if bindings still not init, do it now + if (!this.initialized) { + this._bindings.init(); + this.initialized = true; + this.once('stateChange', advertise.bind(this)); + }else{ + advertise.call(this, this._state); } }; @@ -193,7 +242,9 @@ Bleno.prototype.stopAdvertising = function(callback) { if (callback) { this.once('advertisingStop', callback); } - this._bindings.stopAdvertising(); + if(this._bindings && this.initialized){ + this._bindings.stopAdvertising(); + } }; Bleno.prototype.onAdvertisingStop = function() { @@ -205,7 +256,9 @@ Bleno.prototype.setServices = function(services, callback) { if (callback) { this.once('servicesSet', callback); } - this._bindings.setServices(services); + if(this._bindings && this.initialized){ + this._bindings.setServices(services); + } }; Bleno.prototype.onServicesSet = function(error) { @@ -220,7 +273,9 @@ Bleno.prototype.onServicesSet = function(error) { Bleno.prototype.disconnect = function() { debug('disconnect'); - this._bindings.disconnect(); + if(this._bindings && this.initialized){ + this._bindings.disconnect(); + } }; Bleno.prototype.updateRssi = function(callback) { @@ -230,7 +285,9 @@ Bleno.prototype.updateRssi = function(callback) { }); } - this._bindings.updateRssi(); + if(this._bindings && this.initialized){ + this._bindings.updateRssi(); + } }; Bleno.prototype.onRssiUpdate = function(rssi) {