@abandonware/noble
Version:
A Node.js BLE (Bluetooth Low Energy) central library.
1,436 lines (1,180 loc) • 66 kB
JavaScript
const should = require('should');
const sinon = require('sinon');
const proxyquire = require('proxyquire').noCallThru();
const { assert } = sinon;
describe('hci-socket hci', () => {
const deviceId = 'deviceId';
const Socket = sinon.stub();
const Hci = proxyquire('../../../lib/hci-socket/hci', {
'@abandonware/bluetooth-hci-socket': Socket
});
let hci;
beforeEach(() => {
Socket.prototype.on = sinon.stub();
Socket.prototype.bindUser = sinon.stub();
Socket.prototype.bindRaw = sinon.stub();
Socket.prototype.start = sinon.stub();
Socket.prototype.isDevUp = sinon.stub();
Socket.prototype.removeAllListeners = sinon.stub();
Socket.prototype.setFilter = sinon.stub();
Socket.prototype.write = sinon.stub();
hci = new Hci({});
hci._deviceId = deviceId;
});
afterEach(() => {
sinon.reset();
});
describe('init', () => {
it('should reset', () => {
hci.reset = sinon.spy();
hci._userChannel = 'userChannel';
hci.init();
assert.callCount(hci._socket.on, 2);
assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
assert.calledOnceWithExactly(hci._socket.bindUser, deviceId);
assert.calledOnceWithExactly(hci._socket.start);
assert.calledOnceWithExactly(hci.reset);
});
it('should bindRaw', () => {
hci.pollIsDevUp = sinon.spy();
hci._userChannel = undefined;
hci._bound = false;
hci.init();
assert.callCount(hci._socket.on, 2);
assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
assert.calledOnceWithExactly(hci._socket.bindRaw, deviceId);
assert.calledOnceWithExactly(hci._socket.start);
assert.calledOnceWithExactly(hci.pollIsDevUp);
should(hci._bound).be.true();
});
it('should not bindRaw', () => {
hci.pollIsDevUp = sinon.spy();
hci._userChannel = undefined;
hci._bound = true;
hci.init();
assert.callCount(hci._socket.on, 2);
assert.calledWithMatch(hci._socket.on, 'data', sinon.match.func);
assert.calledWithMatch(hci._socket.on, 'error', sinon.match.func);
assert.notCalled(hci._socket.bindRaw);
assert.calledOnceWithExactly(hci._socket.start);
assert.calledOnceWithExactly(hci.pollIsDevUp);
should(hci._bound).be.true();
});
});
describe('pollIsDevUp', () => {
let callback;
beforeEach(() => {
sinon.useFakeTimers();
callback = sinon.spy();
hci.setSocketFilter = sinon.spy();
hci.setEventMask = sinon.spy();
hci.setLeEventMask = sinon.spy();
hci.readLocalVersion = sinon.spy();
hci.writeLeHostSupported = sinon.spy();
hci.readLeHostSupported = sinon.spy();
hci.readLeBufferSize = sinon.spy();
hci.readBdAddr = sinon.spy();
hci.init = sinon.spy();
hci.setCodedPhySupport = sinon.spy();
hci.on('stateChange', callback);
});
afterEach(() => {
sinon.restore();
sinon.reset();
});
it('should only register timeout', () => {
hci._socket.isDevUp.returns(true);
hci._isDevUp = true;
hci.pollIsDevUp();
assert.notCalled(hci.setSocketFilter);
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.writeLeHostSupported);
assert.notCalled(hci.readLeHostSupported);
assert.notCalled(hci.readLeBufferSize);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(hci.init);
assert.notCalled(callback);
});
it('should re-init', () => {
hci._socket.isDevUp.returns(true);
hci._isDevUp = false;
hci._state = 'poweredOff';
hci.pollIsDevUp();
should(hci._state).equal(null);
assert.calledOnceWithExactly(hci._socket.removeAllListeners);
assert.calledOnceWithExactly(hci.init);
assert.notCalled(hci.setSocketFilter);
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.writeLeHostSupported);
assert.notCalled(hci.readLeHostSupported);
assert.notCalled(hci.readLeBufferSize);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(callback);
});
it('should init all', () => {
hci._socket.isDevUp.returns(true);
hci._isDevUp = false;
hci._state = undefined;
hci.pollIsDevUp();
assert.calledOnceWithExactly(hci.setSocketFilter);
assert.calledOnceWithExactly(hci.setEventMask);
assert.calledOnceWithExactly(hci.setLeEventMask);
assert.calledOnceWithExactly(hci.readLocalVersion);
assert.calledOnceWithExactly(hci.writeLeHostSupported);
assert.calledOnceWithExactly(hci.readLeHostSupported);
assert.calledOnceWithExactly(hci.readLeBufferSize);
assert.calledOnceWithExactly(hci.readBdAddr);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(hci._socket.removeAllListeners);
assert.notCalled(hci.init);
assert.notCalled(callback);
});
it('should init all with extended option', () => {
hci._socket.isDevUp.returns(true);
hci._isDevUp = false;
hci._state = undefined;
hci._isExtended = true;
hci.pollIsDevUp();
assert.calledOnceWithExactly(hci.setSocketFilter);
assert.calledOnceWithExactly(hci.setEventMask);
assert.calledOnceWithExactly(hci.setLeEventMask);
assert.calledOnceWithExactly(hci.readLocalVersion);
assert.calledOnceWithExactly(hci.writeLeHostSupported);
assert.calledOnceWithExactly(hci.readLeHostSupported);
assert.calledOnceWithExactly(hci.readLeBufferSize);
assert.calledOnceWithExactly(hci.readBdAddr);
assert.calledOnceWithExactly(hci.setCodedPhySupport);
assert.notCalled(hci._socket.removeAllListeners);
assert.notCalled(hci.init);
assert.notCalled(callback);
});
it('should emit stateChange', () => {
hci._socket.isDevUp.returns(false);
hci._isDevUp = true;
hci.pollIsDevUp();
assert.calledOnceWithExactly(callback, 'poweredOff');
assert.notCalled(hci._socket.removeAllListeners);
assert.notCalled(hci.init);
assert.notCalled(hci.setSocketFilter);
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.writeLeHostSupported);
assert.notCalled(hci.readLeHostSupported);
assert.notCalled(hci.readLeBufferSize);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setCodedPhySupport);
});
});
it('should write codedPhySupport command', () => {
hci.setCodedPhySupport();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x31, 0x20, 0x03, 0x00, 0x05, 0x05]));
});
it('should write randomMAC command', () => {
hci.setRandomMAC();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x05, 0x20, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00]));
});
it('should setSocketFilter', () => {
hci.setSocketFilter();
assert.calledOnceWithExactly(hci._socket.setFilter, Buffer.from([0x16, 0, 0, 0, 0x20, 0xc1, 0x08, 0, 0, 0, 0, 0x40, 0, 0, 0, 0]));
});
it('should setEventMask', () => {
hci.setEventMask();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x0c, 0x08, 0xff, 0xff, 0xfb, 0xff, 0x07, 0xf8, 0xbf, 0x3d]));
});
it('should reset', () => {
hci.reset();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 3, 0x0c, 0]));
});
it('should readSupportedCommands', () => {
hci.readSupportedCommands();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x02, 0x10, 0x00]));
});
it('should readLocalVersion', () => {
hci.readLocalVersion();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x10, 0]));
});
it('should readBufferSize', () => {
hci.readBufferSize();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 5, 0x10, 0]));
});
it('should readBdAddr', () => {
hci.readBdAddr();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 9, 0x10, 0]));
});
describe('setLeEventMask', () => {
it('should setLeEventMask', () => {
hci.setLeEventMask();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x20, 8, 0x1f, 0, 0, 0, 0, 0, 0, 0]));
});
it('should setLeEventMask for BLE5 (extended)', () => {
hci._isExtended = true;
hci.setLeEventMask();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 1, 0x20, 8, 0x1f, 0xff, 0, 0, 0, 0, 0, 0]));
});
});
it('should readLeBufferSize', () => {
hci.readLeBufferSize();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 2, 0x20, 0]));
});
it('should readLeHostSupported', () => {
hci.readLeHostSupported();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x6c, 0x0c, 0]));
});
it('should writeLeHostSupported', () => {
hci.writeLeHostSupported();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x6d, 0x0c, 2, 1, 0]));
});
describe('setScanParameters', () => {
it('should keep default parameters', () => {
hci.setScanParameters();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0b, 0x20, 7, 1, 0x12, 0, 0x12, 0, 0, 0]));
});
it('should keep default parameters (extended)', () => {
hci._isExtended = true;
hci.setScanParameters();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x41, 0x20, 0x0d, 0x00, 0x00, 0x05, 0x01, 0x12, 0x00, 0x12, 0x00, 0x01, 0x12, 0x00, 0x12, 0x00]));
});
it('should force parameters', () => {
hci.setScanParameters(0x2222, 0x3333);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0b, 0x20, 7, 1, 0x22, 0x022, 0x33, 0x33, 0, 0]));
});
it('should force parameters (extended)', () => {
hci._isExtended = true;
hci.setScanParameters(0x2222, 0x3333);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x41, 0x20, 0x0d, 0x00, 0x00, 0x05, 0x01, 0x22, 0x22, 0x33, 0x33, 0x01, 0x22, 0x22, 0x33, 0x33]));
});
});
describe('setScanEnabled', () => {
it('should keep default parameters', () => {
hci.setScanEnabled();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0c, 0x20, 2, 0, 0]));
});
it('should keep default parameters (extended)', () => {
hci._isExtended = true;
hci.setScanEnabled();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x42, 0x20, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]));
});
it('should force parameters', () => {
hci.setScanEnabled(true, true);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x0c, 0x20, 2, 1, 1]));
});
it('should force parameters (extended)', () => {
hci._isExtended = true;
hci.setScanEnabled(true, true);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([1, 0x42, 0x20, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00]));
});
});
describe('createLeConn', () => {
it('should keep default parameters', () => {
const address = 'aa:bb:cc:dd:ee';
const addressType = 'random';
hci.createLeConn(address, addressType);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0d, 0x20, 0x19, 0x60, 0x00, 0x30, 0x00, 0x00, 0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x00, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x04, 0x00, 0x06, 0x00]));
});
it('should keep default parameters (extended)', () => {
const address = 'aa:bb:cc:dd:ee';
const addressType = 'random';
hci._isExtended = true;
hci.createLeConn(address, addressType);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x43, 0x20, 0x2a, 0x00, 0x00, 0x01, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x00, 0x05, 0x60, 0x00, 0x60, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x06, 0x00, 0x12, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00]));
});
it('should override default parameters', () => {
const address = 'ee:dd:cc:bb:aa';
const addressType = 'not_random';
const parameters = { minInterval: 0x0060, maxInterval: 0x00c0, latency: 0x0010, timeout: 0x0c80 };
hci.createLeConn(address, addressType, parameters);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0d, 0x20, 0x19, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x04, 0x00, 0x06, 0x00]));
});
it('should override default parameters (extended)', () => {
const address = 'ee:dd:cc:bb:aa';
const addressType = 'not_random';
const parameters = { minInterval: 0x0060, maxInterval: 0x00c0, latency: 0x0010, timeout: 0x0c80 };
hci._isExtended = true;
hci.createLeConn(address, addressType, parameters);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x43, 0x20, 0x2a, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x05, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x10, 0x00, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00]));
});
});
it('should write connUpdateLe', () => {
const handle = 0x1234;
const minInterval = 5;
const maxInterval = 15;
const latency = 12;
const supervisionTimeout = 25;
hci.connUpdateLe(handle, minInterval, maxInterval, latency, supervisionTimeout);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x13, 0x20, 0x0e, 0x34, 0x12, 0x04, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00]));
});
it('should write cancelConnect', () => {
hci.cancelConnect();
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x0e, 0x20, 0x00]));
});
it('should write startLeEncryption', () => {
const handle = 0x1234;
const random = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);
const diversifier = Buffer.from([11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 23, 24, 25]);
const key = Buffer.from([31, 32, 33, 34, 35, 36, 37, 38, 39, 30, 31, 32, 33, 33, 34, 35]);
hci.startLeEncryption(handle, random, diversifier, key);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x19, 0x20, 0x1c, 0x34, 0x12, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0b, 0x0c, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x1e, 0x1f, 0x20, 0x21, 0x21, 0x22, 0x23]));
});
describe('disconnect', () => {
it('should write disconnect with defaults', () => {
const handle = 0x1234;
const reason = undefined;
hci.disconnect(handle, reason);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0x04, 0x03, 0x34, 0x12, 0x13]));
});
it('should write disconnect with reason', () => {
const handle = 0x1234;
const reason = 17;
hci.disconnect(handle, reason);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x06, 0x04, 0x03, 0x34, 0x12, 0x11]));
});
});
it('should write readRssi', () => {
const handle = 0x1234;
hci.readRssi(handle);
assert.calledOnceWithExactly(hci._socket.write, Buffer.from([0x01, 0x05, 0x14, 0x02, 0x34, 0x12]));
});
it('should writeAclDataPkt - push in aclQueue and flushAcl', async () => {
hci.flushAcl = sinon.spy();
hci._aclBuffers = [1, 2, 3, 4, 5, 6, 7, 8];
const handle = 0x1234;
const cid = 345;
const data = Buffer.from([5, 6, 7, 8, 9, 10, 11]);
await hci.writeAclDataPkt(handle, cid, data);
assert.calledOnceWithExactly(hci.flushAcl);
should(hci._aclQueue).deepEqual([
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
},
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
}
]);
});
describe('flushAcl', () => {
it('should not write flush on no pending connections', () => {
const queue = [
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
},
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
}
];
hci._aclQueue = [...queue];
hci.flushAcl();
assert.notCalled(hci._socket.write);
should(hci._aclQueue).deepEqual(queue);
});
it('should not write flush on empty queue', () => {
hci._aclQueue = [];
hci._aclConnections.set(4660, { pending: 3 });
hci._aclConnections.set(4661, { pending: 2 });
hci._aclBuffers = { num: 12 };
hci.flushAcl();
assert.notCalled(hci._socket.write);
should(hci._aclQueue).be.empty();
});
it('should not write flush on not enough pending connections', () => {
const queue = [
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
},
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
}
];
hci._aclQueue = [...queue];
hci._aclConnections.set(4660, { pending: 3 });
hci._aclConnections.set(4661, { pending: 2 });
hci._aclBuffers = { num: 1 };
hci.flushAcl();
assert.notCalled(hci._socket.write);
should(hci._aclQueue).deepEqual(queue);
});
it('should write flush', async () => {
const queue = [
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
},
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
},
{
handle: 4661,
packet: Buffer.from([0x02])
}
];
hci._aclQueue = [...queue];
hci._aclConnections.set(4660, { pending: 3 });
hci._aclConnections.set(4661, { pending: 2 });
hci._aclBuffers = { num: 12 };
await hci.flushAcl();
assert.callCount(hci._socket.write, 3);
assert.calledWithExactly(hci._socket.write, Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08]));
assert.calledWithExactly(hci._socket.write, Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b]));
assert.calledWithExactly(hci._socket.write, Buffer.from([0x02]));
should(hci._aclQueue).be.empty();
});
});
describe('onSocketData', () => {
const aclQueue = [
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x08, 0x00, 0x07, 0x00, 0x59, 0x01, 0x05, 0x06, 0x07, 0x08])
},
{
handle: 4660,
packet: Buffer.from([0x02, 0x34, 0x12, 0x03, 0x00, 0x09, 0x0a, 0x0b])
},
{
handle: 4661,
packet: Buffer.from([0x02])
}
];
let disconnCompleteCallback;
let encryptChangeCallback;
let aclDataPktCallback;
let leScanEnableSetCmdCallback;
beforeEach(() => {
hci.flushAcl = sinon.spy();
hci.processCmdCompleteEvent = sinon.spy();
hci.processCmdStatusEvent = sinon.spy();
hci.processLeMetaEvent = sinon.spy();
hci._aclQueue = [...aclQueue];
hci._aclConnections.set(4660, { pending: 3 });
hci._aclConnections.set(4661, { pending: 2 });
disconnCompleteCallback = sinon.spy();
encryptChangeCallback = sinon.spy();
aclDataPktCallback = sinon.spy();
leScanEnableSetCmdCallback = sinon.spy();
hci.on('disconnComplete', disconnCompleteCallback);
hci.on('encryptChange', encryptChangeCallback);
hci.on('aclDataPkt', aclDataPktCallback);
hci.on('leScanEnableSetCmd', leScanEnableSetCmdCallback);
});
afterEach(() => {
sinon.reset();
});
it('should flushAcl - HCI_EVENT_PKT / EVT_DISCONN_COMPLETE', () => {
const eventType = 4;
const subEventType = 5;
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(hci.flushAcl);
assert.calledOnceWithExactly(disconnCompleteCallback, 4660, 3);
// not called
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual([
{
handle: 4661,
packet: Buffer.from([0x02])
}
]);
should(hci._aclConnections).have.keys(4661);
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only emit encryptChange - HCI_EVENT_PKT / EVT_ENCRYPT_CHANGE', () => {
const eventType = 4;
const subEventType = 8;
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(encryptChangeCallback, 4660, 3);
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only processCmdCompleteEvent - HCI_EVENT_PKT / EVT_CMD_COMPLETE', () => {
const eventType = 4;
const subEventType = 14;
const data = Buffer.from([eventType, subEventType, 0, 0, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(hci.processCmdCompleteEvent, 4660, 3, Buffer.from([9, 9]));
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only processCmdStatusEvent - HCI_EVENT_PKT / EVT_CMD_STATUS', () => {
const eventType = 4;
const subEventType = 15;
const data = Buffer.from([eventType, subEventType, 4, 2, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(hci.processCmdStatusEvent, 786, 2);
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only processLeMetaEvent - HCI_EVENT_PKT / EVT_LE_META_EVENT', () => {
const eventType = 4;
const subEventType = 62;
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(hci.processLeMetaEvent, 1, 52, Buffer.from([0x12, 3, 9, 9]));
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only flushAcl - HCI_EVENT_PKT / EVT_NUMBER_OF_COMPLETED_PACKETS', () => {
const eventType = 4;
const subEventType = 19;
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(hci.flushAcl);
// not called
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 0 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should do nothing - HCI_EVENT_PKT / ??', () => {
const eventType = 4;
const subEventType = 122;
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should only emit aclDataPkt - HCI_ACLDATA_PKT / ACL_START', () => {
const eventType = 2;
const subEventTypeP1 = 0xf2;
const subEventTypeP2 = 0x24;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8, 7]);
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(aclDataPktCallback, 1266, 2307, Buffer.from([9, 8, 7]));
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
should(hci._handleBuffers).be.empty();
});
it('should register handle buffer - HCI_ACLDATA_PKT / ACL_START', () => {
const eventType = 2;
const subEventTypeP1 = 0xf2;
const subEventTypeP2 = 0x24;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
hci.onSocketData(data);
// called
// not called
assert.notCalled(aclDataPktCallback);
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
should(hci._handleBuffers).deepEqual({
1266: {
length: 3,
cid: 2307,
data: Buffer.from([9, 8])
}
});
});
it('should do nothing - HCI_ACLDATA_PKT / ACL_CONT', () => {
const eventType = 2;
const subEventTypeP1 = 0xf2;
const subEventTypeP2 = 0x14;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
hci.onSocketData(data);
// called
// not called
assert.notCalled(aclDataPktCallback);
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
should(hci._handleBuffers).be.empty();
});
it('should concat data - HCI_ACLDATA_PKT / ACL_CONT', () => {
const eventType = 2;
const subEventTypeP1 = 0xf2;
const subEventTypeP2 = 0x14;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
const handleBuffers = {
1266: {
length: 3,
cid: 2307,
data: Buffer.from([3, 4])
}
};
hci._handleBuffers = handleBuffers;
hci.onSocketData(data);
// called
// not called
assert.notCalled(aclDataPktCallback);
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
should(hci._handleBuffers).deepEqual({
1266: {
length: 3,
cid: 2307,
data: Buffer.from([3, 4, 3, 0, 3, 9, 9, 8])
}
});
});
it('should concat data and emit aclDataPkt - HCI_ACLDATA_PKT / ACL_CONT', () => {
const eventType = 2;
const subEventTypeP1 = 0xf2;
const subEventTypeP2 = 0x14;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x12, 0x03, 0x00, 3, 9, 9, 8]);
const handleBuffers = {
1266: {
length: 8,
cid: 2307,
data: Buffer.from([3, 4])
}
};
hci._handleBuffers = handleBuffers;
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(aclDataPktCallback, 1266, 2307, Buffer.from([3, 4, 3, 0, 3, 9, 9, 8]));
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
should(hci._handleBuffers).be.empty();
});
it('should do nothing - HCI_ACLDATA_PKT / ??', () => {
const eventType = 2;
const subEventType = 122;
const data = Buffer.from([eventType, subEventType, 0, 1, 0x34, 0x12, 3, 9, 9]);
hci.onSocketData(data);
// called
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
assert.notCalled(leScanEnableSetCmdCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
should(hci._aclConnections.get(4660)).deepEqual({ pending: 3 });
should(hci._aclConnections.get(4661)).deepEqual({ pending: 2 });
});
it('should emit leScanEnableSetCmd - HCI_COMMAND_PKT / LE_SET_SCAN_ENABLE_CMD', () => {
const eventType = 1;
const subEventTypeP1 = 0x0c;
const subEventTypeP2 = 0x20;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
const handleBuffers = {
1266: {
length: 8,
cid: 2307,
data: Buffer.from([3, 4])
}
};
hci._handleBuffers = handleBuffers;
hci.onSocketData(data);
// called
assert.calledOnceWithExactly(leScanEnableSetCmdCallback, true, false);
// not called
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
});
it('should not emit leScanEnableSetCmd - HCI_COMMAND_PKT / ???', () => {
const eventType = 1;
const subEventTypeP1 = 0x0c;
const subEventTypeP2 = 0x21;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
const handleBuffers = {
1266: {
length: 8,
cid: 2307,
data: Buffer.from([3, 4])
}
};
hci._handleBuffers = handleBuffers;
hci.onSocketData(data);
// called
// not called
assert.notCalled(leScanEnableSetCmdCallback);
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
});
it('should do nothing - ?? / ???', () => {
const eventType = 122;
const subEventTypeP1 = 0x0c;
const subEventTypeP2 = 0x21;
const data = Buffer.from([eventType, subEventTypeP1, subEventTypeP2, 0x34, 0x01, 0]);
const handleBuffers = {
1266: {
length: 8,
cid: 2307,
data: Buffer.from([3, 4])
}
};
hci._handleBuffers = handleBuffers;
hci.onSocketData(data);
// called
// not called
assert.notCalled(leScanEnableSetCmdCallback);
assert.notCalled(hci.flushAcl);
assert.notCalled(hci.processLeMetaEvent);
assert.notCalled(encryptChangeCallback);
assert.notCalled(hci.processCmdCompleteEvent);
assert.notCalled(disconnCompleteCallback);
assert.notCalled(aclDataPktCallback);
// hci checks
should(hci._aclQueue).deepEqual(aclQueue);
should(hci._aclConnections).have.keys(4660, 4661);
});
});
describe('onSocketError', () => {
it('should emit stateChange', () => {
const callback = sinon.spy();
hci.on('stateChange', callback);
hci.onSocketError({ code: 'EPERM', message: 'Network is down' });
assert.calledOnceWithExactly(callback, 'unauthorized');
});
it('should do nothing with message', () => {
const callback = sinon.spy();
hci.on('stateChange', callback);
hci.onSocketError({ message: 'Network is down' });
assert.notCalled(callback);
});
it('should do nothing', () => {
const callback = sinon.spy();
hci.on('stateChange', callback);
hci.onSocketError({ });
assert.notCalled(callback);
});
});
describe('processCmdCompleteEvent', () => {
const aclBuffers = {
length: 99,
num: 88
};
let rssiReadCallback;
let leScanEnableSetCallback;
let leScanParametersSetCallback;
let stateChangeCallback;
let addressChangeCallback;
let readLocalVersionCallback;
beforeEach(() => {
hci.setEventMask = sinon.spy();
hci.setLeEventMask = sinon.spy();
hci.readLocalVersion = sinon.spy();
hci.readBdAddr = sinon.spy();
hci.setScanEnabled = sinon.spy();
hci.setScanParameters = sinon.spy();
hci.readBufferSize = sinon.spy();
hci.setCodedPhySupport = sinon.spy();
hci._aclBuffers = aclBuffers;
rssiReadCallback = sinon.spy();
leScanEnableSetCallback = sinon.spy();
leScanParametersSetCallback = sinon.spy();
stateChangeCallback = sinon.spy();
addressChangeCallback = sinon.spy();
readLocalVersionCallback = sinon.spy();
hci.on('rssiRead', rssiReadCallback);
hci.on('leScanEnableSet', leScanEnableSetCallback);
hci.on('leScanParametersSet', leScanParametersSetCallback);
hci.on('stateChange', stateChangeCallback);
hci.on('addressChange', addressChangeCallback);
hci.on('readLocalVersion', readLocalVersionCallback);
});
it('should do nothing', () => {
const cmd = 0;
const status = 0;
const result = Buffer.from([]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(addressChangeCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should reset', () => {
const cmd = 3075;
const status = 0;
const result = Buffer.from([]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(hci.setEventMask);
assert.calledOnceWithExactly(hci.setLeEventMask);
assert.calledOnceWithExactly(hci.readLocalVersion);
assert.calledOnceWithExactly(hci.readBdAddr);
// not called
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(addressChangeCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should reset (extended)', () => {
const cmd = 3075;
const status = 0;
const result = Buffer.from([]);
hci._isExtended = true;
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(hci.setEventMask);
assert.calledOnceWithExactly(hci.setLeEventMask);
assert.calledOnceWithExactly(hci.readLocalVersion);
assert.calledOnceWithExactly(hci.readBdAddr);
assert.calledOnceWithExactly(hci.setCodedPhySupport);
// not called
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(addressChangeCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(true);
});
it('should only log debug - READ_LE_HOST_SUPPORTED_CMD', () => {
const cmd = 3180;
const status = 0;
const result = Buffer.from([0, 1]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(addressChangeCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should do nothing - READ_LE_HOST_SUPPORTED_CMD', () => {
const cmd = 3180;
const status = 1;
const result = Buffer.from([]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(addressChangeCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should emit stateChange - READ_LOCAL_VERSION_CMD', () => {
const cmd = 4097;
const status = 0;
const result = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(stateChangeCallback, 'unsupported');
assert.calledOnceWithExactly(readLocalVersionCallback, 0, 513, 3, 1284, 1798);
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(addressChangeCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should not emit stateChange - READ_LOCAL_VERSION_CMD', () => {
const cmd = 4097;
const status = 0;
const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(readLocalVersionCallback, 9, 513, 3, 1284, 1798);
assert.calledOnceWithExactly(hci.setScanEnabled, false, true);
assert.calledOnceWithExactly(hci.setScanParameters);
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(addressChangeCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should not scan - READ_LOCAL_VERSION_CMD', () => {
const cmd = 4097;
const status = 0;
const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
hci._state = 'poweredOn';
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(readLocalVersionCallback, 9, 513, 3, 1284, 1798);
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(addressChangeCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
});
it('should change extended - READ_SUPPORTED_COMMANDS_CMD', () => {
const cmd = 4098;
const status = 0;
const result = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 30, 31, 32, 33, 34, 35, 35, 36, 0xff]);
hci._state = 'poweredOn';
hci.processCmdCompleteEvent(cmd, status, result);
// called
// not called
assert.notCalled(readLocalVersionCallback);
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(addressChangeCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(32);
});
it('should emit addressChange - READ_BD_ADDR_CMD', () => {
const cmd = 4105;
const status = 0;
const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
hci.addressType = 'addressType';
hci.address = 'address';
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(addressChangeCallback, '07:06:05:04:03:02:01:09');
// not called
assert.notCalled(hci.setEventMask);
assert.notCalled(hci.setLeEventMask);
assert.notCalled(hci.readLocalVersion);
assert.notCalled(hci.readBdAddr);
assert.notCalled(hci.setScanEnabled);
assert.notCalled(hci.setScanParameters);
assert.notCalled(hci.readBufferSize);
assert.notCalled(hci.setCodedPhySupport);
assert.notCalled(rssiReadCallback);
assert.notCalled(stateChangeCallback);
assert.notCalled(leScanEnableSetCallback);
assert.notCalled(leScanParametersSetCallback);
assert.notCalled(readLocalVersionCallback);
// hci checks
should(hci._aclBuffers).deepEqual(aclBuffers);
should(hci._isExtended).equal(false);
should(hci.addressType).equal('public');
should(hci.address).equal('07:06:05:04:03:02:01:09');
});
[8203, 8257].forEach((cmd) => {
it(`should emit stateChange - LE_SET_SCAN_PARAMETERS_CMD - ${cmd}`, () => {
const status = 0;
const result = Buffer.from([9, 1, 2, 3, 4, 5, 6, 7]);
hci.processCmdCompleteEvent(cmd, status, result);
// called
assert.calledOnceWithExactly(stateChangeCallback, 'poweredOn');
assert.calledOnceWithExactly(leScanParametersSetCallback);
// not called