From e92e697cfa500778ad8038db8e49a62284d02543 Mon Sep 17 00:00:00 2001 From: Richard Unger Date: Mon, 26 Feb 2024 23:39:04 +0100 Subject: [PATCH] work on serialport and events --- src/backend/nanodevices.js | 83 ++++++++++++++++++++------------------ src/main.js | 53 ++++++++++++------------ src/preload.js | 6 ++- src/renderer.js | 5 ++- vite.main.config.mjs | 8 ++++ 5 files changed, 84 insertions(+), 71 deletions(-) diff --git a/src/backend/nanodevices.js b/src/backend/nanodevices.js index 655272f..79fcc3e 100644 --- a/src/backend/nanodevices.js +++ b/src/backend/nanodevices.js @@ -1,45 +1,47 @@ import { SerialPort } from 'serialport'; +import { EventEmitter } from 'events'; - -const NANO_PRODUCT_ID = '7523'; -const NANO_VENDOR_ID = '1a86'; +// JTAG interface, TODO: change me! +const NANO_PRODUCT_ID = '1001'; +const NANO_VENDOR_ID = '303a'; const NANO_BAUD_RATE = 115200; -const nanodevices = { - - all_nano_devices: {}, - connected_nano_devices: {}, +class NanoDevices extends EventEmitter { + all_nano_devices = {}; + connected_nano_devices = {}; _list() { - let p = new Promise(); - SerialPort.list().then((ports, err) => { - if (err) { - p.reject(err); // TODO format for errors? - } - else { - console.log('ports', ports) - let found_nano_devices = [] - for (let port of ports) { - if (port.productId === NANO_PRODUCT_ID && port.vendorId === NANO_VENDOR_ID) { - found_nano_devices.push(port.serialNumber); - if (this.all_nano_devices[port.serialNumber] === undefined) { - this.all_nano_devices[port.serialNumber] = port; - this.emit('nanodevices:device-attached', { id: port.serialNumber }); + let p = new Promise((resolve, reject) => { + SerialPort.list().then((ports, err) => { + if (err) { + reject(err); // TODO format for errors? + } + else { + let found_nano_devices = [] + for (let port of ports) { + if (port.productId === NANO_PRODUCT_ID && port.vendorId === NANO_VENDOR_ID) { + found_nano_devices.push(port.serialNumber); + if (this.all_nano_devices[port.serialNumber] === undefined) { + this.all_nano_devices[port.serialNumber] = port; + this.emit('nanodevices:device-attached', port.serialNumber); + console.log('attached', port.serialNumber); + } + } + } + resolve(found_nano_devices); + for (let serialNumber in this.all_nano_devices) { + if (found_nano_devices.indexOf(serialNumber) === -1) { + delete this.all_nano_devices[serialNumber]; + this.emit('nanodevices:device-detached', serialNumber); + console.log('detached', serialNumber); } } } - p.resolve(found_nano_devices); - for (let serialNumber in this.all_nano_devices) { - if (found_nano_devices.indexOf(serialNumber) === -1) { - delete this.all_nano_devices[serialNumber]; - this.emit('nanodevices:device-detached', { id: serialNumber }); - } - } - } - }) + }); + }); return p; - }, + }; _handle_data(connected_port, data) { @@ -51,7 +53,7 @@ const nanodevices = { } connected_port.data = lines[lines.length - 1]; } - }, + }; list_devices() { @@ -60,8 +62,9 @@ const nanodevices = { if (value.serialNumber) result.push(key); } + console.log('list_devices', result); return result; - }, + }; async send(deviceid, jsonstr) { @@ -73,7 +76,7 @@ const nanodevices = { connected_port.port.write(jsonstr+'\n'); return Promise.resolve(); } - }, + }; async connect(deviceid) { @@ -86,19 +89,19 @@ const nanodevices = { let port = new SerialPort(nano_device.path, { baudRate: NANO_BAUD_RATE, autoOpen: false }); port.on('error', (err) => { // forward error to FE - this.emit('nanodevices:error', { id: nano_device.serialNumber }, err); + this.emit('nanodevices:error', nano_device.serialNumber, err); }); port.on('close', (err) => { if (err && err.disconnected) { // forward close to FE - this.emit('nanodevices:disconnected', { id: nano_device.serialNumber }); + this.emit('nanodevices:disconnected', nano_device.serialNumber); } delete this.connected_nano_devices[nano_device.serialNumber]; }); port.on('open', () => { p.resolve(nano_device.serialNumber); this.connected_nano_devices[nano_device.serialNumber] = { port: port, data: '' }; - this.emit('nanodevices:connected', { id: nano_device.serialNumber }); + this.emit('nanodevices:connected', nano_device.serialNumber); }); port.on('data', (data) => { let connected_port = this.connected_nano_devices[nano_device.serialNumber]; @@ -111,7 +114,7 @@ const nanodevices = { }); } return p; - }, + }; disconnect(deviceid) { @@ -130,8 +133,10 @@ const nanodevices = { } } return p; - } + }; }; +const nanodevices = new NanoDevices(); + export default nanodevices; diff --git a/src/main.js b/src/main.js index dbb3994..103731f 100644 --- a/src/main.js +++ b/src/main.js @@ -128,7 +128,7 @@ const createLoadingWindow = (mainWindow) => { // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.whenReady().then(() => { - ipcMain.handle('nanodevices:list_devices', nanodevices.list_devices) + ipcMain.handle('nanodevices:list_devices', ()=>nanodevices.list_devices()) ipcMain.handle('nanodevices:connect', nanodevices.connect) ipcMain.handle('nanodevices:disconnect', nanodevices.disconnect) ipcMain.handle('nanodevices:send', nanodevices.send) @@ -146,33 +146,29 @@ app.whenReady().then(() => { ipcMain.on('electron:openExternal', (_event, url) => shell.openExternal(url)) ipcMain.on('electron:openDevTools', () => mainWindow.webContents.toggleDevTools()) ipcMain.on('electron:reload', () => mainWindow.webContents.reloadIgnoringCache()) - // nanodevices.on('nanodevices:device-attached', (evt, device) => { // TODO cumbersome, is there a shorthand line nanodevice-* ? - // console.log('Attached device', device) - // mainWindow.webContents.send('nanodevices:device-attached', device) - // }) - // nanodevices.on('nanodevices:device-detached', (device) => { - // console.log('Detached device', device) - // mainWindow.webContents.send('nanodevices:device-detached', device) - // }) - // nanodevices.on('nanodevices:connected', (device) => { - // console.log('Connected device', device) - // mainWindow.webContents.send('nanodevices:connected', device) - // }) - // nanodevices.on('nanodevices:disconnected', (device) => { - // console.log('Disconnected device', device) - // mainWindow.webContents.send('nanodevices:disconnected', device) - // }) - // nanodevices.on('nanodevices:error', (device, error) => { - // console.log('Error on device', device, error) - // mainWindow.webContents.send('nanodevices:error', device, error) - // }) - // nanodevices.on('nanodevices:update', (deviceid, jsonstr) => { - // console.log('Nano update', jsonstr) - // mainWindow.webContents.send('nanodevices:update', deviceid, jsonstr) - // }) - nanodevices.on('nanodevices:event', (eventid, deviceid, ...data) => { - console.log('Nano event', eventid, deviceid, data) - mainWindow.webContents.send('nanodevices:event', eventid, deviceid, ...data) + nanodevices.on('nanodevices:device-attached', (deviceid, ...data) => { + console.log('Attached event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'device-attached', deviceid, ...data) + }) + nanodevices.on('nanodevices:device-detached', (deviceid, ...data) => { + console.log('Detached event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'device-detached', deviceid, ...data) + }) + nanodevices.on('nanodevices:device-error', (deviceid, ...data) => { + console.log('Error event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'device-error', deviceid, ...data) + }) + nanodevices.on('nanodevices:connected', (deviceid, ...data) => { + console.log('Connected event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'connected', deviceid, ...data) + }) + nanodevices.on('nanodevices:disconnected', (deviceid, ...data) => { + console.log('Disconnected event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'disconnected', deviceid, ...data) + }) + nanodevices.on('nanodevices:update', (deviceid, ...data) => { + console.log('Update event', deviceid, data) + mainWindow.webContents.send('nanodevices:event', 'update', deviceid, ...data) }) const menu = new Menu() for (const menuItem of Object.values(appMenu)) { @@ -204,6 +200,7 @@ app.whenReady().then(() => { Menu.setApplicationMenu(menu) //mainWindow.webContents.openDevTools() + setInterval(()=>nanodevices._list(), 1000) }) // Quit when all windows are closed, except on macOS. There, it's common diff --git a/src/preload.js b/src/preload.js index 2f76f0e..63aecd8 100644 --- a/src/preload.js +++ b/src/preload.js @@ -14,8 +14,10 @@ contextBridge.exposeInMainWorld('nanodevices', { disconnect(deviceid) { ipcRenderer.invoke('nanodevices:disconnect', deviceid); }, - on(eventid_filter, callback) { + on_event(eventid_filter, callback) { + console.log("attaching filter for ", eventid_filter); ipcRenderer.on('nanodevices:event', (_event, eventid, deviceid, ...data) => { + console.log("Event in ipcRenderer ", eventid, deviceid, data); if (eventid_filter=="*" || eventid_filter==eventid) { callback(eventid, deviceid, ...data); } @@ -38,4 +40,4 @@ contextBridge.exposeInMainWorld('electron', { }), openDevTools: () => ipcRenderer.send('electron:openDevTools'), reload: () => ipcRenderer.send('electron:reload'), -}); \ No newline at end of file +}); diff --git a/src/renderer.js b/src/renderer.js index 0082be3..ee4581d 100644 --- a/src/renderer.js +++ b/src/renderer.js @@ -53,6 +53,7 @@ app.config.globalProperties.window = window app.mount('#app') -window.nanodevices.on('*', (eventid, deviceid, ...data) => { - console.log(eventid, deviceid, data) +window.nanodevices.on_event("*", (eventid, deviceid, ...data) => { + console.log("Event on window ", eventid, deviceid, data) }); +window.nanodevices.list_devices(); \ No newline at end of file diff --git a/vite.main.config.mjs b/vite.main.config.mjs index faf0188..0aa939a 100644 --- a/vite.main.config.mjs +++ b/vite.main.config.mjs @@ -1,8 +1,10 @@ import { defineConfig } from 'vite' import eslint from 'vite-plugin-eslint' +import { builtinModules } from "module"; // https://vitejs.dev/config export default defineConfig({ + mode: 'development', resolve: { // Some libs that can run in both Web and Node.js, such as `axios`, we need to tell Vite to build them in Node.js. browserField: false, @@ -15,4 +17,10 @@ export default defineConfig({ failOnError: false, }), ], + build: { + minify: false, //process.env.MODE !== "development", + rollupOptions: { + external: ["electron", "serialport", ...builtinModules] + } + }, })