Been trying to get Electron.js to talk to my Arduino.
char x = 'v';
void setup() {
// initialize serial:
Serial.begin(9600);
}
void loop() {
// print the string when a newline arrives:
Serial.print(x);
delay(1600);
}
I checked the IDE and it is reacting to the rendering code below:
var path = "/dev/ttyACM0";
const { SerialPort } = require('serialport')
const {DelimiterParser} = require('#serialport/parser-delimiter')
var ports = new SerialPort({path, baudRate: 9600});
const parser = ports.pipe(new DelimiterParser({ delimiter: '\n' }))
//ports.pipe(parser);
//parser.on('ready', () => console.log('the ready byte sequence has been received'))
data=parser.on('data', console.log) // all data after READY is received
// Read the data from the serial port
//parser.on("data", (ports) => console.log(ports));
// console.log('ports', ports);
document.getElementById('ports').innerHTML = data;
The output too the application is this: SerialRead [object Object] . It should be SerialRead v. Below is the index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Read from USB port</title>
<style> </style>
</head>
<body>
<h1>Read</h1>
<center>
SerialRead <span id="ports"></span>
<div id="error"></div>
<div id="ports"></div>
</center>
</body>
<script src="./__renderer.js"></script>
</html>
main.js
const { app, BrowserWindow } = require('electron')
app.commandLine.appendSwitch("disable-gpu");
const path = require('path')
const url = require('url')
// 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 mainWindow
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
backgroundColor: "#ccc",
webPreferences: {
nodeIntegration: true, // to allow require
contextIsolation: false, // allow use with Electron 12+
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'tindex.html'),
protocol: 'file:',
slashes: true
}))
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function() {
// 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.
mainWindow = 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', function() {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
app.quit()
})
app.on('activate', function() {
// On OS X 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 (mainWindow === null) {
createWindow()
}
})
// 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.
Electron and the Aruduino are reacting to each other, the the rendering is not working correctly. I would appreciate any ideas. Thank you!
serialport is a Node.js module. To be able to use a main process module in the renderer process, you need to know about the Process Model.
TL;DR; use contextIsolation and ipc to send messages between main and renderer. Keep in mind: just because you use contextIsolation, does not mean the code is safe. You need to use it properly. Don't expose powerful APIs without filtering.
Related
About 30% of the time my electron app does not execute the fs.readdir callback after I've reloaded the window that contains that script. When I open the application with electron ., the issue never occurs, it only ever occurs after I've reloaded the window.
I've tried adding a setTimeout of 5 seconds before executing fs.readdir, however this didn't change anything. Additionally, after the first time fs.readdir is run, all proceeding fs.readdir callbacks are never executed unless done immediately afterwards or if the window has never been reloaded before.
Anyone know a why this occurs and a solution?
mainWindow.js:
const fs = require('fs')
// read all files in "images" directory
function readDirectory(){
fs.readdir('images', (e, files) => {
// On error, show and return error
if(e) return console.error(e);
console.log(files)
});
}
readDirectory()
main.js:
const electron = require('electron')
const path = require('path')
const {app, BrowserWindow, Menu} = electron
process.env.NODE_ENV = 'development'
let mainWindow
let mainMenu
function createMainWindow(){
// Create mainWindow
mainWindow = new BrowserWindow({
icon:'icon.png',
webPreferences:{
nodeIntegration:true,
fullscreen: true
}
})
// Load html file
mainWindow.loadFile('mainWindow.html')
// Main menu
mainMenu = Menu.buildFromTemplate(mainMenuTemplate)
// Set main menu
Menu.setApplicationMenu(mainMenu)
// Garbage handling
mainWindow.on('close',()=>{
mainWindow = null
mainMenu = null // idk if necessary
})
if (process.env.NODE_ENV !== 'production'){
mainWindow.webContents.openDevTools()
}
}
app.on('ready',e=>{
createMainWindow()
})
const mainMenuTemplate = [
{
role:'reload',
accelerator:'cmdorctrl+r',
}
]
Also, sometimes the content is read but then it seems like it disappears. Vid: https://imgur.com/a/qZjwSBi
If you're using the fs module set:
app.allowRendererProcessReuse = false;
https://github.com/electron/electron/issues/22119
I'm using electron 2.0.7 and I want to prevent multiple instances of the app by using app.makeSingleInstance.
It works but when i'm trying to run another instance of the app I get this error: "A Javascript error is occurred in the main process" as a pop up.
This is the code in main.ts:
function checkSingleInstance() {
// to make singleton instance
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (win) {
if (win.isMinimized()) {
win.restore();
win.focus();
}
}
});
if (isSecondInstance) {
app.quit();
return;
}
}
checkSingleInstance();
This is the error:
Try replacing app.quit() with app.exit().
app.exit() does not emit events before quitting as opposed to app.quit() which does the proper cleanup.
It's hard to say exactly where the error is coming from and why, but this issue is documented here.
After completing the source code you posted, I can run it using Electron 2.0.7 just fine.
The error you're seeing probably stems from some other part of your code. Judging by the error message, check if you import a module by the name screen somewhere.
Here's your source code, completed to a MCVE:
const {app, BrowserWindow} = require('electron')
let win = null
console.log(`Node ${process.versions.node}, Chrome ${process.versions.chrome}, Electron ${process.versions.electron}`)
function checkSingleInstance() {
// to make singleton instance
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (win) {
if (win.isMinimized()) {
win.restore();
win.focus();
}
}
});
if (isSecondInstance) {
console.log("Exiting because another instance is running")
app.quit();
return;
}
}
checkSingleInstance();
app.on('ready', () => {
win = new BrowserWindow({width: 200, height: 200});
win.on('closed', () => win = null);
});
Im having issues in bypassing proxy. I’m new to both JavaScript and Electron.
I'm either facing this issue (pic below) or a blank white screen will be loaded.
My pacfile.pac :
function findProxyForURL(url, host) {
// If the hostname matches, send direct.
if (dnsDomainIs(host, “http://000.00.0.0:0000”) ||
shExpMatch(host, “(*.domain.com)”))
return “DIRECT”;
}
my index.js:
const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow
const path = require('path')
const url = require('url')
var fs = require('fs');
var pac = require('pac-resolver');
// 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 mainWindow
let ProxyFunc
let pacVariable
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
//proxy: "http://000.00.0.0:0000"
// /* src="https://domain.name.com/#/random/login" */
/*mainWindow.webContents.session.setProxy({proxyRules:"http://000.00.0.0:0000"}, function () {
mainWindow.loadURL('https://domain.name.com/#/random/login');
});*/
app.commandLine.appendSwitch('proxy-bypass-list', '*.google.com;*domain.name.com;');
pacVariable = new pacfile();
pacVariable.findProxyForURL("https://domain.name.com/#/random/login", "*domain.name.com");
//ProxyFunc = new FindProxyForURL("https://domain.name.com/#/random/login","domain.name.com");
mainWindow.webContents.session.setProxy({proxyRules:"http://000.00.0.0:0000",proxyBypassRules:"domain.name.com"}, function () {
mainWindow.loadURL(path.join('file://', __dirname, 'index.html'));
});
/*mainWindow.webContents.session.setProxy({proxyRules:"http://000.00.0.0:0000"}, function () {
mainWindow.loadURL('https://domain.name.com/#/random/login');
});*/
mainWindow.openDevTools({ mode: 'bottom' });
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// 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.
mainWindow = 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', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X 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 (mainWindow === null) {
createWindow()
}
})
// 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.
Replace pacVariable = new pacfile() with
var FindProxyForURL = pac(fs.readFileSync('pacfile.pac'));
FindProxyForURL('https://domain.name.com/#/random/login').then((res) => {
console.log(res);
});
refer the docs for API
FindProxyForURL is a promise, so you'll have to write the code that requires the response inside the .then.
I am working on an application using Node.JS, Electron. This application will run its own instance of MongoDB. The start up of Mongo is working using the following code:
child = childProcess.exec(`mongod --dbpath ${appConfig.dbConfigPath}`);
However, when the user exits the program, I want to stop mongo. I have tried the following, all taken from MongoDB Documentation
child = childProcess.exec('mongod --shutdown');
and
child = childProcess.exec(`kill -2 ${child.pid}`);
yet neither of these are shutting down the process.
This application is being developed to run on the windows platform.
For clarity, here is my app configuration file. The init() function is executed from within my main.js. The shutdown() is executed in the windowMain.on('close').
calibration.js
'use strict';
const childProcess = require('child_process');
const fileUtils = require('./lib/utils/fileUtils');
const appConfig = require('./config/appConfig');
let child;
class Calibration {
constructor() {}
init() {
createAppConfigDir();
createAppDataDir();
startMongo();
}
shutdown() {
shutdownMongo();
}
}
function createAppConfigDir() {
fileUtils.createDirSync(appConfig.appConfigDir);
}
function createAppDataDir() {
fileUtils.createDirSync(appConfig.dbConfigPath);
}
function startMongo() {
child = childProcess.exec(`mongod --dbpath ${appConfig.dbConfigPath}`);
console.log(child.pid);
}
function shutdownMongo() {
console.log('inside shutdownMongo');
//This is where I want to shutdown Mongo
}
module.exports = new Calibration();
main.js
'use strict'
const { app, BrowserWindow, crashReporter, ipcMain: ipc } = require('electron');
const path = require('path');
const appCalibration = require('../calibration');
appCalibration.init();
const appConfig = require('../config/appConfig');
let mainWindow = null;
ipc.on('set-title', (event, title) => {
mainWindow.setTitle(title || appconfig.name);
})
ipc.on('quit', () => {
app.quit();
})
// Quit when all windows are closed.
app.on('window-all-closed', function() {
if (process.platform != 'darwin') {
app.quit();
}
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
// Create the browser window.
mainWindow = new BrowserWindow({ center: true });
mainWindow.maximize();
mainWindow.setMinimumSize(770, 400);
mainWindow.loadURL(path.join(`file://${__dirname}`, '../ui/index.html'));
mainWindow.on('close', () => {
console.log('Inside quit')
appCalibration.shutdown();
app.quit();
});
mainWindow.on('closed', function() {
mainWindow = null;
});
});
Any assistance is greatly appreciated.
You can use Ipc to send orders through your js files.
In your main.js where you defined your electron, you can put this:
ipcMain.on("shutDownDatabase", function (event, content) {
// shutdown operations.
});
Then in some part of your application code, you can put a function like this:
function sendShutdownOrder (content){
var ipcRenderer = require("electron").ipcRenderer;
// the content can be a parameter or whatever you want that should be required for the operation.
ipcRenderer.send("shutDownDatabase", content);
}
Also I think you can use the events of Electron to shut down your db, this listens to the events of your mainWindow created when you start electron
mainWindow.on('closed', function () {
// here you command to shutdowm your data base.
mainWindow = null;
});
For more information about IPC you can see here and information about the events of your window here.
With Paulo Galdo Sandoval's suggestion, I was able to get this to work. However, I needed to get the PID for mongod from Windows Task manager. To do that I added the following function to the application configuration js file
function getTaskList() {
let pgm = 'mongod';
exec('tasklist', function(err, stdout, stderr) {
var lines = stdout.toString().split('\n');
var results = new Array();
lines.forEach(function(line) {
var parts = line.split('=');
parts.forEach(function(items) {
if (items.toString().indexOf(pgm) > -1) {
taskList.push(items.toString().replace(/\s+/g, '|').split('|')[1])
}
});
});
});
}
I also declared an array variable to place the located PID in. Then I updated my shutdown function
function shutdownMongo() {
var pgm = 'mongod';
console.log('inside shutdownMongo');
taskList.forEach(function(item) {
console.log('Killing process ' + item);
process.kill(item);
});
}
With this I am now able to start and stop Mongo as my application starts up and closes.
Thanks all
In Electron version 1.X, how can I emit an event from one BrowserWindow and consume it in another BrowserWindow?
I am using Electron version 1.2.1.
One way you could do this is using the ipcRenderer to communicate between BrowserWindow instances and the main process. For example, in the main process you could have something like the following: -
const electron = require('electron');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
let mainWindow, subWindow;
mainWindow = new BrowserWindow({
width: 800,
height: 600,
fullscreen: true
});
mainWindow.loadURL('file://' + __dirname + '/../index.html');
subWindow = new BrowserWindow(); // etc
electron.ipcMain
.on('myMainMessage', function (event, data) {
// data can be passed from browser window
subWindow.webContents.send('myPassedMessage', data);
});
Then, inside the first mainWindow instance you could throw together a message using the ipcRenderer like so: -
var electron = require('electron');
var ipc = electron.ipcRenderer;
ipc.send('myMainMessage', {
property: 'someValue'
});
And inside your other window instance you'd have some JavaScript to listen to the other trigger. Something like this: -
var electron = require('electron');
var ipc = electron.ipcRenderer;
ipc.on('myPassedMessage', function (event, data) {
console.log(data); // will be from the mainWindow instance
});
Consult the docs on the ipcRenderer section for more information.
Communication example from a child_window to its parent_window using webContents:
Inside parent_window:
const BrowserWindow = require('electron').remote.BrowserWindow;
var child_window = new BrowserWindow({ ... });
child_window.webContents.on("event", function(arg1, arg2){
console.log(arg1, arg2); // this will print inside parent_window devtools console
});
Inside child_window:
require('electron').remote.getCurrentWebContents().emit("event", "hello", "world");
The main advantage using this solution instead of the IPC one is that those routines are linked to the local context of child_window's webContents. So those routines are deleted if the child_window is closed and its BrowserWindow object is deleted.
You can also use the same system to communicate from parent_window to child_window.