2018-12-30 22:17:58 -08:00
const { app , BrowserWindow , ipcMain } = require ( 'electron' )
const { download } = require ( 'electron-dl' )
2019-01-01 15:47:54 -08:00
const { spawn } = require ( 'child_process' ) ;
2019-01-02 15:50:05 -08:00
const { execFile } = require ( 'child_process' ) ;
2019-01-13 22:17:32 -08:00
const fs = require ( 'fs' ) ;
2018-12-30 22:17:58 -08:00
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
2019-01-02 18:44:21 -08:00
var avrdudeErr = "" ;
2019-01-04 04:19:17 -08:00
var avrdudeIsRunning = false ;
2019-01-02 18:44:21 -08:00
2018-12-30 22:17:58 -08:00
function createWindow ( ) {
// Create the browser window.
2019-01-15 04:24:58 -08:00
win = new BrowserWindow ( { width : 800 , height : 600 , backgroundColor : '#312450' } )
2018-12-30 22:17:58 -08:00
// and load the index.html of the app.
win . loadFile ( 'index.html' )
// Open the DevTools.
2019-01-04 02:47:00 -08:00
//win.webContents.openDevTools()
2018-12-30 22:17:58 -08:00
// Emitted when the window is closed.
win . on ( 'closed' , ( ) => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null
} )
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app . on ( 'ready' , createWindow )
// Quit when all windows are closed.
app . on ( 'window-all-closed' , ( ) => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
2019-01-14 14:34:00 -08:00
//if (process.platform !== 'darwin')
{
2018-12-30 22:17:58 -08:00
app . quit ( )
}
} )
app . on ( 'activate' , ( ) => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if ( win === null ) {
createWindow ( )
}
} )
2018-12-31 05:59:18 -08:00
ipcMain . on ( 'download' , ( e , args ) => {
2019-01-13 22:17:32 -08:00
filename = args . url . substring ( args . url . lastIndexOf ( '/' ) + 1 ) ;
dlDir = app . getPath ( 'downloads' ) ;
fullFile = dlDir + "/" + filename ;
2019-06-30 23:46:35 -07:00
useTSDir = false ;
//Try and find the TunerStudio ecuDef directory
if ( process . platform == "win32" )
{
//Windows
TunerStudioDir = "C:\Program Files (x86)\EFIAnalytics\TunerStudioMS\config\ecuDef\" ;
try {
fs . existsSync ( TunerStudioDir ) ; //Directory exists
fs . accessSync ( TunerStudioDir , fs . constants . R _OK | fs . constants . W _OK ) ; //Directory can be written to
useTSDir = true ;
} catch ( err ) {
useTSDir = false ;
}
}
else if ( process . platform == "darwin" )
{
//Mac
TunerStudioDir = "/Applications/TunerStudio MS.app/Contents/Java/config/ecuDef/"
try {
fs . existsSync ( TunerStudioDir ) ; //Directory exists
fs . accessSync ( TunerStudioDir , fs . constants . R _OK | fs . constants . W _OK ) ; //Directory can be written to
useTSDir = true ;
} catch ( err ) {
useTSDir = false ;
}
}
else if ( process . platform == "linux" )
{
platform = "avrdude-linux_i686" ;
}
2019-02-11 15:10:32 -08:00
//Special case for handling the build that is from master. This is ALWAYS downloaded as there's no way of telling when it was last updated.
if ( filename == "master.hex" || filename == "master.ini" )
{
if ( fs . existsSync ( fullFile ) )
{
fs . unlinkSync ( fullFile )
console . log ( 'Master version selected, removing local file forcing re-download: ' + filename ) ;
}
}
2019-01-13 22:17:32 -08:00
//console.log("Filename: " + fullFile );
fs . exists ( fullFile , ( exists ) => {
if ( exists ) {
console . log ( "File " + fullFile + " already exists in Downloads directory. Skipping download" ) ;
e . sender . send ( "download complete" , fullFile , "exists" ) ;
}
else {
download ( BrowserWindow . getFocusedWindow ( ) , args . url )
. then ( dl => e . sender . send ( "download complete" , dl . getSavePath ( ) , dl . getState ( ) ) )
. catch ( console . error ) ;
}
} ) ;
2018-12-30 22:17:58 -08:00
} ) ;
2019-01-01 15:47:54 -08:00
ipcMain . on ( 'uploadFW' , ( e , args ) => {
2019-01-04 04:19:17 -08:00
if ( avrdudeIsRunning == true ) { return ; }
avrdudeIsRunning = true ; //Indicate that an avrdude process has started
2019-01-01 15:47:54 -08:00
var platform ;
2019-01-04 04:10:03 -08:00
var burnStarted = false ;
var burnPercent = 0 ;
2019-01-01 19:47:18 -08:00
if ( process . platform == "win32" ) { platform = "avrdude-windows" ; }
2019-06-30 23:46:35 -07:00
//else if(process.platform == "darwin") { platform = "avrdude-darwin-x86"; }
else if ( process . platform == "darwin" ) { platform = "avrdude-darwin-x86_64" ; }
2019-01-01 19:47:18 -08:00
else if ( process . platform == "linux" ) { platform = "avrdude-linux_i686" ; }
2019-01-01 15:47:54 -08:00
2019-01-02 15:50:05 -08:00
var executableName = _ _dirname + "/bin/" + platform + "/avrdude" ;
executableName = executableName . replace ( 'app.asar' , '' ) ; //This is important for allowing the binary to be found once the app is packaed into an asar
2019-01-01 15:47:54 -08:00
var configName = executableName + ".conf" ;
2019-01-01 19:47:18 -08:00
if ( process . platform == "win32" ) { executableName = executableName + '.exe' ; } //This must come after the configName line above
2019-01-01 16:31:28 -08:00
2019-01-01 15:47:54 -08:00
var hexFile = 'flash:w:' + args . firmwareFile + ':i' ;
var execArgs = [ '-v' , '-patmega2560' , '-C' , configName , '-cwiring' , '-b 115200' , '-P' , args . port , '-D' , '-U' , hexFile ] ;
2019-01-02 15:50:05 -08:00
console . log ( executableName ) ;
//const child = spawn(executableName, execArgs);
const child = execFile ( executableName , execArgs ) ;
2019-01-01 15:47:54 -08:00
child . stdout . on ( 'data' , ( data ) => {
2019-01-04 04:10:03 -08:00
console . log ( ` avrdude stdout: \n ${ data } ` ) ;
2019-01-01 15:47:54 -08:00
} ) ;
child . stderr . on ( 'data' , ( data ) => {
console . log ( ` avrdude stderr: ${ data } ` ) ;
2019-01-02 18:44:21 -08:00
avrdudeErr = avrdudeErr + data ;
2019-01-04 04:10:03 -08:00
//Check if avrdude has started the actual burn yet, and if so, track the '#' characters that it prints. Each '#' represents 1% of the total burn process (50 for write and 50 for read)
if ( burnStarted == true )
{
if ( data == "#" ) { burnPercent += 1 ; }
e . sender . send ( "upload percent" , burnPercent ) ;
}
else
{
//This is a hack, but basically watch the output from avrdude for the term 'Writing | ', everything after that is the #s indicating 1% of burn.
if ( avrdudeErr . substr ( avrdudeErr . length - 10 ) == "Writing | " )
{
burnStarted = true ;
}
}
2019-01-01 15:47:54 -08:00
} ) ;
child . on ( 'error' , ( err ) => {
console . log ( 'Failed to start subprocess.' ) ;
2019-01-02 15:50:05 -08:00
console . log ( err ) ;
2019-01-04 04:19:17 -08:00
avrdudeIsRunning = false ;
2019-01-01 15:47:54 -08:00
} ) ;
child . on ( 'close' , ( code ) => {
2019-01-04 04:19:17 -08:00
avrdudeIsRunning = false ;
2019-01-01 21:18:31 -08:00
if ( code !== 0 )
{
console . log ( ` avrdude process exited with code ${ code } ` ) ;
2019-01-02 18:44:21 -08:00
e . sender . send ( "upload error" , avrdudeErr )
avrdudeErr = "" ;
2019-01-01 21:18:31 -08:00
}
else
{
e . sender . send ( "upload completed" , code )
2019-01-01 15:47:54 -08:00
}
} ) ;
} ) ;
2018-12-30 22:17:58 -08:00
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.