work on serialport and events
This commit is contained in:
@@ -1,45 +1,47 @@
|
|||||||
import { SerialPort } from 'serialport';
|
import { SerialPort } from 'serialport';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
// JTAG interface, TODO: change me!
|
||||||
const NANO_PRODUCT_ID = '7523';
|
const NANO_PRODUCT_ID = '1001';
|
||||||
const NANO_VENDOR_ID = '1a86';
|
const NANO_VENDOR_ID = '303a';
|
||||||
const NANO_BAUD_RATE = 115200;
|
const NANO_BAUD_RATE = 115200;
|
||||||
|
|
||||||
|
|
||||||
const nanodevices = {
|
class NanoDevices extends EventEmitter {
|
||||||
|
all_nano_devices = {};
|
||||||
all_nano_devices: {},
|
connected_nano_devices = {};
|
||||||
connected_nano_devices: {},
|
|
||||||
|
|
||||||
_list() {
|
_list() {
|
||||||
let p = new Promise();
|
let p = new Promise((resolve, reject) => {
|
||||||
SerialPort.list().then((ports, err) => {
|
SerialPort.list().then((ports, err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
p.reject(err); // TODO format for errors?
|
reject(err); // TODO format for errors?
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log('ports', ports)
|
let found_nano_devices = []
|
||||||
let found_nano_devices = []
|
for (let port of ports) {
|
||||||
for (let port of ports) {
|
if (port.productId === NANO_PRODUCT_ID && port.vendorId === NANO_VENDOR_ID) {
|
||||||
if (port.productId === NANO_PRODUCT_ID && port.vendorId === NANO_VENDOR_ID) {
|
found_nano_devices.push(port.serialNumber);
|
||||||
found_nano_devices.push(port.serialNumber);
|
if (this.all_nano_devices[port.serialNumber] === undefined) {
|
||||||
if (this.all_nano_devices[port.serialNumber] === undefined) {
|
this.all_nano_devices[port.serialNumber] = port;
|
||||||
this.all_nano_devices[port.serialNumber] = port;
|
this.emit('nanodevices:device-attached', port.serialNumber);
|
||||||
this.emit('nanodevices:device-attached', { id: 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;
|
return p;
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
_handle_data(connected_port, data) {
|
_handle_data(connected_port, data) {
|
||||||
@@ -51,7 +53,7 @@ const nanodevices = {
|
|||||||
}
|
}
|
||||||
connected_port.data = lines[lines.length - 1];
|
connected_port.data = lines[lines.length - 1];
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
list_devices() {
|
list_devices() {
|
||||||
@@ -60,8 +62,9 @@ const nanodevices = {
|
|||||||
if (value.serialNumber)
|
if (value.serialNumber)
|
||||||
result.push(key);
|
result.push(key);
|
||||||
}
|
}
|
||||||
|
console.log('list_devices', result);
|
||||||
return result;
|
return result;
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
async send(deviceid, jsonstr) {
|
async send(deviceid, jsonstr) {
|
||||||
@@ -73,7 +76,7 @@ const nanodevices = {
|
|||||||
connected_port.port.write(jsonstr+'\n');
|
connected_port.port.write(jsonstr+'\n');
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
async connect(deviceid) {
|
async connect(deviceid) {
|
||||||
@@ -86,19 +89,19 @@ const nanodevices = {
|
|||||||
let port = new SerialPort(nano_device.path, { baudRate: NANO_BAUD_RATE, autoOpen: false });
|
let port = new SerialPort(nano_device.path, { baudRate: NANO_BAUD_RATE, autoOpen: false });
|
||||||
port.on('error', (err) => {
|
port.on('error', (err) => {
|
||||||
// forward error to FE
|
// 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) => {
|
port.on('close', (err) => {
|
||||||
if (err && err.disconnected) {
|
if (err && err.disconnected) {
|
||||||
// forward close to FE
|
// 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];
|
delete this.connected_nano_devices[nano_device.serialNumber];
|
||||||
});
|
});
|
||||||
port.on('open', () => {
|
port.on('open', () => {
|
||||||
p.resolve(nano_device.serialNumber);
|
p.resolve(nano_device.serialNumber);
|
||||||
this.connected_nano_devices[nano_device.serialNumber] = { port: port, data: '' };
|
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) => {
|
port.on('data', (data) => {
|
||||||
let connected_port = this.connected_nano_devices[nano_device.serialNumber];
|
let connected_port = this.connected_nano_devices[nano_device.serialNumber];
|
||||||
@@ -111,7 +114,7 @@ const nanodevices = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
},
|
};
|
||||||
|
|
||||||
|
|
||||||
disconnect(deviceid) {
|
disconnect(deviceid) {
|
||||||
@@ -130,8 +133,10 @@ const nanodevices = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const nanodevices = new NanoDevices();
|
||||||
|
|
||||||
export default nanodevices;
|
export default nanodevices;
|
||||||
|
|||||||
53
src/main.js
53
src/main.js
@@ -128,7 +128,7 @@ const createLoadingWindow = (mainWindow) => {
|
|||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
// Some APIs can only be used after this event occurs.
|
// Some APIs can only be used after this event occurs.
|
||||||
app.whenReady().then(() => {
|
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:connect', nanodevices.connect)
|
||||||
ipcMain.handle('nanodevices:disconnect', nanodevices.disconnect)
|
ipcMain.handle('nanodevices:disconnect', nanodevices.disconnect)
|
||||||
ipcMain.handle('nanodevices:send', nanodevices.send)
|
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:openExternal', (_event, url) => shell.openExternal(url))
|
||||||
ipcMain.on('electron:openDevTools', () => mainWindow.webContents.toggleDevTools())
|
ipcMain.on('electron:openDevTools', () => mainWindow.webContents.toggleDevTools())
|
||||||
ipcMain.on('electron:reload', () => mainWindow.webContents.reloadIgnoringCache())
|
ipcMain.on('electron:reload', () => mainWindow.webContents.reloadIgnoringCache())
|
||||||
// nanodevices.on('nanodevices:device-attached', (evt, device) => { // TODO cumbersome, is there a shorthand line nanodevice-* ?
|
nanodevices.on('nanodevices:device-attached', (deviceid, ...data) => {
|
||||||
// console.log('Attached device', device)
|
console.log('Attached event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:device-attached', device)
|
mainWindow.webContents.send('nanodevices:event', 'device-attached', deviceid, ...data)
|
||||||
// })
|
})
|
||||||
// nanodevices.on('nanodevices:device-detached', (device) => {
|
nanodevices.on('nanodevices:device-detached', (deviceid, ...data) => {
|
||||||
// console.log('Detached device', device)
|
console.log('Detached event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:device-detached', device)
|
mainWindow.webContents.send('nanodevices:event', 'device-detached', deviceid, ...data)
|
||||||
// })
|
})
|
||||||
// nanodevices.on('nanodevices:connected', (device) => {
|
nanodevices.on('nanodevices:device-error', (deviceid, ...data) => {
|
||||||
// console.log('Connected device', device)
|
console.log('Error event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:connected', device)
|
mainWindow.webContents.send('nanodevices:event', 'device-error', deviceid, ...data)
|
||||||
// })
|
})
|
||||||
// nanodevices.on('nanodevices:disconnected', (device) => {
|
nanodevices.on('nanodevices:connected', (deviceid, ...data) => {
|
||||||
// console.log('Disconnected device', device)
|
console.log('Connected event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:disconnected', device)
|
mainWindow.webContents.send('nanodevices:event', 'connected', deviceid, ...data)
|
||||||
// })
|
})
|
||||||
// nanodevices.on('nanodevices:error', (device, error) => {
|
nanodevices.on('nanodevices:disconnected', (deviceid, ...data) => {
|
||||||
// console.log('Error on device', device, error)
|
console.log('Disconnected event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:error', device, error)
|
mainWindow.webContents.send('nanodevices:event', 'disconnected', deviceid, ...data)
|
||||||
// })
|
})
|
||||||
// nanodevices.on('nanodevices:update', (deviceid, jsonstr) => {
|
nanodevices.on('nanodevices:update', (deviceid, ...data) => {
|
||||||
// console.log('Nano update', jsonstr)
|
console.log('Update event', deviceid, data)
|
||||||
// mainWindow.webContents.send('nanodevices:update', deviceid, jsonstr)
|
mainWindow.webContents.send('nanodevices:event', 'update', deviceid, ...data)
|
||||||
// })
|
|
||||||
nanodevices.on('nanodevices:event', (eventid, deviceid, ...data) => {
|
|
||||||
console.log('Nano event', eventid, deviceid, data)
|
|
||||||
mainWindow.webContents.send('nanodevices:event', eventid, deviceid, ...data)
|
|
||||||
})
|
})
|
||||||
const menu = new Menu()
|
const menu = new Menu()
|
||||||
for (const menuItem of Object.values(appMenu)) {
|
for (const menuItem of Object.values(appMenu)) {
|
||||||
@@ -204,6 +200,7 @@ app.whenReady().then(() => {
|
|||||||
|
|
||||||
Menu.setApplicationMenu(menu)
|
Menu.setApplicationMenu(menu)
|
||||||
//mainWindow.webContents.openDevTools()
|
//mainWindow.webContents.openDevTools()
|
||||||
|
setInterval(()=>nanodevices._list(), 1000)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Quit when all windows are closed, except on macOS. There, it's common
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ contextBridge.exposeInMainWorld('nanodevices', {
|
|||||||
disconnect(deviceid) {
|
disconnect(deviceid) {
|
||||||
ipcRenderer.invoke('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) => {
|
ipcRenderer.on('nanodevices:event', (_event, eventid, deviceid, ...data) => {
|
||||||
|
console.log("Event in ipcRenderer ", eventid, deviceid, data);
|
||||||
if (eventid_filter=="*" || eventid_filter==eventid) {
|
if (eventid_filter=="*" || eventid_filter==eventid) {
|
||||||
callback(eventid, deviceid, ...data);
|
callback(eventid, deviceid, ...data);
|
||||||
}
|
}
|
||||||
@@ -38,4 +40,4 @@ contextBridge.exposeInMainWorld('electron', {
|
|||||||
}),
|
}),
|
||||||
openDevTools: () => ipcRenderer.send('electron:openDevTools'),
|
openDevTools: () => ipcRenderer.send('electron:openDevTools'),
|
||||||
reload: () => ipcRenderer.send('electron:reload'),
|
reload: () => ipcRenderer.send('electron:reload'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ app.config.globalProperties.window = window
|
|||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
||||||
|
|
||||||
window.nanodevices.on('*', (eventid, deviceid, ...data) => {
|
window.nanodevices.on_event("*", (eventid, deviceid, ...data) => {
|
||||||
console.log(eventid, deviceid, data)
|
console.log("Event on window ", eventid, deviceid, data)
|
||||||
});
|
});
|
||||||
|
window.nanodevices.list_devices();
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import eslint from 'vite-plugin-eslint'
|
import eslint from 'vite-plugin-eslint'
|
||||||
|
import { builtinModules } from "module";
|
||||||
|
|
||||||
// https://vitejs.dev/config
|
// https://vitejs.dev/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
mode: 'development',
|
||||||
resolve: {
|
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.
|
// 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,
|
browserField: false,
|
||||||
@@ -15,4 +17,10 @@ export default defineConfig({
|
|||||||
failOnError: false,
|
failOnError: false,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
build: {
|
||||||
|
minify: false, //process.env.MODE !== "development",
|
||||||
|
rollupOptions: {
|
||||||
|
external: ["electron", "serialport", ...builtinModules]
|
||||||
|
}
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user