├── .gitignore ├── API.md ├── LICENSE ├── README.md ├── examples ├── accelerometer-listener.js ├── button-listener.js ├── compass.js ├── discoverer.js ├── event-listener.js ├── led-pattern.js ├── led-text.js ├── magnetometer-bearing-listener.js ├── magnetometer-listener.js ├── pin-blink.js ├── pin-listener.js └── temperature-listener.js ├── firmware └── node-bbc-microbit-v0.1.0.hex ├── index.js ├── lib ├── accelerometer-service.js ├── bbc-microbit.js ├── button-service.js ├── event-service.js ├── io-pin-service.js ├── led-service.js ├── magnetometer-service.js ├── temperature-service.js └── uart-service.js ├── package.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /API.md: -------------------------------------------------------------------------------- 1 | # node-bbc-microbit API 2 | 3 | 1. [Discovery](#discovery) 4 | 1. [Connecting and disconnecting](#connecting-and-disconnecting) 5 | 1. [Accelerometer](#accelerometer) 6 | 1. [Buttons](#buttons) 7 | 1. [Pin IO](#pin-io) 8 | 1. [LED Matrix](#led-matrix) 9 | 1. [Magnetometer](#magnetometer) 10 | 1. [Temperature](#temperature) 11 | 1. [UART](#uart) 12 | 1. [Event](#event-5) 13 | 14 | ## Require module 15 | 16 | ```javascript 17 | var BBCMicrobit = require('bbc-microbit'); 18 | ``` 19 | 20 | ## Discovery 21 | 22 | ### Single 23 | 24 | ```javascript 25 | BBCMicrobit.discover(callback(microbit)); 26 | ``` 27 | 28 | ### All 29 | 30 | ```javascript 31 | function onDiscover(microbit) { 32 | // ... 33 | } 34 | 35 | BBCMicrobit.discoverAll(onDiscover); 36 | 37 | BBCMicrobit.stopDiscoverAll(onDiscover); 38 | ``` 39 | 40 | ### By id 41 | 42 | ```javascript 43 | BBCMicrobit.discoverById(id, callback(microbit)); 44 | ``` 45 | 46 | ### By address 47 | 48 | ```javascript 49 | BBCMicrobit.discoverByAddress(address, callback(microbit)); 50 | ``` 51 | 52 | ### Properties: 53 | 54 | ```javascript 55 | microbit = { 56 | id: "", 57 | address: "" 58 | }; 59 | ``` 60 | 61 | ## Connecting and disconnecting 62 | 63 | ### Connect and Set Up 64 | 65 | ```javascript 66 | microbit.connectAndSetUp(callback(error)); 67 | ``` 68 | 69 | ### Disconnect 70 | 71 | ```javascript 72 | microbit.disconnect(callback); 73 | ``` 74 | 75 | ### Disconnect event 76 | 77 | Add event listener for when micro:bit disconnects: 78 | 79 | ```javascript 80 | microbit.once('disconnect', callback); 81 | ``` 82 | 83 | ## Device Information 84 | 85 | ```javascript 86 | microbit.readDeviceName(callback(error, deviceName)); 87 | 88 | microbit.readModelNumber(callback(error, modelNumber)); 89 | 90 | microbit.readSerialNumber(callback(error, serialNumber)); 91 | 92 | microbit.readFirmwareRevision(callback(error, firmwareRevision)); 93 | 94 | ``` 95 | 96 | ## [Accelerometer](https://lancaster-university.github.io/microbit-docs/ble/accelerometer-service/) 97 | 98 | Units for `x`, `y`, and `z` is G's. 99 | 100 | ### Data period 101 | 102 | Read or write the `period`. Support values are: 1, 2, 5, 10, 20, 80, 160, or 640 ms. 103 | 104 | ```javascript 105 | microbit.readAccelerometerPeriod(callback(error, period)); 106 | 107 | microbit.writeAccelerometerPeriod(period, callback(error)); 108 | ``` 109 | 110 | ### Read 111 | 112 | ```javascript 113 | microbit.readAccelerometer(callback(error, x, y, z)); 114 | ``` 115 | 116 | ### Subscription 117 | 118 | ```javascript 119 | microbit.subscribeAccelerometer(callback(error)); 120 | 121 | microbit.unsubscribeAccelerometer(callback(error)); 122 | ``` 123 | 124 | #### Event 125 | 126 | ```javascript 127 | microbit.on('accelerometerChange', function(x, y, z) { 128 | // ... 129 | }); 130 | ``` 131 | 132 | ## [Buttons](https://lancaster-university.github.io/microbit-docs/ble/button-service/) 133 | 134 | ### Subscription 135 | 136 | ```javascript 137 | // for both buttons 138 | microbit.subscribeButtons(callback(error)); 139 | 140 | microbit.unsubscribeButtons(callback(error)); 141 | 142 | // just button A 143 | microbit.subscribeButtonA(callback(error)); 144 | 145 | microbit.unsubscribeButtonA(callback(error)); 146 | 147 | // just button B 148 | microbit.subscribeButtonB(callback(error)); 149 | 150 | microbit.unsubscribeButtonB(callback(error)); 151 | ``` 152 | 153 | #### Events 154 | 155 | ```javascript 156 | microbit.on('buttonAChange', function(value) { 157 | // ... 158 | }); 159 | 160 | microbit.on('buttonBChange', function(value) { 161 | // ... 162 | }); 163 | ``` 164 | 165 | `value` interpretation: 166 | * `0`: not pressed 167 | * `1`: pressed 168 | * `2`: long press 169 | 170 | # [Pin IO](https://lancaster-university.github.io/microbit-docs/ble/iopin-service/) 171 | 172 | `pin` must be between `0` and `20`. 173 | 174 | `value` must be between `0` and `255`. 175 | 176 | ### Configure modes 177 | 178 | ```javascript 179 | // AD mode 180 | microbit.pinAnalog(pin, callback(error)); 181 | 182 | microbit.pinDigital(pin, callback(error)); 183 | 184 | // IO mode 185 | microbit.pinInput(pin, callback(error)); 186 | 187 | microbit.pinOutput(pin, callback(error)); 188 | ``` 189 | 190 | ### Read or write 191 | 192 | ```javascript 193 | microbit.readPin(pin, callback(error, value)); // pin must be configured as input 194 | 195 | microbit.writePin(pin, value, callback(error)); // pin must be configured as output 196 | ``` 197 | 198 | ### Subscription 199 | 200 | ```javascript 201 | microbit.subscribePinData(callback(error)); 202 | 203 | microbit.unsubscribePinData(callback(error)); 204 | ``` 205 | 206 | #### Event 207 | 208 | ```javascript 209 | microbit.on('pinDataChange', function(pin, value) { 210 | // ... 211 | }); 212 | ``` 213 | 214 | ### Advanced 215 | 216 | ```javascript 217 | // data is a Buffer with format: , ... 218 | microbit.readPinData(callback(error, data)); 219 | 220 | microbit.writePinData(data, callback(error)); 221 | 222 | // value is a buffer, n-bit of 0 means pin n is in digital mode, 1 means analog mode 223 | microbit.readPinAdConfiguration(callback(error, value)); 224 | 225 | microbit.writePinAdConfiguration(value, callback(error)); 226 | 227 | // value is a buffer, n-bit of 0 means pin n is in output mode, 1 means input mode 228 | microbit.readPinIoConfiguration(callback(error, value)); 229 | 230 | microbit.writePinIoConfiguration(value, callback(error)); 231 | ``` 232 | 233 | ## [LED Matrix](https://lancaster-university.github.io/microbit-docs/ble/led-service/) 234 | 235 | ### Read/write raw data 236 | 237 | `value` is a 5 byte Buffer. Each byte corresponds to a row, and column value is the n'th bit. `0` for off, `1` for on. 238 | 239 | ```javascript 240 | microbit.readLedMatrixState(callback(error, value)); 241 | 242 | microbit.writeLedMatrixState(value, callback(error)); 243 | ``` 244 | 245 | ### Write text 246 | 247 | `text` is a string that must be 20 characters or less 248 | 249 | ```javascript 250 | microbit.writeLedText(text, callback(error)); 251 | ``` 252 | 253 | #### Text scrolling delay 254 | 255 | `delay` is scrolling delay of text in ms. 256 | 257 | ```javascript 258 | microbit.readLedScrollingDelay(callback(error, delay)); 259 | 260 | microbit.writeLedScrollingDelay(delar, callback(error)); 261 | ``` 262 | 263 | ## [Magnetometer](https://lancaster-university.github.io/microbit-docs/ble/magnetometer-service/) 264 | 265 | ### Data period 266 | 267 | Read or write the `period`. Support values are: 1, 2, 5, 10, 20, 80, 160, or 640 ms. 268 | 269 | ```javascript 270 | microbit.readMagnetometerPeriod(callback(error, period)); 271 | 272 | microbit.writeMagnetometerPeriod(period, callback(error)); 273 | ``` 274 | 275 | ### Read 276 | 277 | ```javascript 278 | microbit.readMagnetometer(callback(error, x, y, z)); 279 | 280 | microbit.readMagnetometerBearing(callback(error, bearing)); 281 | ``` 282 | 283 | ### Subscription 284 | 285 | ```javascript 286 | // x, y, and z values 287 | microbit.subscribeMagnetometer(callback(error)); 288 | 289 | microbit.unsubscribeMagnetometer(callback(error)); 290 | 291 | // bearing 292 | microbit.subscribeMagnetometerBearing(callback(error)); 293 | 294 | microbit.unsubscribeMagnetometerBearing(callback(error)); 295 | ``` 296 | 297 | #### Event 298 | 299 | ```javascript 300 | microbit.on('magnetometerChange', function(x, y, z) { 301 | // ... 302 | }); 303 | 304 | microbit.on('magnetometerBearingChange', function(bearing) { 305 | // ... 306 | }); 307 | ``` 308 | 309 | ## [Temperature](https://lancaster-university.github.io/microbit-docs/ble/temperature-service/) 310 | 311 | Units for `temperature` is °C. 312 | 313 | ### Data period 314 | 315 | `period` is in ms. 316 | 317 | ```javascript 318 | microbit.readTemperaturePeriod(callback(error, period)); 319 | 320 | microbit.writeTemperaturePeriod(period, callback(error)); 321 | ``` 322 | 323 | ### Read 324 | 325 | ```javascript 326 | microbit.readTemperature(callback(error, temperature)); 327 | ``` 328 | 329 | ### Subscription 330 | 331 | ```javascript 332 | microbit.subscribeTemperature(callback(error)); 333 | 334 | microbit.unsubscribeTemperature(callback(error)); 335 | ``` 336 | 337 | #### Event 338 | 339 | ```javascript 340 | microbit.on('temperatureChange', function(temperature) { 341 | // ... 342 | }); 343 | ``` 344 | 345 | ## [UART](https://lancaster-university.github.io/microbit-docs/ble/uart-service/) 346 | 347 | __NOTE:__ UART service does nothing currently. It does __not__ bridge the hardware serial pins to BLE! 348 | 349 | `data` is a buffer. 350 | 351 | ### Subscription 352 | 353 | ```javascript 354 | microbit.subscribeUart(callback(error)); 355 | 356 | microbit.unsubscribeUart(callback(error)); 357 | ``` 358 | 359 | #### Event 360 | 361 | ```javascript 362 | microbit.on('uartData', function(data) { 363 | // ... 364 | }); 365 | ``` 366 | 367 | ### Write 368 | 369 | ```javascript 370 | microbit.writeUart(data, callback(error)); 371 | ``` 372 | 373 | ## [Event](https://lancaster-university.github.io/microbit-docs/ble/event-service/) 374 | 375 | ### Micro:bit Events 376 | 377 | Events come in two varieties, reflected by the two corresponding characteristics: 378 | 379 | Micro:bit Events emanate from the micro:bit and may be notified to the connected client. 380 | 381 | Client Events emanate from the connected client and may be written to the connected micro:bit 382 | 383 | 384 | ### Write event 385 | 386 | ```javascript 387 | microbit.writeEvent(id, value, callback); 388 | ``` 389 | 390 | ### Subscription 391 | 392 | ```javascript 393 | microbit.subscribeEvents(id, value, callback(error)); 394 | 395 | microbit.unsubscribeEvent(callback(error)); 396 | ``` 397 | 398 | #### Event 399 | 400 | ```javascript 401 | microbit.on('event', function(id, value) { 402 | // ... 403 | }); 404 | ``` 405 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sandeep Mistry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-bbc-microbit 2 | 3 | Control a [BBC micro:bit](https://www.microbit.co.uk/) from Node.js using BLE. 4 | 5 | ## Prerequisites 6 | 7 | * See [noble prerequisites](https://github.com/sandeepmistry/noble). 8 | * Requires a custom firmware build on the micro:bit. This build removes pairing security and enables all BLE services. The source code of the custom firmware can be found [here](https://github.com/sandeepmistry/node-bbc-microbit-firmware). 9 | 10 | ### Flashing micro:bit firmware 11 | 12 | 1. Save hex file from [firmware folder](firmware/) to computer. 13 | 1. Connect micro:bit to computer using USB cable. 14 | 1. Copy hex file to micro:bit disk drive. 15 | 1. Calibrate magnetometer, by rotating micro:bit around in a circle. 16 | 17 | ## Install 18 | 19 | ``` 20 | npm install bbc-microbit 21 | ``` 22 | 23 | ## Examples 24 | 25 | See [examples](examples/) folder. 26 | 27 | ## Usage 28 | 29 | See [API documentation](API.md). 30 | -------------------------------------------------------------------------------- /examples/accelerometer-listener.js: -------------------------------------------------------------------------------- 1 | // subscribes to the accelerometer service and prints out values 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var period = 160; // ms 6 | 7 | console.log('Scanning for microbit'); 8 | BBCMicrobit.discover(function(microbit) { 9 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 10 | 11 | microbit.on('disconnect', function() { 12 | console.log('\tmicrobit disconnected!'); 13 | process.exit(0); 14 | }); 15 | 16 | microbit.on('accelerometerChange', function(x, y, z) { 17 | console.log('\ton -> accelerometer change: accelerometer = %d %d %d G', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 18 | }); 19 | 20 | console.log('connecting to microbit'); 21 | microbit.connectAndSetUp(function() { 22 | console.log('\tconnected to microbit'); 23 | 24 | console.log('setting accelerometer period to %d ms', period); 25 | microbit.writeAccelerometerPeriod(period, function() { 26 | console.log('\taccelerometer period set'); 27 | 28 | console.log('subscribing to accelerometer'); 29 | microbit.subscribeAccelerometer(function() { 30 | console.log('\tsubscribed to accelerometer'); 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/button-listener.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Listen to buttons being pressed on the BBC micro:bit 3 | * 4 | * Author: Martin Woolley, @bluetooth_mdw 5 | * 6 | * Example: 7 | * 8 | * sudo node button-listener.js 9 | * 10 | * micro:bit hex file must include the Bluetooth Button Service 11 | * 12 | * http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html for hex files and micro:bit info 13 | * 14 | */ 15 | 16 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 17 | 18 | var BUTTON_VALUE_MAPPER = ['Not Pressed', 'Pressed', 'Long Press']; 19 | 20 | // search for a micro:bit, to discover a particular micro:bit use: 21 | // BBCMicrobit.discoverById(id, callback); or BBCMicrobit.discoverByAddress(id, callback); 22 | 23 | console.log('Scanning for microbit'); 24 | BBCMicrobit.discover(function(microbit) { 25 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 26 | 27 | microbit.on('disconnect', function() { 28 | console.log('\tmicrobit disconnected!'); 29 | process.exit(0); 30 | }); 31 | 32 | microbit.on('buttonAChange', function(value) { 33 | console.log('\ton -> button A change: ', BUTTON_VALUE_MAPPER[value]); 34 | }); 35 | 36 | microbit.on('buttonBChange', function(value) { 37 | console.log('\ton -> button B change: ', BUTTON_VALUE_MAPPER[value]); 38 | }); 39 | 40 | console.log('connecting to microbit'); 41 | microbit.connectAndSetUp(function() { 42 | console.log('\tconnected to microbit'); 43 | 44 | console.log('subscribing to buttons'); 45 | // to only subscribe to one button use: 46 | // microbit.subscribeButtonA(); 47 | // or 48 | // microbit.subscribeButtonB(); 49 | microbit.subscribeButtons(function() { 50 | console.log('\tsubscribed to buttons'); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /examples/compass.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Uses data from the micro:bit magnetormeter to display compass directions 3 | * 4 | * Author: Martin Woolley, @bluetooth_mdw 5 | * 6 | * Example: 7 | * 8 | * sudo node compass.js 9 | * 10 | * micro:bit hex file must include the Bluetooth Magnetometer Service 11 | * 12 | * http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html for hex files and micro:bit information 13 | * 14 | */ 15 | 16 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 17 | 18 | var period = 160; // ms 19 | var last_compass_point_name = ""; 20 | 21 | var COMPASS_POINT_DELTA = 22.5; 22 | 23 | var COMPASS_POINTS = [ 24 | "N", 25 | "NNE", 26 | "NE", 27 | "ENE", 28 | "E", 29 | "ESE", 30 | "SE", 31 | "SSE", 32 | "S", 33 | "SSW", 34 | "SW", 35 | "WSW", 36 | "W", 37 | "WNW", 38 | "NW", 39 | "NNW" 40 | ]; 41 | 42 | 43 | console.log('Scanning for microbit'); 44 | BBCMicrobit.discover(function(microbit) { 45 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 46 | 47 | microbit.on('disconnect', function() { 48 | console.log('\tmicrobit disconnected!'); 49 | process.exit(0); 50 | }); 51 | 52 | microbit.on('magnetometerBearingChange', function(bearing) { 53 | var point_name = compassPoint(bearing); 54 | if (point_name !== last_compass_point_name) { 55 | console.log('\t Compass Direction: %s', point_name); 56 | last_compass_point_name = point_name; 57 | } 58 | }); 59 | 60 | console.log('connecting to microbit'); 61 | microbit.connectAndSetUp(function() { 62 | console.log('\tconnected to microbit'); 63 | 64 | console.log('setting magnetometer period to %d ms', period); 65 | microbit.writeMagnetometerPeriod(period, function() { 66 | console.log('\tmagnetometer period set'); 67 | 68 | console.log('subscribing to magnetometer bearing'); 69 | microbit.subscribeMagnetometerBearing(function() { 70 | console.log('\tsubscribed to magnetometer bearing'); 71 | }); 72 | }); 73 | }); 74 | }); 75 | 76 | function compassPoint(bearing) { 77 | var d = bearing / COMPASS_POINT_DELTA; 78 | var name_inx = Math.floor(d); 79 | if (d - name_inx > 0.5) { 80 | name_inx++; 81 | } 82 | if (name_inx > 15) { 83 | name_inx = 0; 84 | } 85 | return COMPASS_POINTS[name_inx]; 86 | } 87 | -------------------------------------------------------------------------------- /examples/discoverer.js: -------------------------------------------------------------------------------- 1 | // discovers all micro:bit's in range 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | // scan for all microbits 6 | console.log('Scanning for microbits'); 7 | BBCMicrobit.discoverAll(function(microbit) { 8 | console.log('\tFound a microbit: id = %s, address = %s', microbit.id, microbit.address); 9 | }); 10 | 11 | 12 | // to scan for a particular id use: 13 | // 14 | // BBCMicrobit.discoverById(id, function(microbit) { 15 | // // ... 16 | // }); 17 | 18 | 19 | // to scan for a particular address use: 20 | // 21 | // BBCMicrobit.discoverByAddress(address, function(microbit) { 22 | // // ... 23 | // }); 24 | -------------------------------------------------------------------------------- /examples/event-listener.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Informs micro:bit of interest in events with event ID 9999 and any event value. Logs events as they are received. 3 | * 4 | * Author: Martin Woolley, @bluetooth_mdw 5 | * 6 | * Example: 7 | * 8 | * sudo node event-listener.js 9 | * 10 | * micro:bit hex file must include the Bluetooth Event Service 11 | * 12 | * http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html for hex files and micro:bit info 13 | */ 14 | 15 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 16 | 17 | var EVENT_FAMILY = 9999; 18 | var EVENT_VALUE_ANY = 0; 19 | var EVENT_VALUE_1 = 1; 20 | 21 | // search for a micro:bit, to discover a particular micro:bit use: 22 | // BBCMicrobit.discoverById(id, callback); or BBCMicrobit.discoverByAddress(id, callback); 23 | // 24 | // C/C++ code containing the following fragments can be used for testing. 25 | // Pressing button A generates event ID 9999, value 1 26 | // Pressing button B generates event ID 9999, value 2 27 | // 28 | 29 | /* 30 | #include "MicroBit.h" 31 | MicroBit uBit; 32 | int EVENT_ID = 9999; 33 | 34 | void onButton(MicroBitEvent e) 35 | { 36 | if (e.source == MICROBIT_ID_BUTTON_A) { 37 | MicroBitEvent evt(EVENT_ID, 1); 38 | } 39 | if (e.source == MICROBIT_ID_BUTTON_B) { 40 | MicroBitEvent evt(EVENT_ID, 2); 41 | } 42 | } 43 | int main() 44 | { 45 | // Initialise the micro:bit runtime. 46 | uBit.init(); 47 | uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButton); 48 | uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_BUTTON_EVT_CLICK, onButton); 49 | release_fiber(); 50 | } 51 | */ 52 | 53 | console.log('Scanning for microbit'); 54 | BBCMicrobit.discover(function(microbit) { 55 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 56 | 57 | 58 | microbit.on('event', function(id, value) { 59 | console.log('\ton -> micro:bit event received event: %d value: %d', id, value); 60 | }); 61 | 62 | microbit.on('disconnect', function() { 63 | console.log('\tmicrobit disconnected!'); 64 | process.exit(0); 65 | }); 66 | 67 | console.log('connecting to microbit'); 68 | microbit.connectAndSetUp(function() { 69 | console.log('\tconnected to microbit'); 70 | 71 | // Example 1: subscribe to all micro:bit events with ID 9999 and any event value 72 | console.log('subscribing to event family 9999, any event value'); 73 | microbit.subscribeEvents(EVENT_FAMILY, EVENT_VALUE_ANY, function() { 74 | console.log('\tsubscribed to micro:bit events of required type'); 75 | }); 76 | 77 | // Example 2: subscribe to the specific event with ID=9999 and value=0001 only 78 | // console.log('subscribing to event family 9999, event value 0001'); 79 | // microbit.subscribeEvents(EVENT_FAMILY, EVENT_VALUE_1, function() { 80 | // console.log('\tsubscribed to micro:bit events of required type'); 81 | // }); 82 | }); 83 | }); 84 | -------------------------------------------------------------------------------- /examples/led-pattern.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Sends a random pattern to a micro:bit for display on the LED matrix 3 | * 4 | * Author: Martin Woolley, @bluetooth_mdw 5 | * 6 | * Example: 7 | * 8 | * sudo node led-pattern.js 9 | * 10 | * micro:bit hex file must include the Bluetooth LED Service 11 | * 12 | * http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html for hex files and micro:bit info 13 | * 14 | */ 15 | 16 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 17 | 18 | // the micro:bit 5x5 LED display can be set to any pattern by sending a 5 byte array to it. Each byte contains a value which sets the LEDs 19 | // in a particular row to either on or off. The 5 least significant bits in each byte correspond to each of the 5 LEDs in that row: 20 | // 21 | // Octet 0, LED Row 1: bit4 bit3 bit2 bit1 bit0 22 | // Octet 1, LED Row 2: bit4 bit3 bit2 bit1 bit0 23 | // Octet 2, LED Row 3: bit4 bit3 bit2 bit1 bit0 24 | // Octet 3, LED Row 4: bit4 bit3 bit2 bit1 bit0 25 | // Octet 4, LED Row 5: bit4 bit3 bit2 bit1 bit0 26 | 27 | var PATTERNS = [ 28 | { 29 | name: 'Arrow up right', 30 | value: new Buffer('0F03050910', 'hex') 31 | }, 32 | { 33 | name: 'Arrow down left', 34 | value: new Buffer('011214181E', 'hex') 35 | }, 36 | { 37 | name: 'Arrow down right', 38 | value: new Buffer('100905030F', 'hex') 39 | }, 40 | { 41 | name: 'Arrow down left', 42 | value: new Buffer('011214181E', 'hex') 43 | }, 44 | { 45 | name: 'Arrow up left', 46 | value: new Buffer('1E18141201', 'hex') 47 | }, 48 | { 49 | name: 'Diamond', 50 | value: new Buffer('040A110A04', 'hex') 51 | }, 52 | { 53 | name: 'Smile', 54 | value: new Buffer('0A0A00110E', 'hex') 55 | }, 56 | { 57 | name: 'Wink', 58 | value: new Buffer('080B00110E', 'hex') 59 | }, 60 | { 61 | name: 'Solid', 62 | value: new Buffer('1F1F1F1F1F', 'hex') 63 | }, 64 | { 65 | name: 'Blank', 66 | value: new Buffer('0000000000', 'hex') 67 | } 68 | ]; 69 | 70 | var patternIndex = Math.floor((Math.random() * PATTERNS.length)); // choose a random pattern 71 | var pattern = PATTERNS[patternIndex]; 72 | 73 | // search for a micro:bit, to discover a particular micro:bit use: 74 | // BBCMicrobit.discoverById(id, callback); or BBCMicrobit.discoverByAddress(id, callback); 75 | 76 | console.log('Scanning for microbit'); 77 | BBCMicrobit.discover(function(microbit) { 78 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 79 | 80 | microbit.on('disconnect', function() { 81 | console.log('\tmicrobit disconnected!'); 82 | process.exit(0); 83 | }); 84 | 85 | console.log('connecting to microbit'); 86 | microbit.connectAndSetUp(function() { 87 | console.log('\tconnected to microbit'); 88 | 89 | console.log('sending pattern: "%s"', pattern.name); 90 | microbit.writeLedMatrixState(pattern.value, function() { 91 | console.log('\tpattern sent'); 92 | 93 | console.log('disconnecting'); 94 | microbit.disconnect(); 95 | }); 96 | }); 97 | }); 98 | -------------------------------------------------------------------------------- /examples/led-text.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Send text to a micro:bit to display on the LED matrix 3 | * 4 | * Author: Martin Woolley, @bluetooth_mdw 5 | * 6 | * Example: 7 | * 8 | * sudo node led-text.js 9 | * 10 | * micro:bit hex file must include the Bluetooth LED Service 11 | * 12 | * http://bluetooth-mdw.blogspot.co.uk/p/bbc-microbit.html for hex files and micro:bit info 13 | */ 14 | 15 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 16 | 17 | var text = 'Hello there'; 18 | 19 | // search for a micro:bit, to discover a particular micro:bit use: 20 | // BBCMicrobit.discoverById(id, callback); or BBCMicrobit.discoverByAddress(id, callback); 21 | 22 | console.log('Scanning for microbit'); 23 | BBCMicrobit.discover(function(microbit) { 24 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 25 | 26 | microbit.on('disconnect', function() { 27 | console.log('\tmicrobit disconnected!'); 28 | process.exit(0); 29 | }); 30 | 31 | console.log('connecting to microbit'); 32 | microbit.connectAndSetUp(function() { 33 | console.log('\tconnected to microbit'); 34 | 35 | console.log('sending text: "%s"', text); 36 | microbit.writeLedText(text, function() { 37 | console.log('\ttext sent'); 38 | 39 | console.log('disconnecting'); 40 | microbit.disconnect(); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /examples/magnetometer-bearing-listener.js: -------------------------------------------------------------------------------- 1 | // subscribes to the magnetometer service and prints out bearing value 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var period = 160; // ms 6 | 7 | console.log('Scanning for microbit'); 8 | BBCMicrobit.discover(function(microbit) { 9 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 10 | 11 | microbit.on('disconnect', function() { 12 | console.log('\tmicrobit disconnected!'); 13 | process.exit(0); 14 | }); 15 | 16 | microbit.on('magnetometerBearingChange', function(bearing) { 17 | console.log('\ton -> magnetometer bearing change: magnetometer bearing = %d', bearing); 18 | }); 19 | 20 | console.log('connecting to microbit'); 21 | microbit.connectAndSetUp(function() { 22 | console.log('\tconnected to microbit'); 23 | 24 | console.log('setting magnetometer period to %d ms', period); 25 | microbit.writeMagnetometerPeriod(period, function() { 26 | console.log('\tmagnetometer period set'); 27 | 28 | console.log('subscribing to magnetometer bearing'); 29 | microbit.subscribeMagnetometerBearing(function() { 30 | console.log('\tsubscribed to magnetometer bearing'); 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/magnetometer-listener.js: -------------------------------------------------------------------------------- 1 | // subscribes to the magnetometer service and prints out values 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var period = 160; // ms 6 | 7 | console.log('Scanning for microbit'); 8 | BBCMicrobit.discover(function(microbit) { 9 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 10 | 11 | microbit.on('disconnect', function() { 12 | console.log('\tmicrobit disconnected!'); 13 | process.exit(0); 14 | }); 15 | 16 | microbit.on('magnetometerChange', function(x, y, z) { 17 | console.log('\ton -> magnetometer change: magnetometer = %d %d %d', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 18 | }); 19 | 20 | console.log('connecting to microbit'); 21 | microbit.connectAndSetUp(function() { 22 | console.log('\tconnected to microbit'); 23 | 24 | console.log('setting magnetometer period to %d ms', period); 25 | microbit.writeMagnetometerPeriod(period, function() { 26 | console.log('\tmagnetometer period set'); 27 | 28 | console.log('subscribing to magnetometer'); 29 | microbit.subscribeMagnetometer(function() { 30 | console.log('\tsubscribed to magnetometer'); 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /examples/pin-blink.js: -------------------------------------------------------------------------------- 1 | // make a pin blink at a interval 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var pin = 0; 6 | var interval = 1000; // ms 7 | var pinValue = 0; 8 | 9 | console.log('Scanning for microbit'); 10 | BBCMicrobit.discover(function(microbit) { 11 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 12 | 13 | microbit.on('disconnect', function() { 14 | console.log('\tmicrobit disconnected!'); 15 | process.exit(0); 16 | }); 17 | 18 | console.log('connecting to microbit'); 19 | microbit.connectAndSetUp(function() { 20 | console.log('\tconnected to microbit'); 21 | 22 | console.log('setting pin %d as output', pin); 23 | microbit.pinOutput(pin, function() { 24 | console.log('\tpin set as output'); 25 | 26 | console.log('setting pin %d as digital', pin); 27 | microbit.pinDigital(pin, function() { 28 | console.log('\tpin set as digital'); 29 | 30 | togglePin(); 31 | }); 32 | }); 33 | }); 34 | 35 | function togglePin() { 36 | pinValue = (pinValue === 0) ? 1 : 0; 37 | 38 | console.log('writing %d to pin %d', pinValue, pin); 39 | microbit.writePin(pin, pinValue, function() { 40 | console.log('\tdone'); 41 | 42 | setTimeout(togglePin, interval); 43 | }); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /examples/pin-listener.js: -------------------------------------------------------------------------------- 1 | // make listen to a pin value 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var pin = 0; 6 | 7 | console.log('Scanning for microbit'); 8 | BBCMicrobit.discover(function(microbit) { 9 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 10 | 11 | microbit.on('disconnect', function() { 12 | console.log('\tmicrobit disconnected!'); 13 | process.exit(0); 14 | }); 15 | 16 | microbit.on('pinDataChange', function(pin, value) { 17 | console.log('\ton -> pin data change: pin = %d, value = %d', pin, value); 18 | }); 19 | 20 | console.log('connecting to microbit'); 21 | microbit.connectAndSetUp(function() { 22 | console.log('\tconnected to microbit'); 23 | 24 | console.log('setting pin %d as input', pin); 25 | microbit.pinInput(pin, function() { 26 | console.log('\tpin set as input'); 27 | 28 | console.log('setting pin %d as analog', pin); 29 | microbit.pinAnalog(pin, function() { 30 | console.log('\tpin set as analog'); 31 | 32 | console.log('subscribing to pin data'); 33 | microbit.subscribePinData(function() { 34 | console.log('\tsubscribed to pin data'); 35 | }); 36 | }); 37 | }); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /examples/temperature-listener.js: -------------------------------------------------------------------------------- 1 | // subscribes to the temperature service and prints out value 2 | 3 | var BBCMicrobit = require('../index'); // or require('bbc-microbit') 4 | 5 | var period = 160; // ms 6 | 7 | console.log('Scanning for microbit'); 8 | BBCMicrobit.discover(function(microbit) { 9 | console.log('\tdiscovered microbit: id = %s, address = %s', microbit.id, microbit.address); 10 | 11 | microbit.on('disconnect', function() { 12 | console.log('\tmicrobit disconnected!'); 13 | process.exit(0); 14 | }); 15 | 16 | microbit.on('temperatureChange', function(temperature) { 17 | console.log('\ton -> temperature change: temperature = %d °C', temperature); 18 | }); 19 | 20 | console.log('connecting to microbit'); 21 | microbit.connectAndSetUp(function() { 22 | console.log('\tconnected to microbit'); 23 | 24 | console.log('setting temperature period to %d ms', period); 25 | microbit.writeTemperaturePeriod(period, function() { 26 | console.log('\ttemperature period set'); 27 | 28 | console.log('subscribing to temperature'); 29 | microbit.subscribeTemperature(function() { 30 | console.log('\tsubscribed to temperature'); 31 | }); 32 | }); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/bbc-microbit'); 2 | -------------------------------------------------------------------------------- /lib/accelerometer-service.js: -------------------------------------------------------------------------------- 1 | var ACCELEROMETER_SERVICE_UUID = 'e95d0753251d470aa062fa1922dfa9a8'; 2 | var ACCELEROMETER_CHARACTERISTIC_UUID = 'e95dca4b251d470aa062fa1922dfa9a8'; 3 | var ACCELEROMETER_PERIOD_CHARACTERISTIC_UUID = 'e95dfb24251d470aa062fa1922dfa9a8'; 4 | 5 | var AccelerometerService = function() { 6 | }; 7 | 8 | AccelerometerService.prototype.hasAccelerometerService = function() { 9 | return this.hasService(ACCELEROMETER_SERVICE_UUID); 10 | }; 11 | 12 | AccelerometerService.prototype.readAccelerometer = function(callback) { 13 | this.readDataCharacteristic(ACCELEROMETER_SERVICE_UUID, ACCELEROMETER_CHARACTERISTIC_UUID, function(error, data) { 14 | if (error) { 15 | return callback(error); 16 | } 17 | 18 | this.convertAccelerometerData(data, function(x, y, z) { 19 | callback(null, x, y, z); 20 | }.bind(this)); 21 | }.bind(this)); 22 | }; 23 | 24 | AccelerometerService.prototype.convertAccelerometerData = function(data, callback) { 25 | var x = data.readInt16LE(0) / 1000.0; 26 | var y = data.readInt16LE(2) / 1000.0; 27 | var z = data.readInt16LE(4) / 1000.0; 28 | 29 | callback(x, y, z); 30 | }; 31 | 32 | AccelerometerService.prototype.subscribeAccelerometer = function(callback) { 33 | this.onAccelerometerChangeBinded = this.onAccelerometerChange.bind(this); 34 | 35 | this.subscribeCharacteristic(ACCELEROMETER_SERVICE_UUID, ACCELEROMETER_CHARACTERISTIC_UUID, this.onAccelerometerChangeBinded, callback); 36 | }; 37 | 38 | AccelerometerService.prototype.unsubscribeAccelerometer = function(callback) { 39 | this.unsubscribeCharacteristic(ACCELEROMETER_SERVICE_UUID, ACCELEROMETER_CHARACTERISTIC_UUID, this.onAccelerometerChangeBinded, callback); 40 | }; 41 | 42 | AccelerometerService.prototype.onAccelerometerChange = function(data) { 43 | this.convertAccelerometerData(data, function(x, y, z) { 44 | this.emit('accelerometerChange', x, y, z); 45 | }.bind(this)); 46 | }; 47 | 48 | AccelerometerService.prototype.readAccelerometerPeriod = function(callback) { 49 | this.readUInt16LECharacteristic(ACCELEROMETER_SERVICE_UUID, ACCELEROMETER_PERIOD_CHARACTERISTIC_UUID, callback); 50 | }; 51 | 52 | AccelerometerService.prototype.writeAccelerometerPeriod = function(period, callback) { 53 | if (period >= 640) { 54 | period = 640; 55 | } else if (period >= 160) { 56 | period = 160; 57 | } else if (period >= 80) { 58 | period = 80; 59 | } else if (period >= 20) { 60 | period = 20; 61 | } else if (period >= 10) { 62 | period = 10; 63 | } else if (period >= 5) { 64 | period = 5; 65 | } else if (period >= 2) { 66 | period = 2; 67 | } else { 68 | period = 1; 69 | } 70 | 71 | this.writeUInt16LECharacteristic(ACCELEROMETER_SERVICE_UUID, ACCELEROMETER_PERIOD_CHARACTERISTIC_UUID, period, callback); 72 | }; 73 | 74 | module.exports = AccelerometerService; 75 | -------------------------------------------------------------------------------- /lib/bbc-microbit.js: -------------------------------------------------------------------------------- 1 | var NobleDevice = require('noble-device'); 2 | 3 | var AccelerometerService = require('./accelerometer-service'); 4 | var ButtonService = require('./button-service'); 5 | var IoPinService = require('./io-pin-service'); 6 | var LedService = require('./led-service'); 7 | var MagnetometerService = require('./magnetometer-service'); 8 | var TemperatureService = require('./temperature-service'); 9 | var UartService = require('./uart-service'); 10 | var EventService = require('./event-service'); 11 | 12 | function BBCMicrobit() { 13 | } 14 | 15 | var BBCMicrobit = function(peripheral) { 16 | NobleDevice.call(this, peripheral); 17 | }; 18 | 19 | BBCMicrobit.is = function(peripheral) { 20 | var localName = peripheral.advertisement.localName; 21 | 22 | return (localName !== undefined) && (localName.indexOf('BBC micro:bit') !== -1); 23 | }; 24 | 25 | NobleDevice.Util.inherits(BBCMicrobit, NobleDevice); 26 | NobleDevice.Util.mixin(BBCMicrobit, NobleDevice.DeviceInformationService); 27 | NobleDevice.Util.mixin(BBCMicrobit, AccelerometerService); 28 | NobleDevice.Util.mixin(BBCMicrobit, ButtonService); 29 | NobleDevice.Util.mixin(BBCMicrobit, IoPinService); 30 | NobleDevice.Util.mixin(BBCMicrobit, LedService); 31 | NobleDevice.Util.mixin(BBCMicrobit, MagnetometerService); 32 | NobleDevice.Util.mixin(BBCMicrobit, TemperatureService); 33 | NobleDevice.Util.mixin(BBCMicrobit, UartService); 34 | NobleDevice.Util.mixin(BBCMicrobit, EventService); 35 | 36 | BBCMicrobit.prototype.toString = function() { 37 | return JSON.stringify({ 38 | id: this.id, 39 | address: this.address 40 | }); 41 | }; 42 | 43 | BBCMicrobit.prototype.connectAndSetUp = function(callback) { 44 | BBCMicrobit.super_.prototype.connectAndSetUp.call(this, function(error) { 45 | if (error) { 46 | return callback(error); 47 | } 48 | 49 | if (this.hasIoPinService()) { 50 | this.readPinAdConfiguration(function(error) { 51 | if (error) { 52 | return callback(error); 53 | } 54 | 55 | this.readPinIoConfiguration(function(error) { 56 | if (error) { 57 | return callback(error); 58 | } 59 | 60 | callback(); 61 | }.bind(this)); 62 | }.bind(this)); 63 | } else { 64 | callback(); 65 | } 66 | }.bind(this)); 67 | }; 68 | 69 | module.exports = BBCMicrobit; 70 | -------------------------------------------------------------------------------- /lib/button-service.js: -------------------------------------------------------------------------------- 1 | var BUTTON_SERVICE_UUID = 'e95d9882251d470aa062fa1922dfa9a8'; 2 | var BUTTON_A_CHARACTERISTIC_UUID = 'e95dda90251d470aa062fa1922dfa9a8'; 3 | var BUTTON_B_CHARACTERISTIC_UUID = 'e95dda91251d470aa062fa1922dfa9a8'; 4 | 5 | var ButtonService = function() { 6 | }; 7 | 8 | ButtonService.prototype.hasButtonService = function() { 9 | return this.hasService(BUTTON_SERVICE_UUID); 10 | }; 11 | 12 | ButtonService.prototype.subscribeButtonA = function(callback) { 13 | this.onButtonAChangeBinded = this.onButtonAChange.bind(this); 14 | 15 | this.subscribeCharacteristic(BUTTON_SERVICE_UUID, BUTTON_A_CHARACTERISTIC_UUID, this.onButtonAChangeBinded, callback); 16 | }; 17 | 18 | ButtonService.prototype.unsubscribeButtonA = function(callback) { 19 | this.unsubscribeCharacteristic(BUTTON_SERVICE_UUID, BUTTON_A_CHARACTERISTIC_UUID, this.onButtonAChangeBinded, callback); 20 | }; 21 | 22 | ButtonService.prototype.onButtonAChange = function(data) { 23 | this.emit('buttonAChange', data.readUInt8(0)); 24 | }; 25 | 26 | ButtonService.prototype.subscribeButtonB = function(callback) { 27 | this.onButtonBChangeBinded = this.onButtonBChange.bind(this); 28 | 29 | this.subscribeCharacteristic(BUTTON_SERVICE_UUID, BUTTON_B_CHARACTERISTIC_UUID, this.onButtonBChangeBinded, callback); 30 | }; 31 | 32 | ButtonService.prototype.unsubscribeButtonB = function(callback) { 33 | this.unsubscribeCharacteristic(BUTTON_SERVICE_UUID, BUTTON_B_CHARACTERISTIC_UUID, this.onButtonBChangeBinded, callback); 34 | }; 35 | 36 | ButtonService.prototype.onButtonBChange = function(data) { 37 | this.emit('buttonBChange', data.readUInt8(0)); 38 | }; 39 | 40 | ButtonService.prototype.subscribeButtons = function(callback) { 41 | this.subscribeButtonA(function(error) { 42 | if (error) { 43 | return callback(error); 44 | } 45 | 46 | this.subscribeButtonB(callback); 47 | }.bind(this)); 48 | }; 49 | 50 | ButtonService.prototype.unsubscribeButtons = function(callback) { 51 | this.unsubscribeButtonB(function(error) { 52 | if (error) { 53 | return callback(error); 54 | } 55 | 56 | this.unsubscribeButtonA(callback); 57 | }.bind(this)); 58 | }; 59 | 60 | module.exports = ButtonService; 61 | -------------------------------------------------------------------------------- /lib/event-service.js: -------------------------------------------------------------------------------- 1 | var EVENT_SERVICE_SERVICE_UUID = 'e95d93af251d470aa062fa1922dfa9a8'; 2 | var MICROBIT_EVENT_CHARACTERISTIC_UUID = 'e95d9775251d470aa062fa1922dfa9a8'; 3 | var CLIENT_REQUIREMENTS_CHARACTERISTIC_UUID = 'e95d23c4251d470aa062fa1922dfa9a8'; 4 | var CLIENT_EVENT_CHARACTERISTIC_UUID = 'e95d5404251d470aa062fa1922dfa9a8'; 5 | 6 | var EventService = function() { 7 | }; 8 | 9 | EventService.prototype.hasEventService = function() { 10 | return this.hasService(EVENTSERVICE_SERVICE_UUID); 11 | }; 12 | 13 | EventService.prototype.onEvent = function(data) { 14 | if (data.length !== 4) { 15 | return; 16 | } 17 | 18 | var id = data.readInt16LE(0); 19 | var value = data.readInt16LE(2); 20 | 21 | this.emit('event', id, value); 22 | }; 23 | 24 | EventService.prototype.subscribeEvents = function(id, value, callback) { 25 | // specifying which events we want to be notified about 26 | this._writeClientEventRequirements(id, value, callback); 27 | 28 | if (!this._eventSubscribed) { 29 | this.onEventBinded = this.onEvent.bind(this); 30 | 31 | this.subscribeCharacteristic(EVENT_SERVICE_SERVICE_UUID, MICROBIT_EVENT_CHARACTERISTIC_UUID, this.onEventBinded); 32 | 33 | this._eventSubscribed = true; 34 | } 35 | }; 36 | 37 | EventService.prototype.unsubscribeEvent = function(callback) { 38 | // allow this event if not previously explicitly subscribed through a call to subscribeEvents because the micro:bit may have persisted the 39 | // client characteristic configuration descriptor state from a previous "session" 40 | this.unsubscribeCharacteristic(EVENT_SERVICE_SERVICE_UUID, MICROBIT_EVENT_CHARACTERISTIC_UUID, this.onEventBinded, callback); 41 | 42 | this._eventSubscribed = false; 43 | }; 44 | 45 | EventService.prototype._writeClientEventRequirements = function(id, value, callback) { 46 | var data = new Buffer(4); 47 | 48 | data.writeUInt16LE(id, 0); 49 | data.writeUInt16LE(value, 2); 50 | 51 | this.writeDataCharacteristic(EVENT_SERVICE_SERVICE_UUID, CLIENT_REQUIREMENTS_CHARACTERISTIC_UUID, data, callback); 52 | }; 53 | 54 | EventService.prototype.writeEvent = function(id, value, callback) { 55 | var data = id << 16 | value; 56 | 57 | this.writeUInt32LECharacteristic(EVENT_SERVICE_SERVICE_UUID, CLIENT_EVENT_CHARACTERISTIC_UUID, data, callback); 58 | }; 59 | 60 | module.exports = EventService; 61 | -------------------------------------------------------------------------------- /lib/io-pin-service.js: -------------------------------------------------------------------------------- 1 | var IO_PIN_SERVICE_UUID = 'e95d127b251d470aa062fa1922dfa9a8'; 2 | var PIN_DATA_CHARACTERISTIC_UUID = 'e95d8d00251d470aa062fa1922dfa9a8'; 3 | var PIN_AD_CONFIGURATION_CHARACTERISTIC_UUID = 'e95d5899251d470aa062fa1922dfa9a8'; 4 | var PIN_IO_CONFIGURATION_CHARACTERISTIC_UUID = 'e95db9fe251d470aa062fa1922dfa9a8'; 5 | 6 | var IoPinService = function() { 7 | this._adMask = 0; 8 | this._ioMask = 0; 9 | }; 10 | 11 | IoPinService.prototype.hasIoPinService = function() { 12 | return this.hasService(IO_PIN_SERVICE_UUID); 13 | }; 14 | 15 | IoPinService.prototype.readPinData = function(callback) { 16 | this.readDataCharacteristic(IO_PIN_SERVICE_UUID, PIN_DATA_CHARACTERISTIC_UUID, function(error, data) { 17 | if (error) { 18 | return callback(error); 19 | } 20 | 21 | var pinData = []; 22 | 23 | for (var i = 0; i < data.length; i += 2) { 24 | var pin = data.readUInt8(i); 25 | var value = data.readUInt8(i + 1); 26 | 27 | pinData.push({ 28 | pin: pin, 29 | value: value 30 | }); 31 | } 32 | 33 | callback(null, pinData); 34 | }.bind(this)); 35 | }; 36 | 37 | IoPinService.prototype.writePinData = function(data, callback) { 38 | this.writeDataCharacteristic(IO_PIN_SERVICE_UUID, PIN_DATA_CHARACTERISTIC_UUID, data, callback); 39 | }; 40 | 41 | IoPinService.prototype.subscribePinData = function(callback) { 42 | this.onPinDataChangeBinded = this.onPinDataChange.bind(this); 43 | 44 | this.subscribeCharacteristic(IO_PIN_SERVICE_UUID, PIN_DATA_CHARACTERISTIC_UUID, this.onPinDataChangeBinded, callback); 45 | }; 46 | 47 | IoPinService.prototype.unsubscribePinData = function(callback) { 48 | this.unsubscribeCharacteristic(IO_PIN_SERVICE_UUID, PIN_DATA_CHARACTERISTIC_UUID, this.onPinDataChangeBinded, callback); 49 | }; 50 | 51 | IoPinService.prototype.onPinDataChange = function(data) { 52 | for (var i = 0; i < data.length; i += 2) { 53 | var pin = data.readUInt8(i); 54 | var value = data.readUInt8(i + 1); 55 | 56 | this.emit('pinDataChange', pin, value); 57 | } 58 | }; 59 | 60 | IoPinService.prototype.readPinAdConfiguration = function(callback) { 61 | this.readUInt32LECharacteristic(IO_PIN_SERVICE_UUID, PIN_AD_CONFIGURATION_CHARACTERISTIC_UUID, function(error, value) { 62 | if (error) { 63 | return callback(error); 64 | } 65 | 66 | this._adMask = value; 67 | 68 | callback(error, value); 69 | }.bind(this)); 70 | }; 71 | 72 | IoPinService.prototype.writePinAdConfiguration = function(value, callback) { 73 | this._adMask = value; 74 | 75 | this.writeUInt32LECharacteristic(IO_PIN_SERVICE_UUID, PIN_AD_CONFIGURATION_CHARACTERISTIC_UUID, value, callback); 76 | }; 77 | 78 | IoPinService.prototype.readPinIoConfiguration = function(callback) { 79 | this.readUInt32LECharacteristic(IO_PIN_SERVICE_UUID, PIN_IO_CONFIGURATION_CHARACTERISTIC_UUID, function(error, value) { 80 | if (error) { 81 | return callback(error); 82 | } 83 | 84 | this._ioMask = value; 85 | 86 | callback(error, value); 87 | }.bind(this)); 88 | }; 89 | 90 | IoPinService.prototype.writePinIoConfiguration = function(value, callback) { 91 | this._ioMask = value; 92 | 93 | this.writeUInt32LECharacteristic(IO_PIN_SERVICE_UUID, PIN_IO_CONFIGURATION_CHARACTERISTIC_UUID, value, callback); 94 | }; 95 | 96 | IoPinService.prototype.pinAnalog = function(pin, callback) { 97 | this._adMask |= (1 << pin); 98 | 99 | this.writePinAdConfiguration(this._adMask, callback); 100 | }; 101 | 102 | IoPinService.prototype.pinDigital = function(pin, callback) { 103 | this._adMask &= ~(1 << pin); 104 | 105 | this.writePinAdConfiguration(this._adMask, callback); 106 | }; 107 | 108 | IoPinService.prototype.pinInput = function(pin, callback) { 109 | this._ioMask |= (1 << pin); 110 | 111 | this.writePinIoConfiguration(this._ioMask, callback); 112 | }; 113 | 114 | IoPinService.prototype.pinOutput = function(pin, callback) { 115 | this._ioMask &= ~(1 << pin); 116 | 117 | this.writePinIoConfiguration(this._ioMask, callback); 118 | }; 119 | 120 | IoPinService.prototype.writePin = function(pin, value, callback) { 121 | var data = new Buffer(2); 122 | 123 | data.writeUInt8(pin, 0); 124 | data.writeUInt8(value, 1); 125 | 126 | this.writePinData(data, callback); 127 | }; 128 | 129 | IoPinService.prototype.readPin = function(pin, callback) { 130 | this.readPinData(function(error, pinData) { 131 | if (error) { 132 | callback(error); 133 | } 134 | 135 | var value = 0; 136 | 137 | for (var i = 0; i < pinData.length; i++) { 138 | if (pinData[i].pin === pin) { 139 | value = pinData[i].value; 140 | break; 141 | } 142 | } 143 | 144 | callback(null, value); 145 | }.bind(this)); 146 | }; 147 | 148 | module.exports = IoPinService; 149 | -------------------------------------------------------------------------------- /lib/led-service.js: -------------------------------------------------------------------------------- 1 | var LED_SERVICE_UUID = 'e95dd91d251d470aa062fa1922dfa9a8'; 2 | var LED_MATRIX_STATE_CHARACTERISTIC_UUID = 'e95d7b77251d470aa062fa1922dfa9a8'; 3 | var LED_TEXT_CHARACTERISTIC_UUID = 'e95d93ee251d470aa062fa1922dfa9a8'; 4 | var LED_SCROLLING_DELAY_CHARACTERISTIC_UUID = 'e95d0d2d251d470aa062fa1922dfa9a8'; 5 | 6 | var LedService = function() { 7 | }; 8 | 9 | LedService.prototype.hasLedService = function() { 10 | return this.hasService(LED_SERVICE_UUID); 11 | }; 12 | 13 | LedService.prototype.readLedMatrixState = function(callback) { 14 | this.readDataCharacteristic(LED_SERVICE_UUID, LED_MATRIX_STATE_CHARACTERISTIC_UUID, callback); 15 | }; 16 | 17 | LedService.prototype.writeLedMatrixState = function(data, callback) { 18 | this.writeDataCharacteristic(LED_SERVICE_UUID, LED_MATRIX_STATE_CHARACTERISTIC_UUID, data, callback); 19 | }; 20 | 21 | LedService.prototype.writeLedText = function(text, callback) { 22 | this.writeStringCharacteristic(LED_SERVICE_UUID, LED_TEXT_CHARACTERISTIC_UUID, text, callback); 23 | }; 24 | 25 | LedService.prototype.readLedScrollingDelay = function(callback) { 26 | this.readUInt16LECharacteristic(LED_SERVICE_UUID, LED_SCROLLING_DELAY_CHARACTERISTIC_UUID, callback); 27 | }; 28 | 29 | LedService.prototype.writeLedScrollingDelay = function(delay, callback) { 30 | this.writeUInt16LECharacteristic(LED_SERVICE_UUID, LED_SCROLLING_DELAY_CHARACTERISTIC_UUID, delay, callback); 31 | }; 32 | 33 | module.exports = LedService; 34 | -------------------------------------------------------------------------------- /lib/magnetometer-service.js: -------------------------------------------------------------------------------- 1 | var MAGNETOMETER_SERVICE_UUID = 'e95df2d8251d470aa062fa1922dfa9a8'; 2 | var MAGNETOMETER_CHARACTERISTIC_UUID = 'e95dfb11251d470aa062fa1922dfa9a8'; 3 | var MAGNETOMETER_PERIOD_CHARACTERISTIC_UUID = 'e95d386c251d470aa062fa1922dfa9a8'; 4 | var MAGNETOMETER_BEARING_CHARACTERISTIC_UUID = 'e95d9715251d470aa062fa1922dfa9a8'; 5 | 6 | var MagnetometerService = function() { 7 | }; 8 | 9 | MagnetometerService.prototype.hasMagnetometerService = function() { 10 | return this.hasService(MAGNETOMETER_SERVICE_UUID); 11 | }; 12 | 13 | MagnetometerService.prototype.readMagnetometer = function(callback) { 14 | this.readDataCharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_CHARACTERISTIC_UUID, function(error, data) { 15 | if (error) { 16 | return callback(error); 17 | } 18 | 19 | this.convertMagnetometerData(data, function(x, y, z) { 20 | callback(null, x, y, z); 21 | }.bind(this)); 22 | }.bind(this)); 23 | }; 24 | 25 | MagnetometerService.prototype.convertMagnetometerData = function(data, callback) { 26 | var x = data.readInt16LE(0) / 1000.0; 27 | var y = data.readInt16LE(2) / 1000.0; 28 | var z = data.readInt16LE(4) / 1000.0; 29 | 30 | callback(x, y, z); 31 | }; 32 | 33 | MagnetometerService.prototype.subscribeMagnetometer = function(callback) { 34 | this.onMagnetometerChangeBinded = this.onMagnetometerChange.bind(this); 35 | 36 | this.subscribeCharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_CHARACTERISTIC_UUID, this.onMagnetometerChangeBinded, callback); 37 | }; 38 | 39 | MagnetometerService.prototype.unsubscribeMagnetometer = function(callback) { 40 | this.unsubscribeCharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_CHARACTERISTIC_UUID, this.onMagnetometerChangeBinded, callback); 41 | }; 42 | 43 | MagnetometerService.prototype.onMagnetometerChange = function(data) { 44 | if (data.length !== 6) { 45 | return; 46 | } 47 | 48 | this.convertMagnetometerData(data, function(x, y, z) { 49 | this.emit('magnetometerChange', x, y, z); 50 | }.bind(this)); 51 | }; 52 | 53 | MagnetometerService.prototype.readMagnetometerPeriod = function(callback) { 54 | this.readUInt16LECharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_PERIOD_CHARACTERISTIC_UUID, callback); 55 | }; 56 | 57 | MagnetometerService.prototype.writeMagnetometerPeriod = function(period, callback) { 58 | if (period >= 640) { 59 | period = 640; 60 | } else if (period >= 160) { 61 | period = 160; 62 | } else if (period >= 80) { 63 | period = 80; 64 | } else if (period >= 20) { 65 | period = 20; 66 | } else if (period >= 10) { 67 | period = 10; 68 | } else if (period >= 5) { 69 | period = 5; 70 | } else if (period >= 2) { 71 | period = 2; 72 | } else { 73 | period = 1; 74 | } 75 | 76 | this.writeUInt16LECharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_PERIOD_CHARACTERISTIC_UUID, period, callback); 77 | }; 78 | 79 | MagnetometerService.prototype.readMagnetometerBearing = function(callback) { 80 | this.readInt16LECharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_BEARING_CHARACTERISTIC_UUID, callback); 81 | }; 82 | 83 | MagnetometerService.prototype.subscribeMagnetometerBearing = function(callback) { 84 | this.onMagnetometerBearingChangeBinded = this.onMagnetometerBearingChange.bind(this); 85 | 86 | this.subscribeCharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_BEARING_CHARACTERISTIC_UUID, this.onMagnetometerBearingChangeBinded, callback); 87 | }; 88 | 89 | MagnetometerService.prototype.unsubscribeMagnetometerBearing = function(callback) { 90 | this.unsubscribeCharacteristic(MAGNETOMETER_SERVICE_UUID, MAGNETOMETER_BEARING_CHARACTERISTIC_UUID, this.onMagnetometerBearingChangeBinded, callback); 91 | }; 92 | 93 | MagnetometerService.prototype.onMagnetometerBearingChange = function(data) { 94 | if (data.length !== 2) { 95 | return; 96 | } 97 | 98 | this.emit('magnetometerBearingChange', data.readInt16LE(0)); 99 | }; 100 | 101 | module.exports = MagnetometerService; 102 | -------------------------------------------------------------------------------- /lib/temperature-service.js: -------------------------------------------------------------------------------- 1 | var TEMPERATURE_SERVICE_UUID = 'e95d6100251d470aa062fa1922dfa9a8'; 2 | var TEMPERATURE_CHARACTERISTIC_UUID = 'e95d9250251d470aa062fa1922dfa9a8'; 3 | var TEMPERATURE_PERIOD_CHARACTERISTIC_UUID = 'e95d1b25251d470aa062fa1922dfa9a8'; 4 | 5 | var TemperatureService = function() { 6 | }; 7 | 8 | TemperatureService.prototype.hasTemperatureService = function() { 9 | return this.hasService(TEMPERATURE_SERVICE_UUID); 10 | }; 11 | 12 | TemperatureService.prototype.readTemperature = function(callback) { 13 | this.readInt8Characteristic(TEMPERATURE_SERVICE_UUID, TEMPERATURE_CHARACTERISTIC_UUID, callback); 14 | }; 15 | 16 | TemperatureService.prototype.subscribeTemperature = function(callback) { 17 | this.onTemperatureChangeBinded = this.onTemperatureChange.bind(this); 18 | 19 | this.subscribeCharacteristic(TEMPERATURE_SERVICE_UUID, TEMPERATURE_CHARACTERISTIC_UUID, this.onTemperatureChangeBinded, callback); 20 | }; 21 | 22 | TemperatureService.prototype.unsubscribeTemperature = function(callback) { 23 | this.unsubscribeCharacteristic(TEMPERATURE_SERVICE_UUID, TEMPERATURE_CHARACTERISTIC_UUID, this.onTemperatureChangeBinded, callback); 24 | }; 25 | 26 | TemperatureService.prototype.onTemperatureChange = function(data) { 27 | this.emit('temperatureChange', data.readInt8(0)); 28 | }; 29 | 30 | TemperatureService.prototype.readTemperaturePeriod = function(callback) { 31 | this.readUInt16LECharacteristic(TEMPERATURE_SERVICE_UUID, TEMPERATURE_PERIOD_CHARACTERISTIC_UUID, callback); 32 | }; 33 | 34 | TemperatureService.prototype.writeTemperaturePeriod = function(period, callback) { 35 | this.writeUInt16LECharacteristic(TEMPERATURE_SERVICE_UUID, TEMPERATURE_PERIOD_CHARACTERISTIC_UUID, period, callback); 36 | }; 37 | 38 | module.exports = TemperatureService; 39 | -------------------------------------------------------------------------------- /lib/uart-service.js: -------------------------------------------------------------------------------- 1 | var UART_SERVICE_UUID = '6e400001b5a3f393e0a9e50e24dcca9e'; 2 | var UART_RX_CHARACTERISTIC_UUID = '6e400002b5a3f393e0a9e50e24dcca9e'; 3 | var UART_TX_CHARACTERISTIC_UUID = '6e400003b5a3f393e0a9e50e24dcca9e'; 4 | 5 | var UartService = function() { 6 | }; 7 | 8 | UartService.prototype.hasUartService = function() { 9 | return this.hasService(UART_SERVICE_UUID); 10 | }; 11 | 12 | UartService.prototype.subscribeUart = function(callback) { 13 | this.onUartDataBinded = this.onUartData.bind(this); 14 | 15 | this.subscribeCharacteristic(UART_SERVICE_UUID, UART_RX_CHARACTERISTIC_UUID, this.onUartDataBinded, callback); 16 | }; 17 | 18 | UartService.prototype.unsubscribeUart = function(callback) { 19 | this.unsubscribeCharacteristic(UART_SERVICE_UUID, UART_RX_CHARACTERISTIC_UUID, this.onUartDataBinded, callback); 20 | }; 21 | 22 | UartService.prototype.onUartData = function(data) { 23 | this.emit('uartData', data); 24 | }; 25 | 26 | UartService.prototype.writeUart = function(data, callback) { 27 | this.writeDataCharacteristic(UART_SERVICE_UUID, UART_TX_CHARACTERISTIC_UUID, data, callback); 28 | }; 29 | 30 | module.exports = UartService; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bbc-microbit", 3 | "version": "0.2.0", 4 | "description": "Control a BBC micro:bit from Node.js using BLE ", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jshint lib/. examples/. *.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/sandeepmistry/node-bbc-microbit" 12 | }, 13 | "keywords": [ 14 | "micro:bit", 15 | "microbit", 16 | "bbc" 17 | ], 18 | "author": "Sandeep Mistry ", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/sandeepmistry/node-bbc-microbit/issues" 22 | }, 23 | "homepage": "https://github.com/sandeepmistry/node-bbc-microbit", 24 | "dependencies": { 25 | "noble-device": "^1.4.0" 26 | }, 27 | "devDependencies": { 28 | "async": "^1.5.2", 29 | "jshint": "^2.9.2" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var async = require('async'); 2 | 3 | var BBCMicrobit = require('./index'); 4 | 5 | BBCMicrobit.discover(function(microbit) { 6 | console.log('discovered ' + microbit); 7 | 8 | microbit.on('disconnect', function() { 9 | console.log('disconnected!'); 10 | process.exit(0); 11 | }); 12 | 13 | microbit.on('temperatureChange', function(temperature) { 14 | console.log('\ton -> temperature change: temperature = %d °C', temperature); 15 | }); 16 | 17 | microbit.on('accelerometerChange', function(x, y, z) { 18 | console.log('\ton -> accelerometer change: accelerometer = %d %d %d G', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 19 | }); 20 | 21 | microbit.on('magnetometerChange', function(x, y, z) { 22 | console.log('\ton -> magnetometer change: magnetometer = %d %d %d', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 23 | }); 24 | 25 | microbit.on('magnetometerBearingChange', function(bearing) { 26 | console.log('\ton -> magnetometer bearing change: magnetometer bearing = %d', bearing); 27 | }); 28 | 29 | microbit.on('buttonAChange', function(pressed) { 30 | console.log('\ton -> button A change: pressed = %d', pressed); 31 | }); 32 | 33 | microbit.on('buttonBChange', function(pressed) { 34 | console.log('\ton -> button B change: pressed = %d', pressed); 35 | }); 36 | 37 | microbit.on('pinDataChange', function(pin, value) { 38 | console.log('\ton -> pin data change: pin = %d, value = %d', pin, value); 39 | }); 40 | 41 | microbit.on('uartData', function(data) { 42 | console.log('\ton -> UART data: data = %s', data.toString('hex')); 43 | }); 44 | 45 | var pin = 0; 46 | 47 | async.series([ 48 | function(callback) { 49 | console.log('connectAndSetUp'); 50 | microbit.connectAndSetUp(callback); 51 | }, 52 | function(callback) { 53 | console.log('readDeviceName'); 54 | microbit.readDeviceName(function(error, deviceName) { 55 | console.log('\tdevice name = ' + deviceName); 56 | callback(); 57 | }); 58 | }, 59 | function(callback) { 60 | console.log('readModelNumber'); 61 | microbit.readModelNumber(function(error, modelNumber) { 62 | console.log('\tmodel number = ' + modelNumber); 63 | callback(); 64 | }); 65 | }, 66 | function(callback) { 67 | console.log('readSerialNumber'); 68 | microbit.readSerialNumber(function(error, serialNumber) { 69 | console.log('\tserial number = ' + serialNumber); 70 | callback(); 71 | }); 72 | }, 73 | function(callback) { 74 | console.log('readFirmwareRevision'); 75 | microbit.readFirmwareRevision(function(error, firmwareRevision) { 76 | console.log('\tfirmware revision = ' + firmwareRevision); 77 | callback(); 78 | }); 79 | }, 80 | function(callback) { 81 | console.log('writeLedMatrixState'); 82 | microbit.writeLedMatrixState(new Buffer('0000000000', 'hex'), callback); 83 | }, 84 | function(callback) { 85 | console.log('readLedMatrixState'); 86 | microbit.readLedMatrixState(function(error, data) { 87 | console.log('\t LED matrix state = %s', data.toString('hex')); 88 | 89 | callback(); 90 | }); 91 | }, 92 | function(callback) { 93 | setTimeout(callback, 5000); 94 | }, 95 | function(callback) { 96 | console.log('writeLedMatrixState'); 97 | microbit.writeLedMatrixState(new Buffer('1f1f1f1f1f', 'hex'), callback); 98 | }, 99 | function(callback) { 100 | console.log('readLedMatrixState'); 101 | microbit.readLedMatrixState(function(error, data) { 102 | console.log('\t LED matrix state = %s', data.toString('hex')); 103 | 104 | callback(); 105 | }); 106 | }, 107 | function(callback) { 108 | setTimeout(callback, 5000); 109 | }, 110 | function(callback) { 111 | console.log('readLedScrollingDelay'); 112 | microbit.readLedScrollingDelay(function(error, delay) { 113 | console.log('\t LED scrolling delay = %d ms', delay); 114 | 115 | callback(); 116 | }); 117 | }, 118 | function(callback) { 119 | console.log('writeLedScrollingDelay'); 120 | microbit.writeLedScrollingDelay(100, callback); 121 | }, 122 | function(callback) { 123 | console.log('readLedScrollingDelay'); 124 | microbit.readLedScrollingDelay(function(error, delay) { 125 | console.log('\t LED scrolling delay = %d ms', delay); 126 | 127 | callback(); 128 | }); 129 | }, 130 | function(callback) { 131 | console.log('writeLedText'); 132 | microbit.writeLedText('Hello from Node.js!', callback); 133 | }, 134 | function(callback) { 135 | console.log('writeTemperaturePeriod'); 136 | microbit.writeTemperaturePeriod(100, callback); 137 | }, 138 | function(callback) { 139 | console.log('readTemperaturePeriod'); 140 | microbit.readTemperaturePeriod(function(error, period) { 141 | console.log('\ttemperature period = %d ms', period); 142 | callback(); 143 | }); 144 | }, 145 | function(callback) { 146 | console.log('readTemperature'); 147 | microbit.readTemperature(function(error, temperature) { 148 | console.log('\ttemperature = %d °C', temperature); 149 | callback(); 150 | }); 151 | }, 152 | function(callback) { 153 | console.log('subscribeTemperature'); 154 | microbit.subscribeTemperature(callback); 155 | }, 156 | function(callback) { 157 | setTimeout(callback, 5000); 158 | }, 159 | function(callback) { 160 | console.log('unsubscribeTemperature'); 161 | microbit.unsubscribeTemperature(callback); 162 | }, 163 | function(callback) { 164 | console.log('writeAccelerometerPeriod'); 165 | microbit.writeAccelerometerPeriod(640, callback); 166 | }, 167 | function(callback) { 168 | console.log('readAccelerometerPeriod'); 169 | microbit.readAccelerometerPeriod(function(error, period) { 170 | console.log('\taccelerometer period = %d ms', period); 171 | callback(); 172 | }); 173 | }, 174 | function(callback) { 175 | console.log('readAccelerometer'); 176 | microbit.readAccelerometer(function(error, x, y, z) { 177 | console.log('\taccelerometer = %d %d %d G', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 178 | callback(); 179 | }); 180 | }, 181 | function(callback) { 182 | console.log('subscribeAccelerometer'); 183 | microbit.subscribeAccelerometer(callback); 184 | }, 185 | function(callback) { 186 | setTimeout(callback, 5000); 187 | }, 188 | function(callback) { 189 | console.log('unsubscribeAccelerometer'); 190 | microbit.unsubscribeAccelerometer(callback); 191 | }, 192 | function(callback) { 193 | console.log('writeMagnetometerPeriod'); 194 | microbit.writeMagnetometerPeriod(640, callback); 195 | }, 196 | function(callback) { 197 | console.log('readMagnetometerPeriod'); 198 | microbit.readMagnetometerPeriod(function(error, period) { 199 | console.log('\tmagnetometer period = %d ms', period); 200 | callback(); 201 | }); 202 | }, 203 | function(callback) { 204 | console.log('readMagnetometer'); 205 | microbit.readMagnetometer(function(error, x, y, z) { 206 | console.log('\tmagnetometer = %d %d %d', x.toFixed(1), y.toFixed(1), z.toFixed(1)); 207 | callback(); 208 | }); 209 | }, 210 | function(callback) { 211 | console.log('subscribeMagnetometer'); 212 | microbit.subscribeMagnetometer(callback); 213 | }, 214 | function(callback) { 215 | setTimeout(callback, 5000); 216 | }, 217 | function(callback) { 218 | console.log('unsubscribeMagnetometer'); 219 | microbit.unsubscribeMagnetometer(callback); 220 | }, 221 | function(callback) { 222 | console.log('readMagnetometerBearing'); 223 | microbit.readMagnetometerBearing(function(error, bearing) { 224 | console.log('\tmagnetometer bearing = %d', bearing); 225 | callback(); 226 | }); 227 | }, 228 | function(callback) { 229 | console.log('subscribeMagnetometerBearing'); 230 | microbit.subscribeMagnetometerBearing(callback); 231 | }, 232 | function(callback) { 233 | setTimeout(callback, 5000); 234 | }, 235 | function(callback) { 236 | console.log('unsubscribeMagnetometerBearing'); 237 | microbit.unsubscribeMagnetometerBearing(callback); 238 | }, 239 | function(callback) { 240 | console.log('subscribeButtonA'); 241 | microbit.subscribeButtonA(callback); 242 | }, 243 | function(callback) { 244 | console.log('subscribeButtonB'); 245 | microbit.subscribeButtonB(callback); 246 | }, 247 | function(callback) { 248 | setTimeout(callback, 10000); 249 | }, 250 | function(callback) { 251 | console.log('unsubscribeButtonB'); 252 | microbit.unsubscribeButtonB(callback); 253 | }, 254 | function(callback) { 255 | console.log('unsubscribeButtonA'); 256 | microbit.unsubscribeButtonA(callback); 257 | }, 258 | function(callback) { 259 | console.log('unsubscribeButtonA'); 260 | microbit.unsubscribeButtonA(callback); 261 | }, 262 | function(callback) { 263 | console.log('writePinAdConfiguration'); 264 | microbit.writePinAdConfiguration(0x00000000, callback); 265 | }, 266 | function(callback) { 267 | console.log('readPinAdConfiguration'); 268 | microbit.readPinAdConfiguration(function(error, value) { 269 | console.log('\tpin AD configuration = %d', value); 270 | 271 | callback(); 272 | }); 273 | }, 274 | function(callback) { 275 | console.log('writePinIoConfiguration'); 276 | microbit.writePinIoConfiguration(0x00000007, callback); 277 | }, 278 | function(callback) { 279 | console.log('readPinIoConfiguration'); 280 | microbit.readPinIoConfiguration(function(error, value) { 281 | console.log('\tpin IO configuration = %d', value); 282 | 283 | callback(); 284 | }); 285 | }, 286 | function(callback) { 287 | console.log('readPinData'); 288 | microbit.readPinData(function(error, data) { 289 | console.log('\tpin data = %j', data); 290 | 291 | callback(); 292 | }); 293 | }, 294 | function(callback) { 295 | console.log('subscribePinData'); 296 | microbit.subscribePinData(callback); 297 | }, 298 | function(callback) { 299 | setTimeout(callback, 10000); 300 | }, 301 | function(callback) { 302 | console.log('unsubscribePinData'); 303 | microbit.unsubscribePinData(callback); 304 | }, 305 | function(callback) { 306 | console.log('writePinIoConfiguration'); 307 | microbit.writePinIoConfiguration(0x00000000, callback); 308 | }, 309 | function(callback) { 310 | console.log('writePinData'); 311 | microbit.writePinData(new Buffer('0001', 'hex'), callback); 312 | }, 313 | function(callback) { 314 | console.log('readPinData'); 315 | microbit.readPinData(function(error, data) { 316 | console.log('\tpin data = %j', data); 317 | 318 | callback(); 319 | }); 320 | }, 321 | function(callback) { 322 | console.log('writePinData'); 323 | microbit.writePinData(new Buffer('0000', 'hex'), callback); 324 | }, 325 | function(callback) { 326 | console.log('readPinData'); 327 | microbit.readPinData(function(error, data) { 328 | console.log('\tpin data = %j', data); 329 | 330 | callback(); 331 | }); 332 | }, 333 | function(callback) { 334 | console.log('pinAnalog', pin); 335 | microbit.pinAnalog(pin, callback); 336 | }, 337 | function(callback) { 338 | console.log('pinDigital', pin); 339 | microbit.pinDigital(pin, callback); 340 | }, 341 | function(callback) { 342 | console.log('pinInput', pin); 343 | microbit.pinInput(pin, callback); 344 | }, 345 | function(callback) { 346 | console.log('readPin', pin); 347 | microbit.readPin(pin, function(error, value) { 348 | console.log('\tpin value = %d', value); 349 | 350 | callback(); 351 | }); 352 | }, 353 | function(callback) { 354 | console.log('pinOutput', pin); 355 | microbit.pinOutput(pin, callback); 356 | }, 357 | function(callback) { 358 | console.log('writePin', pin); 359 | microbit.writePin(pin, 1, callback); 360 | }, 361 | function(callback) { 362 | console.log('writePin', pin); 363 | microbit.writePin(pin, 0, callback); 364 | }, 365 | function(callback) { 366 | console.log('subscribeUart'); 367 | microbit.subscribeUart(callback); 368 | }, 369 | function(callback) { 370 | console.log('writeUart'); 371 | microbit.writeUart(new Buffer('hello UART'), callback); 372 | }, 373 | function(callback) { 374 | setTimeout(callback, 5000); 375 | }, 376 | function(callback) { 377 | console.log('unsubscribeUart'); 378 | microbit.unsubscribeUart(callback); 379 | }, 380 | function(callback) { 381 | console.log('disconnect'); 382 | microbit.disconnect(callback); 383 | } 384 | ]); 385 | }); 386 | --------------------------------------------------------------------------------