diff --git a/demo/app.jsx b/demo/app.jsx index 0f90bec8..a3fc8911 100644 --- a/demo/app.jsx +++ b/demo/app.jsx @@ -52,16 +52,16 @@ const handleBootloaderMode = (e, port) => { daemon.setBootloaderMode(port); }; -const handleUpdateFirmware = (e, boardId, port, wifiModule) => { +const handleUpdateFirmware = (e, boardId, port, firmwareVersion) => { e.preventDefault(); if (![firmwareUpdater.updateStatusEnum.NOPE, firmwareUpdater.updateStatusEnum.DONE, firmwareUpdater.updateStatusEnum.ERROR].includes(firmwareUpdater.updating.getValue().status)) { return; } - firmwareUpdater.updateFirmware(boardId, port, wifiModule); + firmwareUpdater.updateFirmware(boardId, port, firmwareVersion); firmwareUpdater.updatingDone.subscribe(() => { console.log('Firmware updated successfully!'); }); - + firmwareUpdater.updatingError.subscribe(update => { console.log('Something went wrong when trying to update the firmware'); console.error(update.err); @@ -197,10 +197,10 @@ class App extends React.Component { close - handleBootloaderMode(e, device.Name)}> bootloader mode - - handleUpdateFirmware(e, 'mkrwifi1010', device.Name, 'wifiNina')}> - Wifi NINA update firmware - - handleUpdateFirmware(e, 'mkr1000', device.Name, 'wifi101')}> - Wifi 101 update firmware + - handleUpdateFirmware(e, 'mkrwifi1010', device.Name, '1.2.1')}> + MKR WiFi 1010 update firmware + - handleUpdateFirmware(e, 'mkr1000', device.Name, '19.4.4')}> + MKR1000 update firmware ); diff --git a/package-lock.json b/package-lock.json index f7b00371..6451fde1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "arduino-create-agent-js-client", - "version": "2.2.5", + "version": "2.2.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2895,9 +2895,9 @@ } }, "eslint-plugin-import": { - "version": "2.17.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz", - "integrity": "sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g==", + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.17.3.tgz", + "integrity": "sha512-qeVf/UwXFJbeyLbxuY8RgqDyEKCkqV7YC+E5S5uOjAp4tOc8zj01JP3ucoBM8JcEqd1qRasJSg6LLlisirfy0Q==", "dev": true, "requires": { "array-includes": "^3.0.3", @@ -2910,7 +2910,7 @@ "lodash": "^4.17.11", "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.10.0" + "resolve": "^1.11.0" }, "dependencies": { "debug": { @@ -2947,12 +2947,6 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -2960,9 +2954,9 @@ "dev": true }, "resolve": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", + "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", "dev": true, "requires": { "path-parse": "^1.0.6" diff --git a/package.json b/package.json index f591fb33..50a6f8f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "arduino-create-agent-js-client", - "version": "2.2.5", + "version": "2.2.6", "description": "JS module providing discovery of the Arduino Create Plugin and communication with it", "main": "lib/index.js", "module": "es/index.js", @@ -33,7 +33,7 @@ "cross-env": "^5.2.0", "eslint": "^5.16.0", "eslint-config-airbnb-base": "^13.1.0", - "eslint-plugin-import": "^2.17.2", + "eslint-plugin-import": "^2.17.3", "eslint-plugin-react": "^7.13.0", "html-webpack-plugin": "^3.2.0", "lodash": "^4.17.11", diff --git a/src/chrome-app-daemon.js b/src/chrome-app-daemon.js index 0f270660..6f38f6f3 100644 --- a/src/chrome-app-daemon.js +++ b/src/chrome-app-daemon.js @@ -19,7 +19,9 @@ */ import { interval } from 'rxjs'; -import { distinctUntilChanged, filter, startWith, takeUntil } from 'rxjs/operators'; +import { + distinctUntilChanged, filter, startWith, takeUntil +} from 'rxjs/operators'; import Daemon from './daemon'; diff --git a/src/firmware-updater.js b/src/firmware-updater.js index be5bd240..2c512172 100644 --- a/src/firmware-updater.js +++ b/src/firmware-updater.js @@ -1,4 +1,4 @@ -import {BehaviorSubject} from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import { takeUntil, @@ -6,19 +6,6 @@ import { first } from 'rxjs/operators'; -const versionsMap = { - wifi101: { - latestVersion: 'WINC1500 19.5.4', - loaderPath: null, - latestVersionPath: null - }, - wifiNina: { - latestVersion: 'NINA 1.2.2', - loaderPath: null, - latestVersionPath: null - } -}; - /* The status of the Firmware Updater Tool */ const FWUToolStatusEnum = Object.freeze({ NOPE: 'NOPE', @@ -54,27 +41,30 @@ export default class FirmwareUpdater { this.FWUToolStatus = FWUToolStatusEnum.NOPE; this.updating = new BehaviorSubject({ status: this.updateStatusEnum.NOPE }); - + this.updatingDone = this.updating.pipe(filter(update => update.status === this.updateStatusEnum.DONE)) .pipe(first()) .pipe(takeUntil(this.updating.pipe(filter(update => update.status === this.updateStatusEnum.ERROR)))); - + this.updatingError = this.updating.pipe(filter(update => update.status === this.updateStatusEnum.ERROR)) .pipe(first()) .pipe(takeUntil(this.updatingDone)); - + this.gotFWInfo = this.updating.pipe(filter(update => update.status === this.updateStatusEnum.GOT_INFO)) .pipe(first()) .pipe(takeUntil(this.updatingDone)) .pipe(takeUntil(this.updatingError)); } - getFirmwareInfo(boardId, port, wifiModule) { + getFirmwareInfo(boardId, port, firmwareVersion) { + this.firmwareVersionData = null; + this.loaderPath = null; this.updating.next({ status: this.updateStatusEnum.GETTING_INFO }); let versionsList = []; let firmwareInfoMessagesSubscription; const handleFirmwareInfoMessage = message => { + let versions; switch (message.ProgrammerStatus) { case 'Starting': break; @@ -82,31 +72,33 @@ export default class FirmwareUpdater { if (message.Msg.indexOf('Flashing with command:') >= 0) { return; } - const versions = JSON.parse(message.Msg); + versions = JSON.parse(message.Msg); Object.keys(versions).forEach(v => { if (versions[v][0].IsLoader) { - versionsMap[wifiModule].loaderPath = versions[v][0].Path; + this.loaderPath = versions[v][0].Path; } else { versionsList = [...versionsList, ...versions[v]]; } }); - const latestVersion = versionsList.find(version => version.Name === versionsMap[wifiModule].latestVersion) - versionsMap[wifiModule].latestVersionPath = latestVersion.Path; + this.firmwareVersionData = versionsList.find(version => version.Name.split(' ').splice(-1)[0].trim() === firmwareVersion); + if (!this.firmwareVersionData) { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't get firmware info: couldn't find version '${firmwareVersion}' for board '${boardId}'` }); + } break; case 'Error': - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Couldn't get firmware info: ${message}` }) + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Couldn't get firmware info: ${message.Msg}` }); firmwareInfoMessagesSubscription.unsubscribe(); break; case 'Done': firmwareInfoMessagesSubscription.unsubscribe(); - this.updating.next({ status: this.updateStatusEnum.GOT_INFO, versionsList }) + this.updating.next({ status: this.updateStatusEnum.GOT_INFO }); break; default: break; } - } - + }; + if (this.FWUToolStatus !== FWUToolStatusEnum.OK) { this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't get firmware info: couldn't find firmware updater tool` }); return; @@ -139,110 +131,104 @@ export default class FirmwareUpdater { }).then(response => { if (!response.ok) { this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Error fetching ${this.Daemon.pluginURL}/upload` }); - return; + } - }).catch(reason => { + }).catch(() => { this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Coudln't list firmware versions info.` }); - return ; - }); + + }); } - /* - wifiModule can be either 'wifiNina' or 'wifi101' - */ - updateFirmware(boardId, port, wifiModule) { + updateFirmware(boardId, port, firmwareVersion) { this.updating.next({ status: this.updateStatusEnum.STARTED }); - if (!port) { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: no port selected.` }); - return; - } - this.gotFWInfo.subscribe(state => { - if (!versionsMap[wifiModule] && !versionsMap[wifiModule].latestVersion) { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: couldn't find module '${wifiModule}'` }); + this.Daemon.closeSerialMonitor(port); + this.Daemon.serialMonitorOpened.pipe(filter(open => !open)).pipe(first()).subscribe(() => { + if (!port) { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: no port selected.` }); return; } - const latestVersion = state.versionsList.find(version => version.Name === versionsMap[wifiModule].latestVersion); - if (!latestVersion) { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: couldn't find version '${versionsMap[wifiModule].latestVersion}' for module '${versionsMap[wifiModule]}'` }); - return; - } - - let updateFirmwareMessagesSubscription; - - const handleFirmwareUpdateMessage = message => { - switch (message.ProgrammerStatus) { - case 'Error': - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: ${message.Msg}`}); - updateFirmwareMessagesSubscription.unsubscribe(); - break; - case 'Done': - this.updating.next({ status: this.updateStatusEnum.DONE}); - updateFirmwareMessagesSubscription.unsubscribe(); - break; - default: - break; + this.gotFWInfo.subscribe(() => { + if (!this.firmwareVersionData) { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: couldn't find version '${firmwareVersion}' for board '${boardId}'` }); + return; } - } - updateFirmwareMessagesSubscription = this.Daemon.appMessages.subscribe(message => { - if (message.ProgrammerStatus) { - handleFirmwareUpdateMessage(message); - } - }); + let updateFirmwareMessagesSubscription; + + const handleFirmwareUpdateMessage = message => { + switch (message.ProgrammerStatus) { + case 'Error': + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: ${message.Msg}` }); + updateFirmwareMessagesSubscription.unsubscribe(); + break; + case 'Done': + this.updating.next({ status: this.updateStatusEnum.DONE }); + updateFirmwareMessagesSubscription.unsubscribe(); + break; + default: + break; + } + }; - let addresses = ''; - const rootCertificates = [{ - domain: 'arduino.cc', - port: 443 - }]; - - rootCertificates.forEach(address => { - if (address.domain && address.port) { - addresses += `-address ${address.domain}:${address.port} `; - } - }); + updateFirmwareMessagesSubscription = this.Daemon.appMessages.subscribe(message => { + if (message.ProgrammerStatus) { + handleFirmwareUpdateMessage(message); + } + }); - const isUsingAvrdude = boardId === 'uno2018'; - const programmer = isUsingAvrdude ? '{runtime.tools.avrdude}/bin/avrdude' : '{runtime.tools.bossac}/bossac'; + let addresses = ''; + const rootCertificates = [{ + domain: 'arduino.cc', + port: 443 + }]; - const loaderPath = versionsMap[wifiModule].loaderPath; - if (!loaderPath) { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: invalid loaderPath` }); - return; - } + rootCertificates.forEach(address => { + if (address.domain && address.port) { + addresses += `-address ${address.domain}:${address.port} `; + } + }); - const data = { - board: boardId, - port, - commandline: `"{runtime.tools.fwupdater.path}/updater" -flasher {network.password} -firmware {upload.verbose} -port {serial.port} -restore_binary "{build.path}/{build.project_name}.bin" -programmer ${programmer}`, - hex: '', - extra: { - auth: { - password: loaderPath - }, - verbose: true, - params_verbose: `${versionsMap[wifiModule].latestVersionPath} ${addresses}` // eslint-disable-line camelcase - }, - signature: isUsingAvrdude ? signaturesEnum.UPLOAD_FIRMWARE_AVRDUDE : signaturesEnum.UPLOAD_FIRMWARE_BOSSAC, - filename: 'CheckFirmwareVersion.bin' - }; - - fetch(`${this.Daemon.pluginURL}/upload`, { - method: 'POST', - headers: { - 'Content-Type': 'text/plain; charset=utf-8' - }, - body: JSON.stringify(data) - }).then(response => { - if (!response.ok) { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: error fetching ${this.Daemon.pluginURL}/upload` }); + const isUsingAvrdude = boardId === 'uno2018'; + const programmer = isUsingAvrdude ? '{runtime.tools.avrdude}/bin/avrdude' : '{runtime.tools.bossac}/bossac'; + + if (!this.loaderPath) { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: 'loaderPath' is empty or 'null'` }); return; } - }).catch(reason => { - this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: ${reason}` }); - return; + + const data = { + board: boardId, + port, + commandline: `"{runtime.tools.fwupdater.path}/updater" -flasher {network.password} -firmware {upload.verbose} -port {serial.port} -restore_binary "{build.path}/{build.project_name}.bin" -programmer ${programmer}`, + hex: '', + extra: { + auth: { + password: this.loaderPath + }, + verbose: true, + params_verbose: `${this.firmwareVersionData.Path} ${addresses}` // eslint-disable-line camelcase + }, + signature: isUsingAvrdude ? signaturesEnum.UPLOAD_FIRMWARE_AVRDUDE : signaturesEnum.UPLOAD_FIRMWARE_BOSSAC, + filename: 'CheckFirmwareVersion.bin' + }; + + fetch(`${this.Daemon.pluginURL}/upload`, { + method: 'POST', + headers: { + 'Content-Type': 'text/plain; charset=utf-8' + }, + body: JSON.stringify(data) + }).then(response => { + if (!response.ok) { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: error fetching ${this.Daemon.pluginURL}/upload` }); + + } + }).catch(reason => { + this.updating.next({ status: this.updateStatusEnum.ERROR, err: `Can't update Firmware: ${reason}` }); + + }); }); + this.getFirmwareInfo(boardId, port, firmwareVersion); }); - this.getFirmwareInfo(boardId, port, wifiModule); } } diff --git a/src/index.js b/src/index.js index 997c6d0f..9af44873 100644 --- a/src/index.js +++ b/src/index.js @@ -25,4 +25,4 @@ import FirmwareUpdater from './firmware-updater'; const Daemon = window.navigator.userAgent.indexOf(' CrOS ') !== -1 ? ChromeOsDaemon : SocketDaemon; export default Daemon; -export {FirmwareUpdater}; +export { FirmwareUpdater };