From c5384c3c9dfceb40f89beffd2a3efe26790548f6 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Tue, 10 Jul 2018 17:58:25 +0200 Subject: [PATCH 1/6] fix provisioning --- src/boardConfiguration.js | 63 ++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/boardConfiguration.js b/src/boardConfiguration.js index 1317ca34..b9632cbc 100644 --- a/src/boardConfiguration.js +++ b/src/boardConfiguration.js @@ -18,12 +18,12 @@ * */ -import { BehaviorSubject } from 'rxjs'; +import { BehaviorSubject, timer } from 'rxjs'; import { takeUntil, filter, first } from 'rxjs/operators'; import { provisioningSketch } from './sketches/provisioning.ino'; const BAUDRATE = 9600; - +const UPLOAD_DONE_TIMER = 5000; export default class BoardConfiguration { constructor(daemon) { this.CONFIGURE_IN_PROGRESS = 'CONFIGURE_IN_PROGRESS'; @@ -40,6 +40,14 @@ export default class BoardConfiguration { }); } + initConfig() { + this.configuring.next({ status: this.CONFIGURE_IN_PROGRESS, msg: 'Starting board configuration...' }); + } + + notifyError(msg) { + this.configuring.next({ status: this.CONFIGURE_ERROR, msg: msg, err: msg}); + } + /** * Returns the correct Provisioning sketch after adding fqbn * @param {string} fqbn @@ -72,19 +80,11 @@ export default class BoardConfiguration { } if (partialMessage.indexOf('Would you like to generate a new private key and CSR (y/N):') !== -1) { partialMessage = ''; - const serialData = { - com_name: board.port, - data: 'y\n' - }; - this.daemon.writeSerial(board.port, serialData); + this.daemon.writeSerial(board.port, 'y\n'); } if (partialMessage.indexOf('Your ECCX08 is unlocked, would you like to lock it (y/N):') !== -1) { partialMessage = ''; - const serialData = { - com_name: board.port, - data: 'y\n' - }; - this.daemon.writeSerial(board.port, serialData); + this.daemon.writeSerial(board.port, 'y\n'); } const begin = partialMessage.indexOf('-----BEGIN CERTIFICATE REQUEST-----'); @@ -125,12 +125,7 @@ export default class BoardConfiguration { (notAfter.getUTCFullYear() - notBefore.getUTCFullYear()) + '\n' + compressedCert.serial + '\n' + compressedCert.signature + '\n'; - - const serialData = { - com_name: board.port, - data: answers - }; - this.daemon.writeSerial(board.port, serialData); + this.daemon.writeSerial(board.port, answers); }); return storing.finally(() => this.serialMessagesSubscription.unsubscribe()); @@ -143,7 +138,7 @@ export default class BoardConfiguration { * @param {function} createDeviceCb used to create the device associated to the user */ configure(compiledSketch, board, createDeviceCb) { - this.configuring.next({ status: this.CONFIGURE_IN_PROGRESS, msg: 'Starting board configuration' }); + this.configuring.next({ status: this.CONFIGURE_IN_PROGRESS, msg: 'Uploading provisioning sketch...' }); if (!this.daemon.channelOpen.getValue()) { const errorMessage = `Couldn't configure board at port ${board.port} because we there is no open channel to the Arduino Create Plugin.`; this.configuring.next({ @@ -190,26 +185,46 @@ export default class BoardConfiguration { } this.daemon.uploadingDone.pipe(first()).subscribe(() => { + this.configuring.next({ + status: this.CONFIGURE_IN_PROGRESS, + msg: 'Provisioning sketch uploaded successfully. Opening serial monitor...' + }); this.daemon.serialMonitorOpened.pipe(takeUntil(this.daemon.serialMonitorOpened.pipe(filter(open => open)))) .subscribe(() => { + this.configuring.next({ + status: this.CONFIGURE_IN_PROGRESS, + msg: 'Serial monitor opened. Generating CSR...' + }); this.getCsr(board) - .then(csr => createDeviceCb(csr)) - .then(data => this.storeCertificate(data.compressed)) + .then(csr => { + this.configuring.next({ + status: this.CONFIGURE_IN_PROGRESS, + msg: 'CSR generated. Creating device...' + }); + return createDeviceCb(csr) + }) + .then(data => { + this.configuring.next({ + status: this.CONFIGURE_IN_PROGRESS, + msg: 'Device created. Storing certificate...' + }); + return this.storeCertificate(data.compressed, board); + }) .then(() => this.configuring.next({ status: this.CONFIGURE_DONE })) .catch(reason => this.configuring.next({ status: this.CONFIGURE_ERROR, - msg: `Couldn't configure board at port ${board.port}. Configuration failed with error: ${reason}`, + msg: `Couldn't configure board at port ${board.port}. Configuration failed with error: ${reason.message}`, err: reason.toString() })) .finally(() => this.daemon.closeSerialMonitor(board.port, BAUDRATE)); }, error => { this.configuring.next({ status: this.CONFIGURE_ERROR, - msg: `Couldn't configure board at port ${board.port}. Configuration failed with error: ${error}`, + msg: `Couldn't configure board at port ${board.port}. Configuration failed with error: ${error.message}`, err: error.toString() }); }); - this.daemon.openSerialMonitor(board.port, BAUDRATE); + timer(UPLOAD_DONE_TIMER).subscribe(() => this.daemon.openSerialMonitor(board.port, BAUDRATE)); }); this.daemon.uploadingError.pipe(first()).subscribe(upload => { From 2cf314452983064819887cdb7e921df82ad07fdb Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Tue, 10 Jul 2018 18:30:12 +0200 Subject: [PATCH 2/6] minor fix: error messages --- src/socket-daemon.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/socket-daemon.js b/src/socket-daemon.js index d8fd8c20..1d9ec9d1 100644 --- a/src/socket-daemon.js +++ b/src/socket-daemon.js @@ -312,7 +312,7 @@ export default class SocketDaemon extends Daemon { } const serialPort = this.devicesList.getValue().serial.find(p => p.Name === port); if (!serialPort) { - return this.serialMonitorOpened.error(new Error(`Can't find port ${port}`)); + return this.serialMonitorOpened.error(new Error(`Can't find board at ${port}`)); } this.appMessages .pipe(takeUntil(this.serialMonitorOpened.pipe(filter(open => !open)))) @@ -321,7 +321,7 @@ export default class SocketDaemon extends Daemon { this.serialMonitorOpened.next(false); } if (message.Cmd === 'CloseFail') { - this.serialMonitorOpened.error(new Error(`Failed to close serial ${port}`)); + this.serialMonitorOpened.error(new Error(`Failed to close serial monitor at ${port}`)); } }); this.socket.emit('command', `close ${port}`); From 01ec37763dd2a5a17ca010e4b0e588d7cf930a43 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 11 Jul 2018 11:46:05 +0200 Subject: [PATCH 3/6] ease upload --- src/boardConfiguration.js | 26 ++------------------------ src/daemon.js | 31 +++++++++++++++++++++++++++++++ src/socket-daemon.js | 33 +++++++++++++++++++-------------- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/boardConfiguration.js b/src/boardConfiguration.js index b9632cbc..ee539058 100644 --- a/src/boardConfiguration.js +++ b/src/boardConfiguration.js @@ -150,29 +150,6 @@ export default class BoardConfiguration { } this.serialMonitorContent = ''; - const uploadTarget = { - board: board.fqbn, - port: board.port, - network: false - }; - - const file = { - name: compiledSketch.name + board.upload[0].ext, - data: compiledSketch.hex - }; - - const uploadData = { - files: [file], - commandline: board.upload[0].commandline, - signature: board.upload[0].options.signature, - extrafiles: [], - options: { - wait_for_upload_port: (board.upload[0].options.wait_for_upload_port === true || board.upload[0].options.wait_for_upload_port === 'true'), // eslint-disable-line camelcase - use_1200bps_touch: (board.upload[0].options.use_1200bps_touch === true || board.upload[0].options.use_1200bps_touch === 'true'), // eslint-disable-line camelcase - params_verbose: '-v' // eslint-disable-line camelcase - } - }; - // check the uploading status: if (this.daemon.uploading.getValue().status === this.daemon.UPLOAD_IN_PROGRESS) { // if there is an upload in course, notify observers; @@ -231,6 +208,7 @@ export default class BoardConfiguration { this.configuring.next({ status: this.CONFIGURE_ERROR, err: `Couldn't configure board at port ${board.port}. Upload failed with error: ${upload.err}` }); }); - this.daemon.upload(uploadTarget, uploadData); + this.daemon.initUpload(); + this.daemon.uploadSketch(compiledSketch, board); } } diff --git a/src/daemon.js b/src/daemon.js index c5452e90..3f0d1f88 100644 --- a/src/daemon.js +++ b/src/daemon.js @@ -113,4 +113,35 @@ export default class Daemon { } throw new Error('Stop Upload not supported on Chrome OS'); } + + uploadSketch(compiledSketch, board) { + const uploadTarget = { + board: board.fqbn, + port: board.port, + network: false + }; + + const file = { + name: compiledSketch.name + board.upload[0].ext, + data: compiledSketch.hex + }; + + const uploadData = { + files: [file], + commandline: board.upload[0].commandline, + signature: board.upload[0].options.signature, + extrafiles: [], + options: { + wait_for_upload_port: (board.upload[0].options.wait_for_upload_port === true || board.upload[0].options.wait_for_upload_port === 'true'), + use_1200bps_touch: (board.upload[0].options.use_1200bps_touch === true || board.upload[0].options.use_1200bps_touch === 'true'), + params_verbose: '-v' + } + }; + + this.upload(uploadTarget, uploadData); + } + + initUpload() { + this.uploading.next({ status: this.UPLOAD_NOPE }); + } } diff --git a/src/socket-daemon.js b/src/socket-daemon.js index 1d9ec9d1..0a17c559 100644 --- a/src/socket-daemon.js +++ b/src/socket-daemon.js @@ -23,7 +23,7 @@ import semVerCompare from 'semver-compare'; import { detect } from 'detect-browser'; import { BehaviorSubject, timer } from 'rxjs'; -import { filter, takeUntil } from 'rxjs/operators'; +import { filter, takeUntil, first } from 'rxjs/operators'; import Daemon from './daemon'; @@ -332,8 +332,8 @@ export default class SocketDaemon extends Daemon { return; } if (message.Flash === 'Ok' && message.ProgrammerStatus === 'Done') { - this.uploading.next({ status: this.UPLOAD_DONE, msg: message.Flash }); - return; + // After the upload is completed the port goes down for a while, so we have to wait a few seconds + return timer(10000).subscribe(() => this.uploading.next({ status: this.UPLOAD_DONE, msg: message.Flash })); } switch (message.ProgrammerStatus) { case 'Starting': @@ -439,17 +439,22 @@ export default class SocketDaemon extends Daemon { payload.extrafiles.push({ filename: data.files[i].name, hex: data.files[i].data }); } - fetch(`${this.pluginURL}/upload`, { - method: 'POST', - headers: { - 'Content-Type': 'text/plain; charset=utf-8' - }, - body: JSON.stringify(payload) - }) - .catch(error => { - this.uploading.next({ status: this.UPLOAD_ERROR, err: error }); - }); - } + this.serialMonitorOpened.pipe(filter(open => !open)) + .pipe(first()) + .subscribe(() => { + + fetch(`${this.pluginURL}/upload`, { + method: 'POST', + headers: { + 'Content-Type': 'text/plain; charset=utf-8' + }, + body: JSON.stringify(payload) + }) + .catch(error => { + this.uploading.next({ status: this.UPLOAD_ERROR, err: error }); + }); + }) + } /** * Download tool From 191d847c5b8b419be6c3e5f8d4108ac67670f8c1 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Wed, 11 Jul 2018 15:15:46 +0200 Subject: [PATCH 4/6] minor fix --- src/boardConfiguration.js | 4 +--- src/socket-daemon.js | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/boardConfiguration.js b/src/boardConfiguration.js index ee539058..7f6446ac 100644 --- a/src/boardConfiguration.js +++ b/src/boardConfiguration.js @@ -23,7 +23,6 @@ import { takeUntil, filter, first } from 'rxjs/operators'; import { provisioningSketch } from './sketches/provisioning.ino'; const BAUDRATE = 9600; -const UPLOAD_DONE_TIMER = 5000; export default class BoardConfiguration { constructor(daemon) { this.CONFIGURE_IN_PROGRESS = 'CONFIGURE_IN_PROGRESS'; @@ -63,7 +62,6 @@ export default class BoardConfiguration { let partialMessage = ''; const gettingCsr = new Promise((resolve, reject) => { const parseCsrQuestions = message => { - // TODO: store partial messages partialMessage += message; if (partialMessage.indexOf('No ECCX08 present') !== -1) { @@ -201,7 +199,7 @@ export default class BoardConfiguration { err: error.toString() }); }); - timer(UPLOAD_DONE_TIMER).subscribe(() => this.daemon.openSerialMonitor(board.port, BAUDRATE)); + this.daemon.openSerialMonitor(board.port, BAUDRATE); }); this.daemon.uploadingError.pipe(first()).subscribe(upload => { diff --git a/src/socket-daemon.js b/src/socket-daemon.js index 0a17c559..977342b9 100644 --- a/src/socket-daemon.js +++ b/src/socket-daemon.js @@ -31,6 +31,7 @@ import Daemon from './daemon'; const MIN_VERSION = '1.1.71'; const browser = detect(); const POLLING_INTERVAL = 2500; +const UPLOAD_DONE_TIMER = 5000; const PROTOCOL = { HTTP: 'http', @@ -333,7 +334,7 @@ export default class SocketDaemon extends Daemon { } if (message.Flash === 'Ok' && message.ProgrammerStatus === 'Done') { // After the upload is completed the port goes down for a while, so we have to wait a few seconds - return timer(10000).subscribe(() => this.uploading.next({ status: this.UPLOAD_DONE, msg: message.Flash })); + return timer(UPLOAD_DONE_TIMER).subscribe(() => this.uploading.next({ status: this.UPLOAD_DONE, msg: message.Flash })); } switch (message.ProgrammerStatus) { case 'Starting': From 15efcb8a8c5a7d5afad4ebf8fc45fcb76fb238e5 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 12 Jul 2018 12:37:31 +0200 Subject: [PATCH 5/6] configure status subjects --- src/boardConfiguration.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/boardConfiguration.js b/src/boardConfiguration.js index 7f6446ac..9ed59978 100644 --- a/src/boardConfiguration.js +++ b/src/boardConfiguration.js @@ -33,7 +33,9 @@ export default class BoardConfiguration { this.daemon = daemon; this.serialMonitorContent = ''; this.configuring = new BehaviorSubject({ status: this.CONFIGURE_NOPE }); - + this.configureDone = this.configuring.pipe(filter(configure => configure.status === this.CONFIGURE_DONE)); + this.configureInProgress = this.configuring.pipe(filter(configure => configure.status === this.CONFIGURE_IN_PROGRESS)); + this.configureError = this.configuring.pipe(filter(configure => configure.status === this.CONFIGURE_ERROR)); this.daemon.serialMonitorMessages.subscribe(message => { this.serialMonitorContent += message; }); From 7e9dcfdc6d93a9ce8b5e80bdccdc7afb4ccef303 Mon Sep 17 00:00:00 2001 From: Alberto Iannaccone Date: Thu, 12 Jul 2018 16:00:22 +0200 Subject: [PATCH 6/6] move uploadSketch in boardConfiguration --- src/boardConfiguration.js | 29 ++++++++++++++++++++++++++++- src/daemon.js | 27 --------------------------- src/index.js | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/boardConfiguration.js b/src/boardConfiguration.js index 9ed59978..0967f7da 100644 --- a/src/boardConfiguration.js +++ b/src/boardConfiguration.js @@ -131,6 +131,33 @@ export default class BoardConfiguration { return storing.finally(() => this.serialMessagesSubscription.unsubscribe()); } + uploadSketch(compiledSketch, board) { + const uploadTarget = { + board: board.fqbn, + port: board.port, + network: false + }; + + const file = { + name: compiledSketch.name + board.upload[0].ext, + data: compiledSketch.hex + }; + + const uploadData = { + files: [file], + commandline: board.upload[0].commandline, + signature: board.upload[0].options.signature, + extrafiles: [], + options: { + wait_for_upload_port: (board.upload[0].options.wait_for_upload_port === true || board.upload[0].options.wait_for_upload_port === 'true'), + use_1200bps_touch: (board.upload[0].options.use_1200bps_touch === true || board.upload[0].options.use_1200bps_touch === 'true'), + params_verbose: '-v' + } + }; + + this.daemon.upload(uploadTarget, uploadData); + } + /** * Uploads the sketch and performs action in order to configure the board for Arduino Cloud * @param {Object} compiledSketch the Object containing the provisioning sketch, ready to be compiled @@ -209,6 +236,6 @@ export default class BoardConfiguration { }); this.daemon.initUpload(); - this.daemon.uploadSketch(compiledSketch, board); + this.uploadSketch(compiledSketch, board); } } diff --git a/src/daemon.js b/src/daemon.js index 3f0d1f88..3ca42392 100644 --- a/src/daemon.js +++ b/src/daemon.js @@ -114,33 +114,6 @@ export default class Daemon { throw new Error('Stop Upload not supported on Chrome OS'); } - uploadSketch(compiledSketch, board) { - const uploadTarget = { - board: board.fqbn, - port: board.port, - network: false - }; - - const file = { - name: compiledSketch.name + board.upload[0].ext, - data: compiledSketch.hex - }; - - const uploadData = { - files: [file], - commandline: board.upload[0].commandline, - signature: board.upload[0].options.signature, - extrafiles: [], - options: { - wait_for_upload_port: (board.upload[0].options.wait_for_upload_port === true || board.upload[0].options.wait_for_upload_port === 'true'), - use_1200bps_touch: (board.upload[0].options.use_1200bps_touch === true || board.upload[0].options.use_1200bps_touch === 'true'), - params_verbose: '-v' - } - }; - - this.upload(uploadTarget, uploadData); - } - initUpload() { this.uploading.next({ status: this.UPLOAD_NOPE }); } diff --git a/src/index.js b/src/index.js index a5790ff6..1b95a951 100644 --- a/src/index.js +++ b/src/index.js @@ -25,5 +25,5 @@ import BoardConfiguration from './boardConfiguration'; const Daemon = window.navigator.userAgent.indexOf(' CrOS ') !== -1 ? ChromeOsDaemon : SocketDaemon; -export { BoardConfiguration }; +export { Daemon, BoardConfiguration }; export default Daemon;