Hello Big Brain Internet People,
Problem:
I'm trying to build an app for my raspberry pi but I seem to be having a problem with my serialports. I can build and run the program on my host machine fine but when I create an appimage using Electron-Builder my target device seems to have a problem using the serialport module. I assume it has something to do with raspberry pi using an ARM processor and my host desktop is using 64-bit, but I'm not sure how to solve the problem.
This is my first project with nodejs/electron/html/js so any help would be greatly appreciated!
Host System:
Ubuntu 19.10
Arch: 64-bit
Node: v10.15.2
Target System:
Raspberry Pi 4
Raspbian v10
Arch: Armv7l
Node: v12.15.1 - armv7 version
Error:
/tmp/.mount_sec-trTc9j6w/resources/app.asar/node_modules/bindings/bindings.js:121 Uncaught Error: /tmp/.org.chromium.Chromium.PmaAji: wrong ELF class: ELFCLASS64
at process.func [as dlopen] (electron/js2c/asar.js:138)
at Object.Module._extensions..node (internal/modules/cjs/loader.js:881)
at Object.func [as .node] (electron/js2c/asar.js:147)
at Module.load (internal/modules/cjs/loader.js:701)
at tryModuleLoad (internal/modules/cjs/loader.js:633)
at Function.Module._load (internal/modules/cjs/loader.js:625)
at Module.require (internal/modules/cjs/loader.js:739)
at require (internal/modules/cjs/helpers.js:14)
at bindings (/tmp/.mount_sec-trTc9j6w/resources/app.asar/node_modules/bindings/bindings.js:112)
at Object.<anonymous> (/tmp/.mount_sec-trTc9j6w/resources/app.asar/node_modules/#serialport/bindings/lib/linux.js:2)
package.json
{
"name": "sec-transmitter",
"version": "0.1.0",
"description": "",
"main": "main.js",
"dependencies": {
"modbus-serial": "^7.7.4",
"serialport": "^7.1.5"
},
"build": {
"appId": "sec.com",
"linux": {
"category": "Network",
"target": {
"target": "AppImage",
"arch": "armv7l"
}
}
},
"devDependencies": {
"electron": "^5.0.5",
"electron-builder": "^22.2.0",
"electron-rebuild": "^1.8.8"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "electron .",
"install": "electron-rebuild",
"dist": "electron-builder",
"postinstall": "electron-builder install-app-deps"
},
"keywords": [],
"author": "",
"license": "ISC"
}
main.js
const { app, BrowserWindow} = require('electron');
const path = require('path');
function createWindow() {
//create the browser window
let win = new BrowserWindow({
width: 1024,
height: 600,
center: true,
fullscreen: true,
webPreferences: {
nodeIntegration: true
}
})
//and load the index html of the app
win.loadFile('./source/index.html')
win.webContents.openDevTools();
}
app.on('ready', createWindow)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="../assets/css/main.css">
<script src="./index.js"></script>
</head>
<body>
<div class="inner">
<img class="home_button" src="../assets/images/home.png" alt="Home Button">
<div class="Progressbar">
<h1>0</h1>
<progress value="10" max="100" id="pgb1"></progress>
</div>
</div>
<!--<h2>100 </h2>-->
<!-- <h2>NO3</h2>*/-->
`
</div>
<div class="Progressbar">
<h1>0</h1>
<progress value="32" max="100" id="pgb2"></progress>
</div>
<div class="Progressbar">
<h1>0</h1>
<progress value="56" max="100"name="pgb3"></progress>
</div>
<div class="Progressbar">
<h1>0</h1>
<progress value="80" max="100"name="pgb4"></progress>
</div>
<div class="Progressbar">
<h1>0</h1>
<progress value="100" max="100"name="pgb5"></progress>
</div>
</div>
<div class="Ping">
<button id="pingBtn">Ping Device</button>
<button id="closeBtn" onclick="quitApplication()">Exit</button>
</div>
<!--<script src="./modbus_headers.js"></script>
<script src="./modbusrtu_commands.js"></script> -->
<script src="./bgloop.js"></script>
</body>
</html>
bgloop.js
const ModbusRTU = require('../node_modules/modbus-serial');
//create empty modbus client
const client = new ModbusRTU(
);
//open connection to serial port
client.connectRTUBuffered("/dev/ttyUSB0",
{
baudRate: 9600,
dataBits: 8,
parity: 'none',
stopBits: 2,
autoOpen: false,
});
//set timeout, if slave did not reply back
client.setTimeout(500);
//List of ID's
const IDList = [2];
const getPingDevices = async (sensors) => {
try{
//get response from all sensors
for(let sensor of sensors ) {
//output response to console
console.log(await getPingDevice(sensor));
//wait 100 ms before pinging another sensor
await sleep(100);
}
}catch(e){
//if error, handle them here (it should not)
console.log(e);
}finally{
//close ports
//client.close();
// after all the data from the sensors repear again
setImmediate(() => {
getPingDevices(IDList)
})
}
}
const getPingDevice = async (device_id) => {
try{
//set ID of slave
await client.setID(device_id);
//read the ping register at address 3000
let val = await client.readHoldingRegisters(3001,1)
client.close();
//return the value
return val.data[0];
}catch(e){
//if error return -1
return -1
}
}
const sleep = (ms) => new Promise(resolve => setTimeout(resolve,ms));
//start running
getPingDevices(IDList);
Related
This question already has answers here:
Unable to use Node.js APIs in renderer process
(2 answers)
Closed 1 year ago.
I'm new to Electron, and I've really been struggling with getting it to work. I'm experiencing behavior I cannot explain, so here's a sum:
I cannot get the communication between Electron and the html to work
"Uncaught ReferenceError: require is not defined" inside the website, even though I have nodeIntegration:true
File Tree:
./
index.html
index.js
package-lock.json
package.json
node_modules/
index.js:
const electron = require("electron");
const Ffmpeg = require("fluent-ffmpeg");
const CmdExec = require('child_process');
const {
app,
BrowserWindow,
ipcMain
} = electron;
function createWindow() {
//If I put the main window ini into here, and then call app.on("ready", createWindow()); app says
//"Cant create window before ready", even though I just moved the funcion from inside ready to here..
}
app.on('ready', () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
mainWindow.loadURL(`${__dirname}/index.html`);
});
ipcMain.on("video:submit", (event, path) =>{
CmdExec.exec("echo hello", (value)=>{console.log(value)});
});
html:
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="">
</head>
<body>
<h1>WELCOME!</h1>
<script src="" async defer></script>
<form action="">
<div>
<br>
<label for=""></label>
<input type="file" accept="video/*" name="" id="">
</div>
<button type="submit">get info</button>
</form>
<script>
const electron = require("electron");
electron.send('perform-action', args);
document.querySelector("form").addEventListener("submit", (event) => {
event.preventDefault();
const {path} = document.querySelector("input").files[0];
window.api.send("video:submit", path);
});
//Tried multiple methos Ive found on stackoverflow,, dont think I implemented them right
//though
</script>
</body>
</html>
package.json:
{
"name": "media_encoder",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"electron": "electron ."
},
"author": "",
"license": "ISC",
"dependencies": {
"electron": "^12.0.0"
}
}
Electron 12 is now defaulting contextIsolation to true, which disables Node (here are the release notes; and here's the PR).
Here's a discussion of this change. nodeIntegration for what it's worth is going to be removed in a future Electron version.
The easiest way to fix this is to simply disable context isolation:
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
That being said, you might want to consider keeping contextIsolation enabled for security reasons. See this document explaining why this feature bolsters the security of your application.
I do not get the desired output when running the following electron app i.e alert box containing pwd as output. However, the commented line inside index.html seems to work fine. The developer console of the chromium window says "Uncaught ReferenceError: __dirname is not defined at HTMLButtonElement.<anonymous>". This snippet is taken verbatim(except the commented line) from the book "Electron in action" by Steve Kinney 2019 edition.
any suggestions?
package.json is as follows
{
"name": "bookmarker",
"version": "1.0.0",
"description": "electron app",
"main": "./app/main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Wasim Aftab",
"license": "ISC",
"dependencies": {
"electron": "^9.0.0"
}
}
main.js is as follows
const {app, BrowserWindow} = require('electron');
let mainWindow = null;
app.on ('ready', () => {
console.log('Hello, from electron');
mainWindow = new BrowserWindow();
mainWindow.webContents.loadFile(__dirname + '/index.html');
});
index.html is as follows
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="
default-src 'self';
script-src 'self' 'unsafe-inline';
connect-src *">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Bookmarker</title>
</head>
<body>
<h1>Hello from Electron</h1>
<p>
<button class="alert">Current Directory</button>
</p>
</body>
<script>
const button = document.querySelector('.alert');
button.addEventListener('click', () => {
alert(__dirname);
// alert(window.location.pathname.replace(/[^\\\/]*$/, ''));
});
</script>
</html>
__dirname is a nodejs concept, it does not exist in the browser.
One way to resolve the issue is to set nodeIntegration to true:
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
Another way would be to use a preload script (nodeIntegration is always enabled for preload scripts):
mainWindow = new BrowserWindow({
webPreferences: {
preload: (__dirname + "/preload.js")
}
});
And then in the preload.js file:
window.__dirname = __dirname
For electron v16.0.4, addition of contextIsolation: false also required
$ npx electron --version
v16.0.4
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
// enableRemoteModule: true,
},
});
I have a very simple Electron app, using version 5.0.1.
Here is my index.html file:
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Webgl</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="./initialization.js"></script>
<link rel="stylesheet" type="text/css" href="application.css">
</head>
<body>
<script>
initialization();
</script>
</html>
Then my main.js file:
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')
let win
function createWindow () {
// Create the browser window.
win = new BrowserWindow({ width: 1280,
height: 720,
nodeIntegration: true,
resizable: false,
maximizable: false })
// and load the index.html of the app.
win.loadFile('index.html')
// Open the DevTools.
win.webContents.openDevTools()
// 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
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
my package.json file:
{
"name": "estimation",
"version": "1.0.0",
"description": "estimation app",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^5.0.1"
}
}
Then my inittialization.js file that contains the initialization() method and const fs = require('fs');
const fs = require('fs');
function initialization(){
}
Now I have asked the same question in multiple places, I have tried multiple solutions, nothing works. I am wondering if this is an Electron bug at this stage.
The error I can't get rid off and I keep getting whatever I do is this Uncaught ReferenceError: require is not defined
I simply want to use require in another JS file. Why is node.js or electron not picking this up ?
Place the nodeIntegration inside webPreferences attribute
{ width: 1280,
height: 720,
webPreferences : { nodeIntegration: true },
resizable: false,
maximizable: false
}
I wanted to build trading apps using electron JS and using the TradingView library but I got stuck on how to implement it. I also created a new blank project to implement it, but still result.
Is there anyone has ever implement TradingView to electron and could give me solution to this?
Blank app result
Error in console
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://demo_chart.tradingview.com/charting_library/charting_library.min.js"></script>
<script type="text/javascript" src="https://demo_chart.tradingview.com/datafeeds/udf/dist/polyfills.js"></script>
<script type="text/javascript" src="https://demo_chart.tradingview.com/datafeeds/udf/dist/bundle.js"></script>
<script type="text/javascript">
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
TradingView.onready(function()
{
var widget = window.tvWidget = new TradingView.widget({
// debug: true, // uncomment this line to see Library errors and warnings in the console
fullscreen: true,
symbol: 'AAPL',
interval: 'D',
container_id: "tv_chart_container",
// BEWARE: no trailing slash is expected in feed URL
datafeed: new Datafeeds.UDFCompatibleDatafeed("https://demo_feed.tradingview.com"),
library_path: "charting_library/",
locale: getParameterByName('lang') || "en",
disabled_features: ["use_localstorage_for_settings"],
enabled_features: ["study_templates"],
charts_storage_url: 'http://saveload.tradingview.com',
charts_storage_api_version: "1.1",
client_id: 'tradingview.com',
user_id: 'public_user_id',
theme: getParameterByName('theme'),
});
});
</script>
</head>
<body style="margin:0px;">
<div id="tv_chart_container"></div>
</body>
</html>
Never used electron so using this opportunity to try it out myself. This is the steps I took.
Look at the documentation https://electronjs.org/docs/tutorial/first-app
1) created a folder called electron-test
2) run command npm init in that folder
3) modify package.json to be this
{
"name": "electron-test",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": "",
"license": "ISC",
"dependencies": {}
}
4) create main.js
const { app, BrowserWindow } = require("electron");
function createWindow() {
// Create the browser window.
win = new BrowserWindow({ width: 800, height: 600 });
// and load the index.html of the app.
win.loadFile("index.html");
}
app.on("ready", createWindow);
5) create index.html
6) run command npm install electron
7) run command npm start
This is the result
Is there anyone has ever implement TradingView to electron and could give me solution to this?
Well I don't have solution to the error, but I have found my way out to build an tradingView+ElectronJs app.
In short, you can start with TradingView Charting Library Integration Examples, from which you can choose the kind of integration template to start with(I just use react-javascript to start my app).And I just take this template for example.
After follow How to start to configure the app properly. You should first install election to your app(which means run npm install --save electron in the directory root), then add the main.js to your directory root, and configure your package.json and main.js properly. Blow is my package.json and main.js code.
package.json
{
"name": "knownsec-fed",
"version": "0.1.0",
"private": true,
"main": "main.js", // 配置启动文件
"homepage":".", //
"dependencies": {
"electron": "^1.7.10",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "1.1.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject",
"electron-start": "electron ." // start electron app
}
}
main.js
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')
let mainWindow
function createWindow () {
mainWindow = new BrowserWindow({width: 800, height: 600})
/**
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
*/
mainWindow.loadURL('http://localhost:3000/');
// mainWindow.webContents.openDevTools()
mainWindow.on('closed', function () {
mainWindow = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})
to start the electron app, first run npm start to start react then run npm run electron-start to start electron app and then all thing done.
When you open Object with widget, your widget trying to find static folder from wrong path. Just connect library in widget option like this:
I'm working on an Electron-based application, and I don't have much experience with it or JavaScript or Node.js. Currently, I just want to open a window dialoge by a click on a button. But when i click the button nothing happens.
This is my package.json:
{
"name": "Routingtable_Splitter",
"version": "1.0.0",
"description": "...",
"main": "main.js",
"scripts": {
"start": "electron .",
"pack": "build --dir",
"dist": "build",
"package-win": "electron-packager . Splitter --overwrite --asar=true --platform=win32 --arch=ia32"
},
"build": {
"win": {
"target": "squirrel",
"icon": "build/icon.ico"
}
},
"author": "Robert Malleschitz",
"license": "ISC",
"devDependencies": {
"dialog": "^0.3.1",
"document": "^0.4.7",
"electron": "^2.0.4",
"electron-builder": "^20.19.1",
"electron-packager": "^12.1.0",
"electron-winstaller": "^2.6.4",
"fs": "0.0.1-security",
"remote": "^0.2.6"
},
"dependencies": {}
}
this is my HTML code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Tool</title>
</head>
<body>
<h1>Routingtable Splitter</h1>
<main>
<div>
<div style="text-align:right;">
<input type="text" placeholder="Bitte Routingtabelle laden" style="width: 260px" id="actual-file"/>
<input type="submit" value="Routingtabelle laden" id="load-file"/>
<br><br>
<textarea id="editor" style="width: 400px; height: 300px;"></textarea><br />
<input type="button" id="splitTable" value="Split" />
</div>
</div>
</main>
</body>
<script src="renderer.js"></script>
</html>
this is my main.js:
const {app, BrowserWindow} = require('electron')
const {Menu} = require('electron')
const {dialog} = require('electron')
const {remote} = require('electron')
const {document} = require('electron')
const {ipcMain} = require('electron')
var path = require('path')
var electronInstaller = require('electron-winstaller')
let win = null;
function createWindow () {
win = new BrowserWindow({
width: 1200,
height: 1000,
})
win.loadFile('index.html')
}
const menuTemplate = [
{
label: 'Datei',
submenu: [
{
label: 'Lade', click: () => {getRoutingTable();}
},
{
label: 'Beenden', click: () => {app.quit();}
}
]
}
];
function getRoutingTable(){
dialog.showOpenDialog(
{
defaultPath: 'c./',
filters: [
{ name: 'Text Files', extensions: ['txt'] }
],
properties:['openFile']
})
}
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
app.on('ready', createWindow)
{
console.log('app')
}
ipcMain.on('ldFileBtn', function (event, arg) {
console.log('ipcMain');
getRoutingTable();
event.sender.send("btnclick-task-finished", "yes");
});
This is my renderer.js:
const ipcRen = require('electron').ipcRenderer;
const ldFileBtn = document.getElementById('load-file');
ldFileBtn.addEventlistener('click', function() {
console.log('btn_click')
var arg = 'secondparam';
ipcRen.send('ldFileBtn', arg);
});
Why won't the button work? I hope someone can help me. Thanks in advance.