noble
Version:
A Node.js BLE (Bluetooth Low Energy) central library.
630 lines (505 loc) • 24.3 kB
JavaScript
var events = require('events');
var os = require('os');
var util = require('util');
var debug = require('debug')('legacy-bindings');
var osRelease = os.release();
var isLessThan10_8_5 = (parseFloat(osRelease) < 12.5);
var localAddress = require('./local-address');
var uuidToAddress = require('./uuid-to-address');
var XpcConnection = require('xpc-connection');
var NobleBindings = function() {
this._peripherals = {};
this._xpcConnection = new XpcConnection('com.apple.blued');
this._xpcConnection.on('error', function(message) {
this.emit('xpcError', message);
}.bind(this));
this._xpcConnection.on('event', function(event) {
this.emit('xpcEvent', event);
}.bind(this));
};
util.inherits(NobleBindings, events.EventEmitter);
NobleBindings.prototype.sendXpcMessage = function(message) {
this._xpcConnection.sendMessage(message);
};
var nobleBindings = new NobleBindings();
nobleBindings.on('xpcEvent', function(event) {
var kCBMsgId = event.kCBMsgId;
var kCBMsgArgs = event.kCBMsgArgs;
debug('xpcEvent: ' + JSON.stringify(event, undefined, 2));
this.emit('kCBMsgId' + kCBMsgId, kCBMsgArgs);
});
/*
Result codes ...
CBErrorUnknown,
CBATTErrorInvalidHandle = 0x01,
CBATTErrorReadNotPermitted = 0x02,
CBATTErrorWriteNotPermitted = 0x03,
CBATTErrorInvalidPdu = 0x04,
CBATTErrorInsufficientAuthentication = 0x05,
CBATTErrorRequestNotSupported = 0x06,
CBATTErrorInvalidOffset = 0x07,
CBATTErrorInsufficientAuthorization = 0x08,
CBATTErrorPrepareQueueFull = 0x09,
CBATTErrorAttributeNotFound = 0x0A,
CBATTErrorAttributeNotLong = 0x0B,
CBATTErrorInsufficientEncryptionKeySize = 0x0C,
CBATTErrorInvalidAttributeValueLength = 0x0D,
CBATTErrorUnlikelyError = 0x0E,
CBATTErrorInsufficientEncryption = 0x0F,
CBATTErrorUnsupportedGroupType = 0x10,
CBATTErrorInsufficientResources = 0x11,
*/
nobleBindings.on('xpcError', function(message) {
console.error('xpcError: ' + message);
});
nobleBindings.sendCBMsg = function(id, args) {
debug('sendCBMsg: ' + id + ', ' + JSON.stringify(args, undefined, 2));
this.sendXpcMessage({
kCBMsgId: id,
kCBMsgArgs: args
});
};
nobleBindings.init = function() {
this._xpcConnection.setup();
localAddress(function(address) {
if (address) {
this.emit('addressChange', address);
}
this.sendCBMsg(1, {
kCBMsgArgAlert: 1,
kCBMsgArgName: 'node-' + (new Date()).getTime()
});
}.bind(this));
};
nobleBindings.on('kCBMsgId4', function(args) {
var state = ['unknown', 'resetting', 'unsupported', 'unauthorized', 'poweredOff', 'poweredOn'][args.kCBMsgArgState];
debug('state change ' + state);
this.emit('stateChange', state);
});
nobleBindings.startScanning = function(serviceUuids, allowDuplicates) {
var args = {
kCBMsgArgOptions: {},
kCBMsgArgUUIDs: []
};
if (serviceUuids) {
for(var i = 0; i < serviceUuids.length; i++) {
args.kCBMsgArgUUIDs[i] = new Buffer(serviceUuids[i], 'hex');
}
}
if (allowDuplicates) {
args.kCBMsgArgOptions.kCBScanOptionAllowDuplicates = 1;
}
this.sendCBMsg(isLessThan10_8_5 ? 7 : 23, args);
this.emit('scanStart');
};
nobleBindings.stopScanning = function() {
this.sendCBMsg(isLessThan10_8_5 ? 8 : 24, null);
this.emit('scanStop');
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId13' : 'kCBMsgId31', function(args) {
var peripheralUuid = args.kCBMsgArgPeripheral.kCBMsgArgUUID.toString('hex');
var peripheralHandle = args.kCBMsgArgPeripheral.kCBMsgArgPeripheralHandle;
var advertisement = {
localName: args.kCBMsgArgAdvertisementData.kCBAdvDataLocalName,
txPowerLevel: args.kCBMsgArgAdvertisementData.kCBAdvDataTxPowerLevel,
manufacturerData: args.kCBMsgArgAdvertisementData.kCBAdvDataManufacturerData,
serviceData: [],
serviceUuids: []
};
var rssi = args.kCBMsgArgRssi;
var i;
if (args.kCBMsgArgAdvertisementData.kCBAdvDataServiceUUIDs) {
for(i = 0; i < args.kCBMsgArgAdvertisementData.kCBAdvDataServiceUUIDs.length; i++) {
advertisement.serviceUuids.push(args.kCBMsgArgAdvertisementData.kCBAdvDataServiceUUIDs[i].toString('hex'));
}
}
var serviceData = args.kCBMsgArgAdvertisementData.kCBAdvDataServiceData;
if (serviceData) {
for (i = 0; i < serviceData.length; i += 2) {
var serviceDataUuid = serviceData[i].toString('hex');
var data = serviceData[i + 1];
advertisement.serviceData.push({
uuid: serviceDataUuid,
data: data
});
}
}
debug('peripheral ' + peripheralUuid + ' discovered');
this._peripherals[peripheralUuid] = this._peripherals[peripheralHandle] = {
uuid: peripheralUuid,
address: undefined,
addressType: undefined,
handle: peripheralHandle,
advertisement: advertisement,
rssi: rssi
};
(function(peripheralUuid, peripheralHandle, advertisement, rssi) {
uuidToAddress(peripheralUuid, function(error, address, addressType) {
address = address || 'unknown';
addressType = addressType || 'unknown';
this._peripherals[peripheralUuid].address = this._peripherals[peripheralHandle].address = address;
this._peripherals[peripheralUuid].addressType = this._peripherals[peripheralHandle].addressType = addressType;
this.emit('discover', peripheralUuid, address, addressType, undefined, advertisement, rssi);
}.bind(this));
}.bind(this))(peripheralUuid, peripheralHandle, advertisement, rssi);
});
nobleBindings.connect = function(peripheralUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 9 : 25, {
kCBMsgArgOptions: {
kCBConnectOptionNotifyOnDisconnection: 1
},
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId14' : 'kCBMsgId32', function(args) {
var peripheralUuid = args.kCBMsgArgUUID.toString('hex');
// var peripheralHandle = args.kCBMsgArgPeripheralHandle;
debug('peripheral ' + peripheralUuid + ' connected');
this.emit('connect', peripheralUuid);
});
nobleBindings.disconnect = function(peripheralUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 10 : 26, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId15' : 'kCBMsgId33', function(args) {
var peripheralUuid = args.kCBMsgArgUUID.toString('hex');
// var peripheralHandle = args.kCBMsgArgPeripheralHandle;
debug('peripheral ' + peripheralUuid + ' disconnected');
this.emit('disconnect', peripheralUuid);
});
nobleBindings.updateRssi = function(peripheralUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 16 : 35, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId20' : 'kCBMsgId41', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var rssi = args.kCBMsgArgData;
this._peripherals[peripheralHandle].rssi = rssi;
debug('peripheral ' + peripheralUuid + ' RSSI update ' + rssi);
this.emit('rssiUpdate', peripheralUuid, rssi);
});
nobleBindings.discoverServices = function(peripheralUuid, uuids) {
var args = {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgUUIDs: []
};
if (uuids) {
for(var i = 0; i < uuids.length; i++) {
args.kCBMsgArgUUIDs[i] = new Buffer(uuids[i], 'hex');
}
}
this.sendCBMsg(isLessThan10_8_5 ? 17 : 36, args);
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId21' : 'kCBMsgId42', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var serviceUuids = [];
this._peripherals[peripheralHandle].services = {};
for(var i = 0; i < args.kCBMsgArgServices.length; i++) {
var service = {
uuid: args.kCBMsgArgServices[i].kCBMsgArgUUID.toString('hex'),
startHandle: args.kCBMsgArgServices[i].kCBMsgArgServiceStartHandle,
endHandle: args.kCBMsgArgServices[i].kCBMsgArgServiceEndHandle
};
this._peripherals[peripheralHandle].services[service.uuid] = this._peripherals[peripheralHandle].services[service.startHandle] = service;
serviceUuids.push(service.uuid);
}
this.emit('servicesDiscover', peripheralUuid, serviceUuids);
});
nobleBindings.discoverIncludedServices = function(peripheralUuid, serviceUuid, serviceUuids) {
var args = {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgServiceStartHandle: this._peripherals[peripheralUuid].services[serviceUuid].startHandle,
kCBMsgArgServiceEndHandle: this._peripherals[peripheralUuid].services[serviceUuid].endHandle,
kCBMsgArgUUIDs: []
};
if (serviceUuids) {
for(var i = 0; i < serviceUuids.length; i++) {
args.kCBMsgArgUUIDs[i] = new Buffer(serviceUuids[i], 'hex');
}
}
this.sendCBMsg(isLessThan10_8_5 ? 25 : 46, args);
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId27' : 'kCBMsgId48', function(args) {
var peripheralUuidHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralUuidHandle].uuid;
var serviceStartHandle = args.kCBMsgArgServiceStartHandle;
var serviceUuid = this._peripherals[peripheralUuidHandle].services[serviceStartHandle].uuid;
var result = args.kCBMsgArgResult;
var includedServiceUuids = [];
this._peripherals[peripheralUuidHandle].services[serviceStartHandle].includedServices = {};
for(var i = 0; i < args.kCBMsgArgServices.length; i++) {
var includedService = {
uuid: args.kCBMsgArgServices[i].kCBMsgArgUUID.toString('hex'),
startHandle: args.kCBMsgArgServices[i].kCBMsgArgServiceStartHandle,
endHandle: args.kCBMsgArgServices[i].kCBMsgArgServiceEndHandle
};
this._peripherals[peripheralUuidHandle].services[serviceStartHandle].includedServices[includedServices.uuid] =
this._peripherals[peripheralUuidHandle].services[serviceStartHandle].includedServices[includedServices.startHandle] = includedService;
includedServiceUuids.push(includedService.uuid);
}
this.emit('includedServicesDiscover', peripheralUuid, serviceUuid, includedServiceUuids);
});
nobleBindings.discoverCharacteristics = function(peripheralUuid, serviceUuid, characteristicUuids) {
var args = {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgServiceStartHandle: this._peripherals[peripheralUuid].services[serviceUuid].startHandle,
kCBMsgArgServiceEndHandle: this._peripherals[peripheralUuid].services[serviceUuid].endHandle,
kCBMsgArgUUIDs: []
};
if (characteristicUuids) {
for(var i = 0; i < characteristicUuids.length; i++) {
args.kCBMsgArgUUIDs[i] = new Buffer(characteristicUuids[i], 'hex');
}
}
this.sendCBMsg(isLessThan10_8_5 ? 26 : 47, args);
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId28' : 'kCBMsgId49', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var serviceStartHandle = args.kCBMsgArgServiceStartHandle;
var serviceUuid = this._peripherals[peripheralHandle].services[serviceStartHandle].uuid;
var result = args.kCBMsgArgResult;
var characteristics = [];
this._peripherals[peripheralHandle].services[serviceStartHandle].characteristics = {};
for(var i = 0; i < args.kCBMsgArgCharacteristics.length; i++) {
var properties = args.kCBMsgArgCharacteristics[i].kCBMsgArgCharacteristicProperties;
var characteristic = {
uuid: args.kCBMsgArgCharacteristics[i].kCBMsgArgUUID.toString('hex'),
handle: args.kCBMsgArgCharacteristics[i].kCBMsgArgCharacteristicHandle,
valueHandle: args.kCBMsgArgCharacteristics[i].kCBMsgArgCharacteristicValueHandle,
properties: []
};
if (properties & 0x01) {
characteristic.properties.push('broadcast');
}
if (properties & 0x02) {
characteristic.properties.push('read');
}
if (properties & 0x04) {
characteristic.properties.push('writeWithoutResponse');
}
if (properties & 0x08) {
characteristic.properties.push('write');
}
if (properties & 0x10) {
characteristic.properties.push('notify');
}
if (properties & 0x20) {
characteristic.properties.push('indicate');
}
if (properties & 0x40) {
characteristic.properties.push('authenticatedSignedWrites');
}
if (properties & 0x80) {
characteristic.properties.push('extendedProperties');
}
this._peripherals[peripheralHandle].services[serviceStartHandle].characteristics[characteristic.uuid] =
this._peripherals[peripheralHandle].services[serviceStartHandle].characteristics[characteristic.handle] =
this._peripherals[peripheralHandle].services[serviceStartHandle].characteristics[characteristic.valueHandle] = characteristic;
characteristics.push({
uuid: characteristic.uuid,
properties: characteristic.properties
});
}
this.emit('characteristicsDiscover', peripheralUuid, serviceUuid, characteristics);
});
nobleBindings.read = function(peripheralUuid, serviceUuid, characteristicUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 29 : 50 , {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgCharacteristicHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].handle,
kCBMsgArgCharacteristicValueHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].valueHandle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId35' : 'kCBMsgId56', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheral = this._peripherals[peripheralHandle];
if (peripheral) {
var peripheralUuid = peripheral.uuid;
var characteristicHandle = args.kCBMsgArgCharacteristicHandle;
var isNotification = args.kCBMsgArgIsNotification ? true : false;
var data = args.kCBMsgArgData;
for(var i in peripheral.services) {
if (peripheral.services[i].characteristics &&
peripheral.services[i].characteristics[characteristicHandle]) {
this.emit('read', peripheralUuid, peripheral.services[i].uuid,
peripheral.services[i].characteristics[characteristicHandle].uuid, data, isNotification);
break;
}
}
} else {
console.warn('noble (mac legacy): received read event from unknown peripheral: ' + peripheralHandle + ' !');
}
});
nobleBindings.write = function(peripheralUuid, serviceUuid, characteristicUuid, data, withoutResponse) {
this.sendCBMsg(isLessThan10_8_5 ? 30 : 51, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgCharacteristicHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].handle,
kCBMsgArgCharacteristicValueHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].valueHandle,
kCBMsgArgData: data,
kCBMsgArgType: (withoutResponse ? 1 : 0)
});
if (withoutResponse) {
this.emit('write', peripheralUuid, serviceUuid, characteristicUuid);
}
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId36' : 'kCBMsgId57', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var characteristicHandle = args.kCBMsgArgCharacteristicHandle;
var result = args.kCBMsgArgResult;
for(var i in this._peripherals[peripheralHandle].services) {
if (this._peripherals[peripheralHandle].services[i].characteristics &&
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle]) {
this.emit('write', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].uuid);
break;
}
}
});
nobleBindings.broadcast = function(peripheralUuid, serviceUuid, characteristicUuid, broadcast) {
this.sendCBMsg(isLessThan10_8_5 ? 31 : 52, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgCharacteristicHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].handle,
kCBMsgArgCharacteristicValueHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].valueHandle,
kCBMsgArgState: (broadcast ? 1 : 0)
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId37' : 'kCBMsgId58', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var characteristicHandle = args.kCBMsgArgCharacteristicHandle;
var result = args.kCBMsgArgResult;
var state = args.kCBMsgArgState ? true : false;
for(var i in this._peripherals[peripheralHandle].services) {
if (this._peripherals[peripheralHandle].services[i].characteristics &&
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle]) {
this.emit('broadcast', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].uuid, state);
break;
}
}
});
nobleBindings.notify = function(peripheralUuid, serviceUuid, characteristicUuid, notify) {
this.sendCBMsg(isLessThan10_8_5 ? 32 : 53, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgCharacteristicHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].handle,
kCBMsgArgCharacteristicValueHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].valueHandle,
kCBMsgArgState: (notify ? 1 : 0)
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId38' : 'kCBMsgId59', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var characteristicHandle = args.kCBMsgArgCharacteristicHandle;
var result = args.kCBMsgArgResult;
var state = args.kCBMsgArgState ? true : false;
for(var i in this._peripherals[peripheralHandle].services) {
if (this._peripherals[peripheralHandle].services[i].characteristics &&
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle]) {
this.emit('notify', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].uuid, state);
break;
}
}
});
nobleBindings.discoverDescriptors = function(peripheralUuid, serviceUuid, characteristicUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 34 : 55, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgCharacteristicHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].handle,
kCBMsgArgCharacteristicValueHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].valueHandle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId39' : 'kCBMsgId60', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var characteristicHandle = args.kCBMsgArgCharacteristicHandle;
var result = args.kCBMsgArgResult;
var descriptors = []; //args.kCBMsgArgDescriptors;
for(var i in this._peripherals[peripheralHandle].services) {
if (this._peripherals[peripheralHandle].services[i].characteristics &&
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle]) {
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].descriptors = {};
for(var j = 0; j < args.kCBMsgArgDescriptors.length; j++) {
var descriptor = {
uuid: args.kCBMsgArgDescriptors[j].kCBMsgArgUUID.toString('hex'),
handle: args.kCBMsgArgDescriptors[j].kCBMsgArgDescriptorHandle
};
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].descriptors[descriptor.uuid] =
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].descriptors[descriptor.handle] = descriptor;
descriptors.push(descriptor.uuid);
}
this.emit('descriptorsDiscover', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[characteristicHandle].uuid, descriptors);
break;
}
}
});
nobleBindings.readValue = function(peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid) {
this.sendCBMsg(isLessThan10_8_5 ? 40 : 61, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgDescriptorHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].descriptors[descriptorUuid].handle
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId42' : 'kCBMsgId63', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var descriptorHandle = args.kCBMsgArgDescriptorHandle;
var result = args.kCBMsgArgResult;
var data = args.kCBMsgArgData;
this.emit('handleRead', peripheralUuid, descriptorHandle, data);
for(var i in this._peripherals[peripheralHandle].services) {
for(var j in this._peripherals[peripheralHandle].services[i].characteristics) {
if (this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors &&
this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors[descriptorHandle]) {
this.emit('valueRead', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[j].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors[descriptorHandle].uuid, data);
return; // break;
}
}
}
});
nobleBindings.writeValue = function(peripheralUuid, serviceUuid, characteristicUuid, descriptorUuid, data) {
this.sendCBMsg(isLessThan10_8_5 ? 41 : 62, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgDescriptorHandle: this._peripherals[peripheralUuid].services[serviceUuid].characteristics[characteristicUuid].descriptors[descriptorUuid].handle,
kCBMsgArgData: data
});
};
nobleBindings.on(isLessThan10_8_5 ? 'kCBMsgId43' : 'kCBMsgId64', function(args) {
var peripheralHandle = args.kCBMsgArgPeripheralHandle;
var peripheralUuid = this._peripherals[peripheralHandle].uuid;
var descriptorHandle = args.kCBMsgArgDescriptorHandle;
var result = args.kCBMsgArgResult;
this.emit('handleWrite', peripheralUuid, descriptorHandle);
for(var i in this._peripherals[peripheralHandle].services) {
for(var j in this._peripherals[peripheralHandle].services[i].characteristics) {
if (this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors &&
this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors[descriptorHandle]) {
this.emit('valueWrite', peripheralUuid, this._peripherals[peripheralHandle].services[i].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[j].uuid,
this._peripherals[peripheralHandle].services[i].characteristics[j].descriptors[descriptorHandle].uuid);
return; // break;
}
}
}
});
nobleBindings.readHandle = function(peripheralUuid, handle) {
this.sendCBMsg(isLessThan10_8_5 ? 40 : 61, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgDescriptorHandle: handle
});
};
nobleBindings.writeHandle = function(peripheralUuid, handle, data, withoutResponse) {
// TODO: use without response
this.sendCBMsg(isLessThan10_8_5 ? 41 : 62, {
kCBMsgArgPeripheralHandle: this._peripherals[peripheralUuid].handle,
kCBMsgArgDescriptorHandle: handle,
kCBMsgArgData: data
});
};
module.exports = nobleBindings;