import { parseXml } from '@rgrove/parse-xml'; /// class Updater { archiveURL; feedType; bleObject; bleDeviceId; _updaterServiceUUID = "71a4438e-fd52-4b15-b3d2-ec0e3e56193b"; _updaterVersionCharactersiticUUID = "1978a3df-c009-4837-b295-57ef429dde8c"; file; constructor(archiveURL = "/", feedType = "atom", bleObject) { this.archiveURL = archiveURL; this.feedType = feedType; if (bleObject) { this.bleObject = bleObject; } } /* FEEDS */ async getRawArchive() { const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}.${this.feedType}`, { // "mode": "cors" }); const text = await res.text(); return text; } // atom feeds atomGetVersionDetails(entry) { let outEntry = { title: "", date: new Date, link: "", html: "" }; entry.children.forEach((elm) => { let element = elm; if (element.name == "title") { outEntry.title = element.children[0].text; } else if (element.name == "updated") { outEntry.date = new Date(element.children[0].text); } else if (element.name == "link") { outEntry.link = element.attributes["href"]; } else if (element.name == "content") { outEntry.html = element.children[0].text; } }); return outEntry; } async atomGetArchive() { const rawArchive = await this.getRawArchive(); const releaseNotes = parseXml(rawArchive); const output = []; // console.dir(releaseNotes) releaseNotes.children[0].children.forEach((elm) => { if (elm.type == "element") { const element = elm; if (element.name == "entry") { output.push(this.atomGetVersionDetails(element)); } } }); return output; } // rss feeds rssGetVersionDetails(entry) { let outEntry = { title: "", date: new Date, link: "", html: "" }; entry.children.forEach((elm) => { let element = elm; if (element.name == "title") { outEntry.title = element.children[0].text; } else if (element.name == "pubDate") { outEntry.date = element.children[0].text; } else if (element.name == "link") { outEntry.link = element.children[0].text; } else if (element.name == "content") { outEntry.html = element.children[0].text; } }); return outEntry; } async rssGetArchive() { const rawArchive = await this.getRawArchive(); const releaseNotes = parseXml(rawArchive); const output = []; releaseNotes.children[0].children[1].children.forEach((elm) => { if (elm.type == "element") { const element = elm; if (element.name == "item") { output.push(this.rssGetVersionDetails(element)); } } }); return output; } async getArchive() { if (this.feedType == "atom") { return this.atomGetArchive(); } else if (this.feedType == "rss") { return this.rssGetArchive(); } } /* BLUETOOTH */ setDeviceId(id) { this.bleDeviceId = id; } bytesToString(buffer) { return String.fromCharCode.apply(null, new Uint8Array(buffer)); } async readVersionNumber() { return new Promise((resolve, reject) => { this.bleObject.read(this.bleDeviceId, this._updaterServiceUUID, this._updaterVersionCharactersiticUUID, (rawData) => { resolve(this.bytesToString(rawData)); }, (error) => { reject(`Error: ${error}`); }); }); } async getLatestVersion() { let feed = await this.getArchive(); let newestDate = feed[0].date; let i = 0; feed.forEach((item, index) => { if (item.date > newestDate) { newestDate = item.date; i = index; } }); return feed[i].title; } async checkForUpdate() { // read device value const deviceVersion = await this.readVersionNumber(); // compare with latest version const latestVersion = await this.getLatestVersion(); if (deviceVersion != latestVersion) { return true; } // update return false; } async getBoardVersion() { return await this.readVersionNumber(); } /* FILE FLASHING */ async getFirmware(version) { try { const res = await fetch(`http://cors.emaker.limited/?url=${this.archiveURL}/download/${version.title}/firmware.bin`); let buf = await res.arrayBuffer(); this.file = new Int8Array(buf); return true; } catch { return false; } } getFileSize() { return this.file.byteLength; } } export { Updater as default };