1 /* Copyright 2016-present Samsung Electronics Co., Ltd. and other contributors
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 /* Copyright (C) 2015 Sandeep Mistry sandeep.mistry@gmail.com
18 * Permission is hereby granted, free of charge, to any person obtaining a copy
19 * of this software and associated documentation files (the "Software"), to deal
20 * in the Software without restriction, including without limitation the rights
21 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22 * copies of the Software, and to permit persons to whom the Software is
23 * furnished to do so, subject to the following conditions:
25 * The above copyright notice and this permission notice shall be included in
26 * all copies or substantial portions of the Software.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 var debug = console.log; //requir('debug')('ble');
39 var events = require('events');
40 var util = require('util');
42 var UuidUtil = require('ble_uuid_util');
44 var PrimaryService = require('ble_primary_service');
45 var Characteristic = require('ble_characteristic');
46 var Descriptor = require('ble_descriptor');
50 var platform = process.platform;
52 if (platform === 'darwin') {
53 // `requir` is intentional errta to avoid pre-build module dependency analyzer error
54 // The analyzer does not understand comment
55 // bindings = requir('./mac/bindings');
56 } else if (platform === 'linux' || platform === 'win32' || platform === 'android') {
57 bindings = require('ble_hci_socket_bindings');
59 throw new Error('Unsupported platform');
63 this.platform = 'unknown';
64 this.state = 'unknown';
65 this.address = 'unknown';
69 this._bindings = bindings;
71 this._bindings.on('stateChange', this.onStateChange.bind(this));
72 this._bindings.on('platform', this.onPlatform.bind(this));
73 this._bindings.on('addressChange', this.onAddressChange.bind(this));
74 this._bindings.on('advertisingStart', this.onAdvertisingStart.bind(this));
75 this._bindings.on('advertisingStop', this.onAdvertisingStop.bind(this));
76 this._bindings.on('servicesSet', this.onServicesSet.bind(this));
77 this._bindings.on('accept', this.onAccept.bind(this));
78 this._bindings.on('mtuChange', this.onMtuChange.bind(this));
79 this._bindings.on('disconnect', this.onDisconnect.bind(this));
81 this._bindings.on('rssiUpdate', this.onRssiUpdate.bind(this));
83 this._bindings.init();
86 util.inherits(Bleno, events.EventEmitter);
88 Bleno.prototype.PrimaryService = PrimaryService;
89 Bleno.prototype.Characteristic = Characteristic;
90 Bleno.prototype.Descriptor = Descriptor;
92 Bleno.prototype.onPlatform = function(platform) {
93 debug('platform ' + platform);
95 this.platform = platform;
98 Bleno.prototype.onStateChange = function(state) {
99 debug('stateChange ' + state);
103 this.emit('stateChange', state);
106 Bleno.prototype.onAddressChange = function(address) {
107 debug('addressChange ' + address);
109 this.address = address;
112 Bleno.prototype.onAccept = function(clientAddress) {
113 debug('accept ' + clientAddress);
114 this.emit('accept', clientAddress);
117 Bleno.prototype.onMtuChange = function(mtu) {
122 this.emit('mtuChange', mtu);
125 Bleno.prototype.onDisconnect = function(clientAddress) {
126 debug('disconnect' + clientAddress);
127 this.emit('disconnect', clientAddress);
130 Bleno.prototype.startAdvertising = function(name, serviceUuids, callback) {
131 if (this.state !== 'poweredOn') {
132 var error = new Error('Could not start advertising, state is ' + this.state + ' (not poweredOn)');
134 if (typeof callback === 'function') {
141 this.once('advertisingStart', callback);
144 var undashedServiceUuids = [];
146 if (serviceUuids && serviceUuids.length) {
147 for (var i = 0; i < serviceUuids.length; i++) {
148 undashedServiceUuids[i] = UuidUtil.removeDashes(serviceUuids[i]);
152 this._bindings.startAdvertising(name, undashedServiceUuids);
156 Bleno.prototype.startAdvertisingIBeacon = function(uuid, major, minor, measuredPower, callback) {
157 if (this.state !== 'poweredOn') {
158 var error = new Error('Could not start advertising, state is ' + this.state + ' (not poweredOn)');
160 if (typeof callback === 'function') {
166 var undashedUuid = UuidUtil.removeDashes(uuid);
167 var uuidData = new Buffer(undashedUuid, 'hex');
168 var uuidDataLength = uuidData.length;
169 var iBeaconData = new Buffer(uuidData.length + 5);
171 for (var i = 0; i < uuidDataLength; i++) {
172 iBeaconData[i] = uuidData[i];
175 iBeaconData.writeUInt16BE(major, uuidDataLength);
176 iBeaconData.writeUInt16BE(minor, uuidDataLength + 2);
177 iBeaconData.writeInt8(measuredPower, uuidDataLength + 4);
180 this.once('advertisingStart', callback);
183 debug('iBeacon data = ' + iBeaconData.toString('hex'));
185 this._bindings.startAdvertisingIBeacon(iBeaconData);
189 Bleno.prototype.onAdvertisingStart = function(error) {
190 debug('advertisingStart: ' + error);
193 this.emit('advertisingStartError', error);
196 this.emit('advertisingStart', error);
199 Bleno.prototype.startAdvertisingWithEIRData = function(advertisementData, scanData, callback) {
200 if (typeof scanData === 'function') {
205 if (this.state !== 'poweredOn') {
206 var error = new Error('Could not advertising scanning, state is ' + this.state + ' (not poweredOn)');
208 if (typeof callback === 'function') {
215 this.once('advertisingStart', callback);
218 this._bindings.startAdvertisingWithEIRData(advertisementData, scanData);
222 Bleno.prototype.stopAdvertising = function(callback) {
224 this.once('advertisingStop', callback);
226 this._bindings.stopAdvertising();
229 Bleno.prototype.onAdvertisingStop = function() {
230 debug('advertisingStop');
231 this.emit('advertisingStop');
234 Bleno.prototype.setServices = function(services, callback) {
236 this.once('servicesSet', callback);
238 this._bindings.setServices(services);
241 Bleno.prototype.onServicesSet = function(error) {
242 debug('servicesSet');
245 this.emit('servicesSetError', error);
248 this.emit('servicesSet', error);
251 Bleno.prototype.disconnect = function() {
253 this._bindings.disconnect();
256 Bleno.prototype.updateRssi = function(callback) {
258 this.once('rssiUpdate', function(rssi) {
259 callback(null, rssi);
263 this._bindings.updateRssi();
266 Bleno.prototype.onRssiUpdate = function(rssi) {
267 this.emit('rssiUpdate', rssi);
270 module.exports = new Bleno();