@@ -25,8 +25,36 @@ import {
25
25
takeUntil , filter , startWith , first , distinctUntilChanged
26
26
} from 'rxjs/operators' ;
27
27
28
+ const versionsMap = {
29
+ wifi101 : {
30
+ latestVersion : 'WINC1500 19.5.4' ,
31
+ loaderPath : null ,
32
+ latestVersionPath : null
33
+ } ,
34
+ wifiNina : {
35
+ latestVersion : 'NINA 1.2.2' ,
36
+ loaderPath : null ,
37
+ latestVersionPath : null
38
+ }
39
+ } ;
40
+
28
41
const POLLING_INTERVAL = 1500 ;
29
42
43
+ /* The status of the Firmware Updater Tool */
44
+ const FWUToolStatusEnum = Object . freeze ( {
45
+ NOPE : 'NOPE' ,
46
+ OK : 'OK' ,
47
+ CHECKING : 'CHECKING' ,
48
+ ERROR : 'ERROR DOWNLOADING TOOL'
49
+ } ) ;
50
+
51
+ /* The signatures needed to run the commands to use the Firmware Updater Tool */
52
+ const signaturesEnum = Object . freeze ( {
53
+ GET_FIRMWARE_INFO : 'aceffd98d331df0daa5bb3308bb49a95767d77e7a1557c07a0ec544d2f41c3ec67269f01ce9a63e01f3b43e087ab8eb22b7f1d34135b6686e8ce27d4b5dc083ec8e6149df11880d32486448a71280ef3128efccbd45a84dbd7990a9420a65ee86b3822edba3554fa8e6ca11aec12d4dd99ad072285b98bfdf7b2b64f677da50feb8bddef25a36f52d7605078487d8a5d7cbdc84bfa65d510cee97b46baefea149139a9a6ed4b545346040536e33d850e6ad84c83fe605f677e2ca77439de3fa42350ce504ad9a49cf62c6751d4c2a284500d2c628cd52cd73b4c3e7ef08ae823eb8941383f9c6ff0686da532369d3b266ded8fdd33cca1a128068a4795920f25' ,
54
+ UPLOAD_FIRMWARE_BOSSAC : 'b2137435f74601a0b1b090ca1592b14199c1c79c87cecac4bb168456b570f17b635f438f5cd80649a101ab27085394e4a0e92f41a2b1b65932789eee8c3ebf39633a503a8a53d3291944afe10ff88f6ea06b0fd7fd7de6d70b302df3a92091a2abe2691ad1aeee051e4bb69f6afa3bd41e643855769347dca018804ae97bcb1331df796fd8921a11b333b45bebe430d323ddd151a907e8fb0e875a45d093cdb4332ec3dbd72a50341b538e058b3f25d4a528bea514b96b8e0701032d64232b7141c62f2231352f4197a1011292a4c3e900c133824e148f3703ea8374873d9097578146819e62685f1a8cbc442dd435ea603136c86ecf028df39fd10a8b3499c6' ,
55
+ UPLOAD_FIRMWARE_AVRDUDE : '68ed3d9abdc7c77d01223d09c7ae55b08b8ff94f2a42d21a672effb4bdeeb12b10177e831805b3037d9f8d38e8eeeb8327b6c4691731a2a146cfd12398e5a12596e097160ae8d84fc488650ee57439f7fcd83f27d01e9834de555ceec7dc6951b3be5e5a3507752dce8e4ba1f6f9e6494162d537009db899882b9c4fca0868ad446b82fdeabf93bc30c5a39f8fe9c25e799842a10f4171e2896a0e19667b34258f06494663a4a102bcf9fd61d1ff8ebec18204bbd1a66de3e0b53e257ce521b41999dc82428539086ae9a4a5ea7112d87c05a2782cdace0e6576b162294f9ba47c658cc40999ba31be8a129689a703f6c4182055a600b6e41d450fad2896180d'
56
+ } ) ;
57
+
30
58
export default class Daemon {
31
59
constructor ( boardsUrl = 'https://builder.arduino.cc/v3/boards' ) {
32
60
this . BOARDS_URL = boardsUrl ;
@@ -78,6 +106,12 @@ export default class Daemon {
78
106
this . downloadingError = this . downloading . pipe ( filter ( download => download . status === this . DOWNLOAD_ERROR ) )
79
107
. pipe ( first ( ) )
80
108
. pipe ( takeUntil ( this . downloadingDone ) ) ;
109
+
110
+ this . downloadingDone . subscribe ( ( ) => {
111
+ this . FWUToolStatus = FWUToolStatusEnum . OK ;
112
+ } ) ;
113
+
114
+ this . FWUToolStatus = FWUToolStatusEnum . NOPE ;
81
115
}
82
116
83
117
notifyUploadError ( err ) {
@@ -177,4 +211,175 @@ export default class Daemon {
177
211
} ) ;
178
212
this . openSerialMonitor ( port , 1200 ) ;
179
213
}
214
+
215
+ getFirmwareInfo ( boardId , port , wifiModule ) {
216
+ return new Promise ( ( resolve , reject ) => {
217
+ let versionsList = [ ] ;
218
+ let firmwareInfoMessagesSubscription ;
219
+
220
+ const handleFirmwareInfoMessage = message => {
221
+ switch ( message . ProgrammerStatus ) {
222
+ case 'Starting' :
223
+ break ;
224
+ case 'Busy' :
225
+ if ( message . Msg . indexOf ( 'Flashing with command:' ) >= 0 ) {
226
+ return ;
227
+ }
228
+ const versions = JSON . parse ( message . Msg ) ;
229
+ Object . keys ( versions ) . forEach ( v => {
230
+ if ( versions [ v ] [ 0 ] . IsLoader ) {
231
+ versionsMap [ wifiModule ] . loaderPath = versions [ v ] [ 0 ] . Path ;
232
+ }
233
+ else {
234
+ versionsList = [ ...versionsList , ...versions [ v ] ] ;
235
+ }
236
+ } ) ;
237
+ const latestVersion = versionsList . find ( version => version . Name === versionsMap [ wifiModule ] . latestVersion )
238
+ versionsMap [ wifiModule ] . latestVersionPath = latestVersion . Path ;
239
+ break ;
240
+ case 'Error' :
241
+ return reject ( `Couldn't get firmware info: ${ message } ` )
242
+ firmwareInfoMessagesSubscription . unsubscribe ( ) ;
243
+ break ;
244
+ case 'Done' :
245
+ firmwareInfoMessagesSubscription . unsubscribe ( ) ;
246
+ return resolve ( versionsList ) ;
247
+ break ;
248
+ default :
249
+ break ;
250
+ }
251
+ }
252
+
253
+ if ( this . FWUToolStatus !== FWUToolStatusEnum . OK ) {
254
+ return reject ( `Can't get firmware info: couldn't find firmware updater tool` )
255
+ }
256
+
257
+ firmwareInfoMessagesSubscription = this . appMessages . subscribe ( message => {
258
+ if ( message . ProgrammerStatus ) {
259
+ handleFirmwareInfoMessage ( message ) ;
260
+ }
261
+ } ) ;
262
+ const data = {
263
+ board : boardId ,
264
+ port,
265
+ commandline : `"{runtime.tools.fwupdater.path}/updater" -get_available_for {network.password}` ,
266
+ signature : signaturesEnum . GET_FIRMWARE_INFO ,
267
+ extra : {
268
+ auth : {
269
+ password : boardId
270
+ }
271
+ } ,
272
+ filename : 'ListFirmwareVersionsInfo.bin'
273
+ } ;
274
+
275
+ return fetch ( `${ this . pluginURL } /upload` , {
276
+ method : 'POST' ,
277
+ headers : {
278
+ 'Content-Type' : 'text/plain; charset=utf-8'
279
+ } ,
280
+ body : JSON . stringify ( data )
281
+ } ) . then ( response => {
282
+ if ( ! response . ok ) {
283
+ return reject ( `Error fetching ${ this . pluginURL } /upload` ) ;
284
+ }
285
+ } ) . catch ( reason => {
286
+ return reject ( `Coudln't list firmware versions info.` ) ;
287
+ } ) ;
288
+ } )
289
+ }
290
+
291
+ /*
292
+ wifiModule can be either 'wifiNina' or 'wifi101'
293
+ */
294
+ updateFirmware ( boardId , port , wifiModule ) {
295
+ return new Promise ( ( resolve , reject ) => {
296
+ if ( ! port ) {
297
+ return reject ( `Can't update Firmware: no port selected.` ) ;
298
+ }
299
+ this . getFirmwareInfo ( boardId , port , wifiModule ) . then ( versionsList => {
300
+ if ( ! versionsMap [ wifiModule ] && ! versionsMap [ wifiModule ] . latestVersion ) {
301
+ return reject ( `Can't update Firmware: couldn't find module '${ wifiModule } '` ) ;
302
+ }
303
+ const latestVersion = versionsList . find ( version => version . Name === versionsMap [ wifiModule ] . latestVersion ) ;
304
+ if ( ! latestVersion ) {
305
+ return reject ( `Can't update Firmware: couldn't find version '${ versionsMap [ wifiModule ] . latestVersion } ' for module '${ versionsMap [ wifiModule ] } '` ) ;
306
+ }
307
+
308
+ let updateFirmwareMessagesSubscription ;
309
+
310
+ const handleFirmwareUpdateMessage = message => {
311
+ switch ( message . ProgrammerStatus ) {
312
+ case 'Error' :
313
+ return reject ( `Can't update Firmware: ${ message . Msg } ` )
314
+ updateFirmwareMessagesSubscription . unsubscribe ( ) ;
315
+ break ;
316
+ case 'Done' :
317
+ return resolve ( ) ;
318
+ updateFirmwareMessagesSubscription . unsubscribe ( ) ;
319
+ break ;
320
+ default :
321
+ break ;
322
+ }
323
+ }
324
+
325
+ updateFirmwareMessagesSubscription = this . appMessages . subscribe ( message => {
326
+ if ( message . ProgrammerStatus ) {
327
+ handleFirmwareUpdateMessage ( message ) ;
328
+ }
329
+ } ) ;
330
+
331
+ let addresses = '' ;
332
+ const rootCertificates = [ {
333
+ domain : 'arduino.cc' ,
334
+ port : 443
335
+ } ] ;
336
+
337
+ rootCertificates . forEach ( address => {
338
+ if ( address . domain && address . port ) {
339
+ addresses += `-address ${ address . domain } :${ address . port } ` ;
340
+ }
341
+ } ) ;
342
+
343
+ const isUsingAvrdude = boardId === 'uno2018' ;
344
+ const programmer = isUsingAvrdude ? '{runtime.tools.avrdude}/bin/avrdude' : '{runtime.tools.bossac}/bossac' ;
345
+
346
+ const loaderPath = versionsMap [ wifiModule ] . loaderPath ;
347
+ if ( ! loaderPath ) {
348
+ return reject ( `Can't update Firmware: invalid loaderPath` ) ;
349
+ }
350
+
351
+ const data = {
352
+ board : boardId ,
353
+ port,
354
+ 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 } ` ,
355
+ hex : '' ,
356
+ extra : {
357
+ auth : {
358
+ password : loaderPath
359
+ } ,
360
+ verbose : true ,
361
+ params_verbose : `${ versionsMap [ wifiModule ] . latestVersionPath } ${ addresses } ` // eslint-disable-line camelcase
362
+ } ,
363
+ signature : isUsingAvrdude ? signaturesEnum . UPLOAD_FIRMWARE_AVRDUDE : signaturesEnum . UPLOAD_FIRMWARE_BOSSAC ,
364
+ filename : 'CheckFirmwareVersion.bin'
365
+ } ;
366
+
367
+ fetch ( `${ this . pluginURL } /upload` , {
368
+ method : 'POST' ,
369
+ headers : {
370
+ 'Content-Type' : 'text/plain; charset=utf-8'
371
+ } ,
372
+ body : JSON . stringify ( data )
373
+ } ) . then ( response => {
374
+ if ( ! response . ok ) {
375
+ return reject ( `Can't update Firmware: Error fetching ${ this . pluginURL } /upload` ) ;
376
+ }
377
+ } ) . catch ( reason => {
378
+ return reject ( `Can't update Firmware: ${ reason } ` )
379
+ } ) ;
380
+ } ) . catch ( reason => {
381
+ return reject ( reason )
382
+ } ) ;
383
+ } )
384
+ }
180
385
}
0 commit comments