microblue
Version:
An easy solution to communicate with your micro:bit by bluetooth
170 lines (148 loc) • 7.16 kB
JavaScript
var noble = require('noble');
var uartServiceUuid = '6e400001b5a3f393e0a9e50e24dcca9e';
var uartReadCharacteristicUuid = '6e400002b5a3f393e0a9e50e24dcca9e';
var uartWriteCharacteristicUuid = '6e400003b5a3f393e0a9e50e24dcca9e';
var accelerometerServiceUuid = 'e95d0753251d470aa062fa1922dfa9a8';
var accelerometerDataCharacteristicUuid = 'e95dca4b251d470aa062fa1922dfa9a8';
var magnetometerServiceUuid = 'e95df2d8251d470aa062fa1922dfa9a8';
var magnetometerDataCharacteristicUuid = 'e95dfb11251d470aa062fa1922dfa9a8';
var serviceUUIDs = [uartServiceUuid, accelerometerServiceUuid, magnetometerServiceUuid];
var characteristicUUIDs = [uartReadCharacteristicUuid, uartWriteCharacteristicUuid, accelerometerDataCharacteristicUuid, magnetometerDataCharacteristicUuid];
var uartService = null;
var uartReadCharacteristic = null;
var uartWriteCharacteristic = null;
var accelerometerService = null;
var accelerometerDataCharacteristic = null;
var magnetometerService = null;
var magnetometerDataCharacteristic = null;
var connect = function(callback){
noble.on('stateChange', function(state){
if(state === 'poweredOn'){
noble.startScanning();
}
else{
noble.stopScanning();
}
});
//console.log("microblue: try to discover micro:bit...");
noble.on('discover', function(peripheral){
//console.log("microblue find: " + peripheral.address + " " + peripheral.advertisement.localName);
if(peripheral.advertisement.localName != undefined){
if(peripheral.advertisement.localName.indexOf("BBC micro:bit") > -1){
noble.stopScanning();
peripheral.connect(function(err){
if(err){
console.log('microblue warning: please check if your device is paired with a micro:bit');
console.log('microblue help: if you are already paired try to restart the bluetooth with the command "sudo service bluetooth restart" && "sudo systemctl daemon-reload"');
process.exit();
}
peripheral.discoverServices(serviceUUIDs, function(err,services){
if(err){
console.log('microblue error: Discover Services failed');
}
services.forEach(function(service){
service.discoverCharacteristics(characteristicUUIDs, function(err, characteristics){
if(err){
console.log('microblue error: Discover characteristics failed');
}
characteristics.forEach(function(characteristic){
//console.log(characteristic.uuid);
if(uartReadCharacteristicUuid == characteristic.uuid){
uartReadCharacteristic = characteristic;
}else if(uartWriteCharacteristicUuid == characteristic.uuid){
uartWriteCharacteristic = characteristic;
}else if(accelerometerDataCharacteristicUuid == characteristic.uuid){
accelerometerDataCharacteristic = characteristic;
}else if(magnetometerDataCharacteristicUuid == characteristic.uuid){
magnetometerDataCharacteristic = characteristic;
}
});
});
});
});
setTimeout(function(){
//console.log("callback");
callback();
}, 500);
process.on('SIGINT', function(){
console.log("Caught interrupt signal");
console.log("microblue warning: disconnect..");
peripheral.disconnect(function(err){
if(err){
console.log('microblue error: failed to disconnect the microbit');
}else{
process.exit();
}
});
});
});
}
}
});
}
var read = function(callback){
if(uartReadCharacteristic == null){
console.log("microblue error: uart service not open");
}else{
uartReadCharacteristic.subscribe(function(err){
uartReadCharacteristic.read(function(err, data){
uartReadCharacteristic.unsubscribe();
callback(data.toString());
});
});
}
}
var write = function(buffer){
if(uartWriteCharacteristic == null){
console.log("microblue error: uart service not open");
}else{
var LF = new Buffer(1);
LF[0] = 0x0A;
uartWriteCharacteristic.write(buffer, true);
uartWriteCharacteristic.write(LF, true);
}
}
var accelerometer = function(callback){
if(accelerometerDataCharacteristic == null){
console.log("microblue error: accelerometer service not open");
}else{
accelerometerDataCharacteristic.subscribe(function(err){
accelerometerDataCharacteristic.read(function(err, data){
accelerometerDataCharacteristic.unsubscribe();
x = data[0] | (data[1] << 8);
y = data[2] | (data[3] << 8);
z = data[4] | (data[5] << 8);
if(x & (1 << 16 - 1)){ x = x - (1<<16); }
if(y & (1 << 16 - 1)){ y = y - (1<<16); }
if(z & (1 << 16 - 1)){ z = z - (1<<16); }
callback({'x':x,'y':y,'z':z});
});
});
}
}
var compass = function(callback){
if(magnetometerDataCharacteristic == null){
console.log("microblue error: magnetometer service not open");
}else{
magnetometerDataCharacteristic.subscribe(function(err){
magnetometerDataCharacteristic.read(function(err, data){
magnetometerDataCharacteristic.unsubscribe();
x = data[0] | (data[1] << 8);
y = data[2] | (data[3] << 8);
z = data[4] | (data[5] << 8);
if(x & (1 << 16 - 1)){ x = x - (1<<16); }
if(y & (1 << 16 - 1)){ y = y - (1<<16); }
if(z & (1 << 16 - 1)){ z = z - (1<<16); }
x = x / 1000;
y = y / 1000;
z = z / 1000;
callback({'x':x,'y':y, 'z':z});
});
});
}
}
exports.connect = connect;
exports.read = read;
exports.write = write;
exports.accelerometer = accelerometer;
exports.compass = compass;