mirror of
https://github.com/thegecko/web-bluetooth-dfu.git
synced 2025-12-12 12:08:13 +08:00
Renamed firmware, added nrf52 support to examples and reserructed dummy disconnects
This commit is contained in:
20
README.md
20
README.md
@@ -1,29 +1,31 @@
|
||||
# Web Bluetooth DFU
|
||||
Device firmware update with Web Bluetooth
|
||||
|
||||
Update device firmware via [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth/) using the protocol here:
|
||||
Update device firmware via [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth/) following the protocol here:
|
||||
|
||||
[http://developer.nordicsemi.com/nRF51_SDK/nRF51_SDK_v8.x.x/doc/8.1.0/s110/html/a00103.html](http://developer.nordicsemi.com/nRF51_SDK/nRF51_SDK_v8.x.x/doc/8.1.0/s110/html/a00103.html)
|
||||
http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk52.v0.9.2/bledfu_transport.html?cp=4_0_2_4_2_4
|
||||
|
||||
## Device Configuration
|
||||
|
||||
Put this firmware onto an [nrf51822](https://www.nordicsemi.com/eng/Products/nRF51-DK):
|
||||
You will need an [nRF51](https://www.nordicsemi.com/Products/nRF51-DK) or [nRF52](https://www.nordicsemi.com/Products/Bluetooth-Smart-Bluetooth-low-energy/nRF52-DK) development kit, flashed with the appropriate image:
|
||||
|
||||
[NRF51822_DFU_Test_BOOT.hex](https://thegecko.github.io/web-bluetooth-dfu/firmware/NRF51822_DFU_Test_BOOT.hex)
|
||||
[nrf51_boot_s110.hex](https://thegecko.github.io/web-bluetooth-dfu/firmware/nrf51_boot_s110.hex)
|
||||
|
||||
Then reset the device.
|
||||
[nrf52_boot_s132.hex](https://thegecko.github.io/web-bluetooth-dfu/firmware/nrf52_boot_s132.hex)
|
||||
|
||||
## Web Example
|
||||
|
||||
Open this site in a Web Bluetooth enabled browser:
|
||||
Open this site in a [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth/) enabled browser:
|
||||
|
||||
[https://thegecko.github.io/web-bluetooth-dfu/](https://thegecko.github.io/web-bluetooth-dfu/)
|
||||
|
||||
## Node Example
|
||||
|
||||
Install the npm dependencies and run.
|
||||
Clone this repository, install the npm dependencies and execute.
|
||||
|
||||
```
|
||||
npm install
|
||||
node example_node
|
||||
```
|
||||
node example_node <device-type>
|
||||
```
|
||||
|
||||
Where ```<device-type>``` is one of ```nrf51``` or ```nrf52```.
|
||||
42
dist/dfu.js
vendored
42
dist/dfu.js
vendored
@@ -1,10 +1,10 @@
|
||||
/* @license
|
||||
*
|
||||
* Device firmware update with Web Bluetooth
|
||||
* Version: 0.0.1
|
||||
* Version: 0.0.2
|
||||
*
|
||||
* Protocol from:
|
||||
* http://developer.nordicsemi.com/nRF51_SDK/nRF51_SDK_v8.x.x/doc/8.1.0/s110/html/a00103.html
|
||||
* http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.sdk52.v0.9.2/bledfu_transport.html?cp=4_0_2_4_2_4
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
@@ -114,27 +114,32 @@
|
||||
*/
|
||||
function writeMode(device) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var controlChar = null;
|
||||
/*
|
||||
// Disconnect event currently not implemented...
|
||||
// TODO: once disconnect event is implemented we should resolve in its callback...
|
||||
device.addEventListener("gattserverdisconnected", () => {
|
||||
log("DFU Target issued GAP Disconnect and reset into Bootloader/DFU mode.");
|
||||
resolve(device);
|
||||
});
|
||||
*/
|
||||
var characteristics = null;
|
||||
|
||||
connect(device)
|
||||
.then(chars => {
|
||||
log("enabling notifications");
|
||||
controlChar = chars.controlChar;
|
||||
return controlChar.startNotifications();
|
||||
characteristics = chars;
|
||||
return characteristics.controlChar.startNotifications();
|
||||
})
|
||||
.then(() => {
|
||||
log("writing modeData");
|
||||
return controlChar.writeValue(new Uint8Array([1, 4]));
|
||||
return characteristics.controlChar.writeValue(new Uint8Array([1, 4]));
|
||||
})
|
||||
.then(() => {
|
||||
log("modeData written");
|
||||
resolve(device); // TODO: once disconnect event is implemented we should resolve in its callback...
|
||||
// Hack to gracefully disconnect without disconnect event
|
||||
setTimeout(() => {
|
||||
characteristics.server.disconnect();
|
||||
resolve(device);
|
||||
}, 2000);
|
||||
})
|
||||
.catch(error => {
|
||||
error = "writeMode error: " + error;
|
||||
@@ -143,7 +148,7 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contains basic functionality for performing safety checks on software updates for nRF5 based devices.
|
||||
* Init packet used for pre-checking to ensure the following image is compatible with the device.
|
||||
@@ -175,8 +180,9 @@
|
||||
return versionChar.readValue()
|
||||
.then(data => {
|
||||
console.log('read versionChar');
|
||||
var major = data.getUint8(0);
|
||||
var minor = data.getUint8(1);
|
||||
var view = new DataView(data);
|
||||
var major = view.getUint8(0);
|
||||
var minor = view.getUint8(1);
|
||||
return transfer(chars, arrayBuffer, imageType, major, minor);
|
||||
});
|
||||
} else {
|
||||
@@ -232,14 +238,14 @@
|
||||
log("found packet characteristic");
|
||||
packetChar = characteristic;
|
||||
service.getCharacteristic(versionUUID)
|
||||
.then(characteristic => { // Older DFU implementations (from older Nordic SDKs) have no DFU Version characteristic. So this may fail.
|
||||
// Older DFU implementations (from older Nordic SDKs) have no DFU Version characteristic. So this may fail.
|
||||
.then(characteristic => {
|
||||
log("found version characteristic");
|
||||
versionChar = characteristic;
|
||||
complete();
|
||||
})
|
||||
.catch(error => {
|
||||
error += ' no version charactersitic found';
|
||||
log(error);
|
||||
log("info: no version characteristic found");
|
||||
complete();
|
||||
});
|
||||
})
|
||||
@@ -382,7 +388,7 @@
|
||||
case OPCODE.VALIDATE_FIRMWARE:
|
||||
log('complete, reset...');
|
||||
/*
|
||||
// Disconnect event currently not implemented
|
||||
// TODO: Resolve in disconnect event handler when implemented in Web Bluetooth API.
|
||||
controlChar.service.device.addEventListener("gattserverdisconnected", () => {
|
||||
resolve();
|
||||
});
|
||||
@@ -390,7 +396,11 @@
|
||||
controlChar.writeValue(new Uint8Array([OPCODE.ACTIVATE_IMAGE_AND_RESET]))
|
||||
.then(() => {
|
||||
log('image activated and dfu target reset');
|
||||
resolve(); // TODO: Resolve in disconnect event handler when implemented in Web Bluetooth API.
|
||||
// Hack to gracefully disconnect without disconnect event
|
||||
setTimeout(() => {
|
||||
chars.server.disconnect();
|
||||
resolve();
|
||||
}, 2000);
|
||||
})
|
||||
.catch(error => {
|
||||
error = "error resetting: " + error;
|
||||
|
||||
@@ -5,12 +5,30 @@ var fs = require('fs');
|
||||
var log = console.log;
|
||||
dfu.addLogger(log);
|
||||
|
||||
var fileMask = "firmware/NRF51822_{0}_Rob_OTA.hex";
|
||||
var fileMask = "";
|
||||
var fileName = null;
|
||||
|
||||
var deviceType = process.argv[2];
|
||||
if (!deviceType) {
|
||||
deviceType = "nrf51";
|
||||
log("no device-type specified, defaulting to " + deviceType);
|
||||
}
|
||||
|
||||
switch(deviceType) {
|
||||
case "nrf51":
|
||||
fileMask = "firmware/nrf51_app_{0}.hex";
|
||||
break;
|
||||
case "nrf52":
|
||||
fileMask = "firmware/nrf52_app.hex";
|
||||
break;
|
||||
default:
|
||||
log("unknown device-type: " + deviceType);
|
||||
process.exit();
|
||||
}
|
||||
|
||||
dfu.findDevice({ services: [0x180D] })
|
||||
.then(device => {
|
||||
fileName = fileMask.replace("{0}", device.name === "Hi_Rob" ? "Bye" : "Hi");
|
||||
fileName = fileMask.replace("{0}", device.name === "Hi_Rob" ? "bye" : "hi");
|
||||
log("found device: " + device.name);
|
||||
log("using file name: " + fileName);
|
||||
|
||||
|
||||
@@ -2,20 +2,35 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>web-bluetooth-dfu</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style>
|
||||
html, body { width: 100%; padding: 0; margin: 0; font-family: sans-serif; }
|
||||
input { font-size: 20px; }
|
||||
button { font-size: 20px; padding: 0 20px; display: block; margin: 20px auto; }
|
||||
.device-type { width: 160px; margin: 20px auto; white-space: nowrap; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button onclick="setMode()" style="font-size: 20px;">Set Mode</button>
|
||||
<button onclick="findDFU()" style="font-size: 20px;">Transfer</button>
|
||||
<button onclick="both()" style="font-size: 20px;">Both</button>
|
||||
<div class="device-type">
|
||||
<input type="radio" name="device-type" id="nrf51" checked>
|
||||
<label for="nrf51">nRF51</label>
|
||||
<input type="radio" name="device-type" id="nrf52">
|
||||
<label for="nrf52">nRF52</label>
|
||||
</div>
|
||||
|
||||
<button onclick="setMode()">Set Mode</button>
|
||||
<button onclick="findDFU()">Transfer</button>
|
||||
<button onclick="both()">Both</button>
|
||||
|
||||
<div id="results"></div>
|
||||
|
||||
<script src="dist/dfu.js"></script>
|
||||
<script src="dist/hex2bin.js"></script>
|
||||
|
||||
<script>
|
||||
var urlMask = "//thegecko.github.io/web-bluetooth-dfu/firmware/NRF51822_{0}_Rob_OTA.hex";
|
||||
var urlMask52 = "https://raw.githubusercontent.com/mjdietzx/web-bluetooth-dfu/develop/firmware/ble_app_hrs_with_dfu_nrf52.hex";
|
||||
var resultsEl = document.getElementById("results");
|
||||
var urlBase = "//thegecko.github.io/web-bluetooth-dfu/firmware/";
|
||||
|
||||
function log(message) {
|
||||
console.log(message);
|
||||
@@ -36,8 +51,18 @@
|
||||
|
||||
function transfer(device) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var url = urlMask.replace("{0}", device.name === "Hi_Rob" ? "Bye" : "Hi");
|
||||
//var url = urlMask52; // nRF52832 application (example BLE heart rate from Nordic SDK) for DFU OTA update.
|
||||
var url = "";
|
||||
var deviceType = document.querySelector('input[name="device-type"]:checked').id;
|
||||
|
||||
switch(deviceType) {
|
||||
case "nrf51":
|
||||
url = urlBase + "nrf51_app_{0}.hex";
|
||||
url = url.replace("{0}", device.name === "Hi_Rob" ? "bye" : "hi");
|
||||
break;
|
||||
case "nrf52":
|
||||
url = urlBase + "nrf52_app.hex";
|
||||
break;
|
||||
}
|
||||
|
||||
download(url)
|
||||
.then(hex => {
|
||||
|
||||
Reference in New Issue
Block a user