possible file transfer
This commit is contained in:
85
dist/index.cjs.js
vendored
85
dist/index.cjs.js
vendored
@@ -8,15 +8,21 @@ class Updater {
|
|||||||
feedType;
|
feedType;
|
||||||
bleObject;
|
bleObject;
|
||||||
bleDeviceId;
|
bleDeviceId;
|
||||||
_updaterServiceUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e56193b";
|
_updaterServiceUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561900";
|
||||||
_updaterVersionCharactersiticUUID = "1978a3df-c009-4837-b295-57ef429dde8c";
|
_updaterVersionCharactersiticUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561910";
|
||||||
|
_updaterCommandCharacterisitcUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561920";
|
||||||
|
_updateFileCharacteristicUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561930";
|
||||||
file;
|
file;
|
||||||
constructor(archiveURL = "/", feedType = "atom", bleObject) {
|
_fileSize;
|
||||||
|
_fileProgress = 0;
|
||||||
|
_packetSize;
|
||||||
|
constructor(archiveURL = "/", feedType = "atom", bleObject, packetSize = 512) {
|
||||||
this.archiveURL = archiveURL;
|
this.archiveURL = archiveURL;
|
||||||
this.feedType = feedType;
|
this.feedType = feedType;
|
||||||
if (bleObject) {
|
if (bleObject) {
|
||||||
this.bleObject = bleObject;
|
this.bleObject = bleObject;
|
||||||
}
|
}
|
||||||
|
this._packetSize = packetSize;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
FEEDS
|
FEEDS
|
||||||
@@ -157,6 +163,7 @@ class Updater {
|
|||||||
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
||||||
let buf = await res.arrayBuffer();
|
let buf = await res.arrayBuffer();
|
||||||
this.file = new Int8Array(buf);
|
this.file = new Int8Array(buf);
|
||||||
|
this._fileSize = this.file.byteLength;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -164,7 +171,77 @@ class Updater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getFileSize() {
|
getFileSize() {
|
||||||
return this.file.byteLength;
|
return this._fileSize;
|
||||||
|
}
|
||||||
|
async sendNextPacket() {
|
||||||
|
let packet = this.file.slice(this._fileProgress, this._fileProgress + this._packetSize);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.bleObject.write(this.bleDeviceId, this._updaterServiceUUID, this._updateFileCharacteristicUUID, packet.buffer, () => {
|
||||||
|
resolve(true);
|
||||||
|
}, (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async sendEndCmd(agree) {
|
||||||
|
const buffer = new ArrayBuffer(1);
|
||||||
|
let view = new Int8Array(buffer);
|
||||||
|
view[0] = agree ? 3 : 4;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// start and autoconnect before you run this function, so that you can have an "uninterrupted" connection when the board reboots
|
||||||
|
async flashFirmware(progressCallback) {
|
||||||
|
// write filesize to board
|
||||||
|
// await notify from cmd - ready
|
||||||
|
// send a packet
|
||||||
|
// check for error
|
||||||
|
// write file length
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const buffer = new ArrayBuffer(4);
|
||||||
|
let view = new Int32Array(buffer);
|
||||||
|
view[0] = this._fileSize;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
// start notify
|
||||||
|
this.bleObject.startNotification(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, async (rawData) => {
|
||||||
|
let dataView = new Int8Array(rawData);
|
||||||
|
if (dataView[0] == 1) {
|
||||||
|
// send file
|
||||||
|
await this.sendNextPacket();
|
||||||
|
progressCallback(`Sending (${Math.floor((this._fileProgress * 100) / this._fileSize)})`);
|
||||||
|
}
|
||||||
|
else if (dataView[0] == 2) {
|
||||||
|
// done logic
|
||||||
|
if (this._fileProgress >= this._fileSize) {
|
||||||
|
// send agree
|
||||||
|
await this.sendEndCmd(true);
|
||||||
|
progressCallback(`Complete!`);
|
||||||
|
this.bleObject.stopNotification(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, () => {
|
||||||
|
// success
|
||||||
|
resolve(true);
|
||||||
|
}, (error) => {
|
||||||
|
reject("Error: Failed to stop notify");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// send disagree
|
||||||
|
await this.sendEndCmd(false);
|
||||||
|
progressCallback(`Error, starting over`);
|
||||||
|
this._fileProgress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dataView[0] == 15) {
|
||||||
|
// error cmd
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error on remote");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no command
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error: command does not exist");
|
||||||
|
}
|
||||||
|
}, () => { reject("Error: Failed to start notify"); });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
dist/index.d.ts
vendored
10
dist/index.d.ts
vendored
@@ -11,8 +11,13 @@ export default class Updater {
|
|||||||
protected bleDeviceId: string;
|
protected bleDeviceId: string;
|
||||||
private readonly _updaterServiceUUID;
|
private readonly _updaterServiceUUID;
|
||||||
private readonly _updaterVersionCharactersiticUUID;
|
private readonly _updaterVersionCharactersiticUUID;
|
||||||
|
private readonly _updaterCommandCharacterisitcUUID;
|
||||||
|
private readonly _updateFileCharacteristicUUID;
|
||||||
file: Int8Array;
|
file: Int8Array;
|
||||||
constructor(archiveURL?: string, feedType?: string, bleObject?: BLECentralPlugin.BLECentralPluginStatic);
|
private _fileSize;
|
||||||
|
private _fileProgress;
|
||||||
|
private _packetSize;
|
||||||
|
constructor(archiveURL?: string, feedType?: string, bleObject?: BLECentralPlugin.BLECentralPluginStatic, packetSize?: number);
|
||||||
private getRawArchive;
|
private getRawArchive;
|
||||||
private atomGetVersionDetails;
|
private atomGetVersionDetails;
|
||||||
private atomGetArchive;
|
private atomGetArchive;
|
||||||
@@ -27,4 +32,7 @@ export default class Updater {
|
|||||||
getBoardVersion(): Promise<string>;
|
getBoardVersion(): Promise<string>;
|
||||||
getFirmware(version: versionNotes): Promise<boolean>;
|
getFirmware(version: versionNotes): Promise<boolean>;
|
||||||
getFileSize(): number;
|
getFileSize(): number;
|
||||||
|
private sendNextPacket;
|
||||||
|
private sendEndCmd;
|
||||||
|
flashFirmware(progressCallback: (message: string) => void): Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|||||||
85
dist/index.es.js
vendored
85
dist/index.es.js
vendored
@@ -6,15 +6,21 @@ class Updater {
|
|||||||
feedType;
|
feedType;
|
||||||
bleObject;
|
bleObject;
|
||||||
bleDeviceId;
|
bleDeviceId;
|
||||||
_updaterServiceUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e56193b";
|
_updaterServiceUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561900";
|
||||||
_updaterVersionCharactersiticUUID = "1978a3df-c009-4837-b295-57ef429dde8c";
|
_updaterVersionCharactersiticUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561910";
|
||||||
|
_updaterCommandCharacterisitcUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561920";
|
||||||
|
_updateFileCharacteristicUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e561930";
|
||||||
file;
|
file;
|
||||||
constructor(archiveURL = "/", feedType = "atom", bleObject) {
|
_fileSize;
|
||||||
|
_fileProgress = 0;
|
||||||
|
_packetSize;
|
||||||
|
constructor(archiveURL = "/", feedType = "atom", bleObject, packetSize = 512) {
|
||||||
this.archiveURL = archiveURL;
|
this.archiveURL = archiveURL;
|
||||||
this.feedType = feedType;
|
this.feedType = feedType;
|
||||||
if (bleObject) {
|
if (bleObject) {
|
||||||
this.bleObject = bleObject;
|
this.bleObject = bleObject;
|
||||||
}
|
}
|
||||||
|
this._packetSize = packetSize;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
FEEDS
|
FEEDS
|
||||||
@@ -155,6 +161,7 @@ class Updater {
|
|||||||
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
||||||
let buf = await res.arrayBuffer();
|
let buf = await res.arrayBuffer();
|
||||||
this.file = new Int8Array(buf);
|
this.file = new Int8Array(buf);
|
||||||
|
this._fileSize = this.file.byteLength;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
@@ -162,7 +169,77 @@ class Updater {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getFileSize() {
|
getFileSize() {
|
||||||
return this.file.byteLength;
|
return this._fileSize;
|
||||||
|
}
|
||||||
|
async sendNextPacket() {
|
||||||
|
let packet = this.file.slice(this._fileProgress, this._fileProgress + this._packetSize);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.bleObject.write(this.bleDeviceId, this._updaterServiceUUID, this._updateFileCharacteristicUUID, packet.buffer, () => {
|
||||||
|
resolve(true);
|
||||||
|
}, (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
async sendEndCmd(agree) {
|
||||||
|
const buffer = new ArrayBuffer(1);
|
||||||
|
let view = new Int8Array(buffer);
|
||||||
|
view[0] = agree ? 3 : 4;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// start and autoconnect before you run this function, so that you can have an "uninterrupted" connection when the board reboots
|
||||||
|
async flashFirmware(progressCallback) {
|
||||||
|
// write filesize to board
|
||||||
|
// await notify from cmd - ready
|
||||||
|
// send a packet
|
||||||
|
// check for error
|
||||||
|
// write file length
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const buffer = new ArrayBuffer(4);
|
||||||
|
let view = new Int32Array(buffer);
|
||||||
|
view[0] = this._fileSize;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
// start notify
|
||||||
|
this.bleObject.startNotification(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, async (rawData) => {
|
||||||
|
let dataView = new Int8Array(rawData);
|
||||||
|
if (dataView[0] == 1) {
|
||||||
|
// send file
|
||||||
|
await this.sendNextPacket();
|
||||||
|
progressCallback(`Sending (${Math.floor((this._fileProgress * 100) / this._fileSize)})`);
|
||||||
|
}
|
||||||
|
else if (dataView[0] == 2) {
|
||||||
|
// done logic
|
||||||
|
if (this._fileProgress >= this._fileSize) {
|
||||||
|
// send agree
|
||||||
|
await this.sendEndCmd(true);
|
||||||
|
progressCallback(`Complete!`);
|
||||||
|
this.bleObject.stopNotification(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, () => {
|
||||||
|
// success
|
||||||
|
resolve(true);
|
||||||
|
}, (error) => {
|
||||||
|
reject("Error: Failed to stop notify");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// send disagree
|
||||||
|
await this.sendEndCmd(false);
|
||||||
|
progressCallback(`Error, starting over`);
|
||||||
|
this._fileProgress = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dataView[0] == 15) {
|
||||||
|
// error cmd
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error on remote");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no command
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error: command does not exist");
|
||||||
|
}
|
||||||
|
}, () => { reject("Error: Failed to start notify"); });
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
142
src/index.ts
142
src/index.ts
@@ -2,10 +2,10 @@
|
|||||||
import { parseXml, XmlDocument, XmlElement, XmlText } from "@rgrove/parse-xml";
|
import { parseXml, XmlDocument, XmlElement, XmlText } from "@rgrove/parse-xml";
|
||||||
|
|
||||||
export type versionNotes = {
|
export type versionNotes = {
|
||||||
title: string;
|
title: string;
|
||||||
date: Date | string;
|
date: Date | string;
|
||||||
link: string;
|
link: string;
|
||||||
html: string;
|
html: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Updater {
|
export default class Updater {
|
||||||
@@ -17,17 +17,24 @@ export default class Updater {
|
|||||||
|
|
||||||
private readonly _updaterServiceUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561900";
|
private readonly _updaterServiceUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561900";
|
||||||
private readonly _updaterVersionCharactersiticUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561910";
|
private readonly _updaterVersionCharactersiticUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561910";
|
||||||
|
private readonly _updaterCommandCharacterisitcUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561920";
|
||||||
|
private readonly _updateFileCharacteristicUUID: string = "71a4438e-fd52-4b15-b3d2-ec0e3e561930";
|
||||||
|
|
||||||
public file: Int8Array;
|
public file: Int8Array;
|
||||||
|
private _fileSize: number;
|
||||||
|
private _fileProgress: number = 0;
|
||||||
|
|
||||||
|
private _packetSize: number;
|
||||||
|
|
||||||
constructor(archiveURL: string = "/", feedType: string = "atom", bleObject?: BLECentralPlugin.BLECentralPluginStatic) {
|
constructor(archiveURL: string = "/", feedType: string = "atom", bleObject?: BLECentralPlugin.BLECentralPluginStatic, packetSize: number = 512) {
|
||||||
this.archiveURL = archiveURL;
|
this.archiveURL = archiveURL;
|
||||||
this.feedType = feedType;
|
this.feedType = feedType;
|
||||||
if (bleObject) {
|
if (bleObject) {
|
||||||
this.bleObject = bleObject;
|
this.bleObject = bleObject;
|
||||||
}
|
}
|
||||||
|
this._packetSize = packetSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FEEDS
|
FEEDS
|
||||||
*/
|
*/
|
||||||
@@ -42,7 +49,7 @@ export default class Updater {
|
|||||||
|
|
||||||
// atom feeds
|
// atom feeds
|
||||||
private atomGetVersionDetails(entry: XmlElement): versionNotes {
|
private atomGetVersionDetails(entry: XmlElement): versionNotes {
|
||||||
let outEntry: versionNotes = {title: "", date: new Date, link: "", html: ""};
|
let outEntry: versionNotes = { title: "", date: new Date, link: "", html: "" };
|
||||||
entry.children.forEach((elm) => {
|
entry.children.forEach((elm) => {
|
||||||
let element = elm as XmlElement;
|
let element = elm as XmlElement;
|
||||||
if (element.name == "title") {
|
if (element.name == "title") {
|
||||||
@@ -54,7 +61,7 @@ export default class Updater {
|
|||||||
else if (element.name == "link") {
|
else if (element.name == "link") {
|
||||||
outEntry.link = element.attributes["href"];
|
outEntry.link = element.attributes["href"];
|
||||||
} else if (element.name == "content") {
|
} else if (element.name == "content") {
|
||||||
outEntry.html = (element.children[0] as XmlText).text;
|
outEntry.html = (element.children[0] as XmlText).text;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -80,7 +87,7 @@ export default class Updater {
|
|||||||
|
|
||||||
// rss feeds
|
// rss feeds
|
||||||
private rssGetVersionDetails(entry: XmlElement): versionNotes {
|
private rssGetVersionDetails(entry: XmlElement): versionNotes {
|
||||||
let outEntry: versionNotes = {title: "", date: new Date, link: "", html: ""};
|
let outEntry: versionNotes = { title: "", date: new Date, link: "", html: "" };
|
||||||
entry.children.forEach((elm) => {
|
entry.children.forEach((elm) => {
|
||||||
let element = elm as XmlElement;
|
let element = elm as XmlElement;
|
||||||
if (element.name == "title") {
|
if (element.name == "title") {
|
||||||
@@ -92,7 +99,7 @@ export default class Updater {
|
|||||||
else if (element.name == "link") {
|
else if (element.name == "link") {
|
||||||
outEntry.link = (element.children[0] as XmlText).text;
|
outEntry.link = (element.children[0] as XmlText).text;
|
||||||
} else if (element.name == "content") {
|
} else if (element.name == "content") {
|
||||||
outEntry.html = (element.children[0] as XmlText).text;
|
outEntry.html = (element.children[0] as XmlText).text;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -114,11 +121,11 @@ export default class Updater {
|
|||||||
})
|
})
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getArchive(): Promise<versionNotes[]> {
|
public async getArchive(): Promise<versionNotes[]> {
|
||||||
if (this.feedType == "atom") {
|
if (this.feedType == "atom") {
|
||||||
return this.atomGetArchive()
|
return this.atomGetArchive()
|
||||||
} else if (this.feedType == "rss"){
|
} else if (this.feedType == "rss") {
|
||||||
return this.rssGetArchive()
|
return this.rssGetArchive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,16 +145,17 @@ export default class Updater {
|
|||||||
private async readVersionNumber(): Promise<string> {
|
private async readVersionNumber(): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.bleObject.read(
|
this.bleObject.read(
|
||||||
this.bleDeviceId,
|
this.bleDeviceId,
|
||||||
this._updaterServiceUUID,
|
this._updaterServiceUUID,
|
||||||
this._updaterVersionCharactersiticUUID,
|
this._updaterVersionCharactersiticUUID,
|
||||||
(rawData: ArrayBuffer) => {
|
(rawData: ArrayBuffer) => {
|
||||||
resolve(this.bytesToString(rawData));
|
resolve(this.bytesToString(rawData));
|
||||||
},
|
},
|
||||||
(error: string) => {
|
(error: string) => {
|
||||||
reject(`Error: ${error}`);
|
reject(`Error: ${error}`);
|
||||||
}
|
}
|
||||||
)});
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getLatestVersion(): Promise<string> {
|
private async getLatestVersion(): Promise<string> {
|
||||||
@@ -169,7 +177,7 @@ export default class Updater {
|
|||||||
// compare with latest version
|
// compare with latest version
|
||||||
const latestVersion = await this.getLatestVersion();
|
const latestVersion = await this.getLatestVersion();
|
||||||
if (deviceVersion != latestVersion) {
|
if (deviceVersion != latestVersion) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// update
|
// update
|
||||||
return false;
|
return false;
|
||||||
@@ -178,7 +186,7 @@ export default class Updater {
|
|||||||
public async getBoardVersion(): Promise<string> {
|
public async getBoardVersion(): Promise<string> {
|
||||||
return await this.readVersionNumber();
|
return await this.readVersionNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
FILE FLASHING
|
FILE FLASHING
|
||||||
*/
|
*/
|
||||||
@@ -188,6 +196,7 @@ export default class Updater {
|
|||||||
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`);
|
||||||
let buf = await res.arrayBuffer();
|
let buf = await res.arrayBuffer();
|
||||||
this.file = new Int8Array(buf);
|
this.file = new Int8Array(buf);
|
||||||
|
this._fileSize = this.file.byteLength;
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return false;
|
||||||
@@ -195,11 +204,86 @@ export default class Updater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getFileSize(): number {
|
public getFileSize(): number {
|
||||||
return this.file.byteLength;
|
return this._fileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public async flashFirmware(): Promise<boolean> {
|
private async sendNextPacket(): Promise<boolean> {
|
||||||
|
let packet = this.file.slice(this._fileProgress, this._fileProgress+this._packetSize);
|
||||||
// }
|
return new Promise((resolve, reject) => {
|
||||||
|
this.bleObject.write(this.bleDeviceId, this._updaterServiceUUID, this._updateFileCharacteristicUUID, packet.buffer,
|
||||||
|
() => {
|
||||||
|
resolve(true);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async sendEndCmd(agree: boolean): Promise<void> {
|
||||||
|
const buffer = new ArrayBuffer(1);
|
||||||
|
let view = new Int8Array(buffer);
|
||||||
|
view[0] = agree ? 3 : 4;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start and autoconnect before you run this function, so that you can have an "uninterrupted" connection when the board reboots
|
||||||
|
public async flashFirmware(progressCallback: (message: string) => void): Promise<boolean> {
|
||||||
|
// write filesize to board
|
||||||
|
// await notify from cmd - ready
|
||||||
|
// send a packet
|
||||||
|
// check for error
|
||||||
|
|
||||||
|
// write file length
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const buffer = new ArrayBuffer(4)
|
||||||
|
let view = new Int32Array(buffer);
|
||||||
|
view[0] = this._fileSize;
|
||||||
|
await this.bleObject.withPromises.write(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID, buffer);
|
||||||
|
|
||||||
|
// start notify
|
||||||
|
this.bleObject.startNotification(this.bleDeviceId, this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID,
|
||||||
|
async (rawData: ArrayBuffer): Promise<void> => {
|
||||||
|
let dataView = new Int8Array(rawData);
|
||||||
|
if (dataView[0] == 1) {
|
||||||
|
// send file
|
||||||
|
await this.sendNextPacket();
|
||||||
|
progressCallback(`Sending (${Math.floor((this._fileProgress *100)/this._fileSize)})`);
|
||||||
|
} else if (dataView[0] == 2) {
|
||||||
|
// done logic
|
||||||
|
if (this._fileProgress >= this._fileSize) {
|
||||||
|
// send agree
|
||||||
|
await this.sendEndCmd(true);
|
||||||
|
progressCallback(`Complete!`);
|
||||||
|
this.bleObject.stopNotification(this.bleDeviceId,
|
||||||
|
this._updaterServiceUUID, this._updaterCommandCharacterisitcUUID,
|
||||||
|
() => {
|
||||||
|
// success
|
||||||
|
resolve(true);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
reject("Error: Failed to stop notify");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// send disagree
|
||||||
|
await this.sendEndCmd(false);
|
||||||
|
progressCallback(`Error, starting over`);
|
||||||
|
this._fileProgress = 0;
|
||||||
|
}
|
||||||
|
} else if (dataView[0] == 15) {
|
||||||
|
// error cmd
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error on remote");
|
||||||
|
} else {
|
||||||
|
// no command
|
||||||
|
progressCallback(`Error on remote`);
|
||||||
|
reject("Error: command does not exist");
|
||||||
|
}
|
||||||
|
}, () => { reject("Error: Failed to start notify"); });
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user