Created
October 18, 2017 09:03
-
-
Save IvanSanchez/7e4d796616f4dfd85598bf0b1d627a25 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var noble = require('noble'); | |
noble.on('stateChange', (state)=>{ | |
console.log(state); | |
if (state === 'poweredOn') { | |
noble.startScanning(); | |
} else { | |
noble.stopScanning(); | |
} | |
}); | |
noble.on('warning', function(warning) { | |
console.warn('Warning: ', warning); | |
}); | |
noble.on('discover', function(peripheral) { | |
console.log( | |
"Found device with local name: ", peripheral.advertisement.localName, | |
" address ", peripheral.addressType, peripheral.address, | |
" service UUIDS ", peripheral.advertisement.serviceUuids, | |
" RSSI ", peripheral.rssi, | |
"\n" ); | |
// If the device is advertising a Nordic Secure DFU (0xfe59) service... | |
// if (peripheral.advertisement.serviceUuids.indexOf('fe59') !== 1){ | |
// Check if the device is advertiing a "DfuTest" name. | |
if (peripheral.advertisement.localName === 'DfuTest'){ | |
noble.stopScanning(); | |
peripheral.connect(onConnect.bind(peripheral)); | |
} | |
}); | |
function onConnect(err) { | |
if (err) { throw err; } | |
// Discover the DFU service | |
this.discoverServices(['fe59'], onDiscoverServices); | |
} | |
function onDiscoverServices(err, services) { | |
if (err) { throw err; } | |
var dfuService = services[0]; | |
// Discover the two characteristics of the DFU service | |
dfuService.discoverCharacteristics(null, onDiscoverCharacteristics); | |
} | |
function onDiscoverCharacteristics(err, characteristics) { | |
if (err) { throw err; } | |
// console.log(characteristics); | |
var controlEndpoint = characteristics.filter(function(i){ | |
return i.uuid === '8ec90001f3154f609fb8838830daea50' | |
})[0]; | |
var dataEndpoint = characteristics.filter(function(i){ | |
return i.uuid === '8ec90002f3154f609fb8838830daea50' | |
})[0]; | |
// Change this value to receive notifications more/less often | |
var prn = 0x10; | |
controlEndpoint.subscribe(function() { | |
sendBytes(controlEndpoint, false, [ | |
0x02, // 0x02 = "Set PRN" command. We expect a notification through the | |
prn, 0x00, // control characteristic every PRN (little-endian) data packets | |
]) | |
.then(function(){ | |
return waitForBytes(controlEndpoint); // Should receive 0x60 0x02 0x01. | |
}) | |
.then(function(){ | |
return sendBytes(controlEndpoint, false, [ | |
0x01, // 0x01 = "Create object". The target should allocate ... | |
0x01, // ...in the command region (0x01) a buffer... | |
0xFF, 0x00, 0x00, 0x00 // ... of 0x000000FF (little-endian) bytes. | |
]); | |
}) | |
.then(function(){ | |
return waitForBytes(controlEndpoint); // Should receive 0x60 0x01 0x01. | |
}) | |
.then(function(){ return sendDataBlock(controlEndpoint, dataEndpoint, prn); }) | |
.then(function(){ return sendDataBlock(controlEndpoint, dataEndpoint, prn); }) | |
.then(function(){ return sendDataBlock(controlEndpoint, dataEndpoint, prn); }) | |
.then(function(){ return process.exit(0); }) | |
}); | |
} | |
// Returns a Promise | |
function sendBytes(endpoint, writeWithoutResponse, bytes) { | |
bytes = new Buffer(bytes); | |
// Uncomment the timeout to add a synthetic delay | |
return new Promise(function(res, rej){ | |
// setTimeout(function() { | |
endpoint.write(bytes, writeWithoutResponse, function(err) { | |
if (writeWithoutResponse) { | |
console.log(' data --> ', bytes); | |
} else { | |
console.log(' cmnd --> ', bytes); | |
} | |
if (err) rej(err); else res(); | |
}); | |
// }, 250); | |
}); | |
} | |
// Returns a Promise | |
function waitForBytes(endpoint) { | |
return new Promise(function(res, rej){ | |
endpoint.once('data', function(bytes) { | |
console.log(' recv <-- ', bytes); | |
res(bytes); | |
}); | |
}); | |
} | |
// Sends a bunch of data blocks and then waits for a notification. | |
function sendDataBlock(controlEndpoint, dataEndpoint, prnLeft) { | |
if (prnLeft <= 0) { | |
return waitForBytes(controlEndpoint); // Should receive 0x60 0x03 [offset] [crc] | |
} | |
return sendBytes(dataEndpoint, true, [1,2,3,4,5,6,7,8]) | |
.then(function(){ | |
return sendDataBlock(controlEndpoint, dataEndpoint, prnLeft - 1); | |
}) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment