@@ -2,7 +2,7 @@ import { app, shell, BrowserWindow, ipcMain, Menu } from 'electron'
22import { join } from 'path'
33import { electronApp , optimizer , is } from '@electron-toolkit/utils'
44import icon from '../../resources/icon.png?asset'
5- import { checkForUSBKeyboards , handleSelectDrive , selectKeyboard } from './selectKeyboard'
5+ import { checkForUSBKeyboards , handleSelectDrive , selectKeyboard } from './selectKeyboard'
66import { updateFirmware } from './kmkUpdater'
77import { handleKeymapSave , saveConfiguration } from './saveConfig'
88import { autoUpdater } from 'electron-updater'
@@ -125,7 +125,8 @@ const createWindow = async () => {
125125 ...( process . platform === 'linux' ? { icon } : { } ) ,
126126 webPreferences : {
127127 preload : join ( __dirname , '../preload/index.js' ) ,
128- sandbox : false
128+ sandbox : false ,
129+ experimentalFeatures : true
129130 }
130131 } )
131132
@@ -178,6 +179,22 @@ app.on('window-all-closed', () => {
178179 app . quit ( )
179180 }
180181} )
182+ app . on ( 'before-quit' , ( event ) => {
183+ // Prevent the default behavior of this event
184+ if ( debugPort !== undefined ) {
185+ event . preventDefault ( )
186+
187+ console . log ( 'Preparing to quit...' )
188+ debugPort . close ( ( ) => {
189+ console . log ( 'Port closed' )
190+ debugPort = undefined
191+ app . quit ( )
192+ } )
193+ } else {
194+ // Now allow the app to continue quitting
195+ app . quit ( )
196+ }
197+ } )
181198
182199// In this file you can include the rest of your app"s specific main process
183200// code. You can also put them in separate files and require them here.
@@ -193,6 +210,10 @@ ipcMain.handle('updateFirmware', () => updateFirmware())
193210ipcMain . on ( 'saveConfiguration' , ( _event , data ) => saveConfiguration ( data ) )
194211ipcMain . handle ( 'checkForUSBKeyboards' , ( _event , data ) => checkForUSBKeyboards ( data ) )
195212ipcMain . handle ( 'selectKeyboard' , ( _event , data ) => selectKeyboard ( data ) )
213+ ipcMain . handle ( 'serialPorts' , ( _event , data ) => checkSerialDevices ( ) )
214+ ipcMain . on ( 'serialSend' , ( _event , data ) => sendSerial ( data ) )
215+ ipcMain . handle ( 'serialConnect' , ( _event , data ) => serialConnect ( data ) )
216+ ipcMain . handle ( 'openExternal' , ( _event , data ) => openExternal ( data ) )
196217
197218autoUpdater . on ( 'update-available' , ( ) => {
198219 if ( mainWindow ) mainWindow . webContents . send ( 'update_available' )
@@ -246,7 +267,7 @@ const scanForKeyboards = async () => {
246267 circuitPythonPorts . map ( async ( a ) => await timeout ( getBoardInfo ( a ) , 2000 ) )
247268 ) ) as {
248269 status : 'fulfilled' | 'rejected'
249- value : { name : string ; id : string ; path : string }
270+ value : { name : string ; id : string ; path : string }
250271 } [ ]
251272 const filteredBoards : { name : string ; id : string ; path : string } [ ] = boards
252273 . filter ( ( a ) => a . value !== undefined )
@@ -435,3 +456,73 @@ const deselectKeyboard = () => {
435456 connectedKeyboardPort . close ( )
436457 }
437458}
459+
460+ const sendSerial = ( message ) => {
461+ console . log ( 'sending serial' , message )
462+ mainWindow ?. webContents . send ( 'serialData' , { message : `> sent: ${ message } \n` } )
463+ if ( message === 'ctrlc' ) {
464+ message = Buffer . from ( '\x03\x03' , 'utf8' )
465+ } else if ( message === 'ctrld' ) {
466+ message = Buffer . from ( '\x04' , 'utf8' )
467+ } else {
468+ const buffermessage = Buffer . from ( message + `\r\n` , 'utf8' )
469+ message = buffermessage
470+ }
471+ debugPort . write ( message , ( err ) => {
472+ if ( err ) {
473+ console . error ( 'error sending serial' , err )
474+ }
475+ } )
476+ }
477+
478+ const checkSerialDevices = async ( ) => {
479+ try {
480+ console . log ( 'checking serial devices' )
481+ const ports = await serialPort . SerialPort . list ( )
482+
483+ if ( ports . length === 0 ) {
484+ console . log ( 'No serial ports found' )
485+ return [ ]
486+ }
487+
488+ const returnPorts = ports . map ( ( port ) => {
489+ return {
490+ port : port . path ,
491+ manufacturer : port . manufacturer ,
492+ serialNumber : port . serialNumber ,
493+ // Add more attributes here if needed
494+ }
495+ } )
496+ console . log ( 'found serial ports' , returnPorts )
497+ return returnPorts
498+ } catch ( error ) {
499+ console . error ( 'Error fetching the list of serial ports:' , error )
500+ return [ ]
501+ }
502+ }
503+
504+ let debugPort : any = undefined
505+ const serialConnect = async ( port ) => {
506+ if ( debugPort !== undefined ) {
507+ debugPort . close ( ( ) => {
508+ console . log ( 'closed serial port' )
509+ debugPort = undefined
510+ } )
511+ }
512+ console . log ( 'connecting to serial port' , port )
513+ try {
514+ debugPort = new serialPort . SerialPort ( { path : port , baudRate, autoOpen : true } , ( e ) => { } )
515+ const parser = debugPort . pipe ( new ReadlineParser ( { delimiter : '\n' } ) )
516+ parser . on ( 'data' , ( data ) => {
517+ console . log ( 'got data from serial' , data )
518+ mainWindow ?. webContents . send ( 'serialData' , { message : data } )
519+ } )
520+ console . log ( 'connected to serial port and listening for messages' , port )
521+ } catch ( e ) {
522+ console . log ( 'error connecting to serial port' , e )
523+ }
524+ }
525+
526+ const openExternal = ( url ) => {
527+ shell . openExternal ( url )
528+ }
0 commit comments