I wrote an electron app that has to connect to a local server in order to work. Once the program starts, it tries to connect to the server using the Nodejs net library, if one second passes without it connecting to the server the program will try to connect again, once a connection to the server is established the program will continue as normal.
The issue I am having is when my client can't find, or connect, to the server on the network, I get a pop-up error message which I don't want to show.
The image below shows the error message I am receiving, I am using Ubuntu but I get the same message on windows:
And just for reference here is my relevant code:
main.js:
const express = require('express');
const ChatApp = express();
require('./backend/scripts/javascript/net_receiver.js');
require('./backend/scripts/javascript/websocket_receiver.js');
ChatApp.use(express.static('./frontend'));
ChatApp.listen(3003, function()
{
console.log('\nControl Panel Server Running on Port 3003');
});
const { app, BrowserWindow } = require("electron");
app.commandLine.appendSwitch('ignore-certificate-errors');
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = true
let mainWindow;
function createWindow()
{
mainWindow = new BrowserWindow(
{
icon: 'frontend/chat_app/css/App_Logo.jpg',
width: 700,
height: 830,
//autoHideMenuBar: true,
//fullscreen: true,
webPreferences:
{
nodeIntegration: true,
}
});
mainWindow.loadURL("http://localhost:3003");
mainWindow.on("closed", function ()
{
mainWindow = null;
});
}
app.on("ready", createWindow);
app.on("resize", function (e, x, y)
{
mainWindow.setSize(x, y);
});
app.on("window-all-closed", function ()
{
if (process.platform !== "darwin")
{
app.quit();
}
});
app.on("activate", function ()
{
if (mainWindow === null)
{
createWindow();
}
});
net_client_sender.js
const net = require('net');
const client = new net.Socket();
const settings = require("../../settings/comms_settings.json");
netClient = {}
netClient.client = client;
netClient.ConnectToPLC = () =>
{
client.connect(settings["modbusPORT"], settings["plcIPv4"]);
}
netClient.SendRequest = (msg) =>
{
client.write(msg);
}
module.exports = netClient;
net_client_receiver.js
api = require("./api.js");
netClient = require("./net_client.js");
var connected = false;
/*Check if there is a connection to the PLC,*/
/*if not wait a moment and try to connect again*/
var CheckConnection = () =>
{
/*if there is no connection to PLC*/
var connectionTester = setInterval(() =>
{
if (connected === false)
{
console.log("Connection to PLC failed!");
console.log("Retrying connection...\n\n");
/*Retry connection to PLC*/
netClient.ConnectToPLC();
}
/*if there is a connection to the PLC*/
else
{
/*stop trying to connect to the PLC*/
clearInterval(connectionTester);
}
}, 1000);
}
netClient.client.on("timeout", () =>
{
connected = false;
CheckConnection();
});
netClient.client.on("connect", () =>
{
connected = true;
api.StartMainLoop();
});
netClient.client.on("data", (data) =>
{
api.ReadModbusMessage(data);
});
netClient.ConnectToPLC();
CheckConnection();
So just to clarify, I am not concerned with the error itself, but rather just with the fact that the error is shown in a pop-up message. So if someone can please tell me what to do to make it not show it would help a lot.
Related
I am developing a simple webRTC application, using my own server for signaling.
the javascript code is as follow (I have removed the signaling process and unnecessary logic):
const configuration = {
iceServers: [
{
urls: [
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
],
},
],
iceCandidatePoolSize: 10,
};
const callerCandidatesString = "callerCandidates";
const calleeCandidatesString = "calleeCandidates";
var received_offer = null;
var offer = null;
var answer = null;
var peerConnection = null;
let localStream = null;
let remoteStream = null;
var constraints = {
optional: [],
mandatory: {
OfferToReceiveAudio: true,
OfferToReceiveVideo: true
}
}
async function startMedia(e) {
const localStream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});
document.getElementById("video1").srcObject = localStream;
remoteStream = new MediaStream();
document.getElementById("video2").srcObject = remoteStream;
if (I am the caller) {
create_the_offer();
}
if (I am the callee) {
get_the_offer();
}
}
async function create_the_offer() {
peerConnection = new RTCPeerConnection(configuration);
registerPeerConnectionListeners();
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});
var offer = await peerConnection.createOffer(constraints);
peerConnection.setLocalDescription(offer);
peerConnection.onicecandidate = function(candidate) {
if (candidate.candidate == null) {
//save the offer in the server
--> offer: JSON.stringify(peerConnection.localDescription)},
}
}
check_if_there_is_an_answer();
}
async function get_the_offer() {
// --> retrieve the offer from the server, then
create_answer(offer_from_server);
}
async function create_answer(received_offer) {
console.log("Create PeerConnection with configuration: ", configuration);
peerConnection = new RTCPeerConnection(configuration);
registerPeerConnectionListeners();
localStream.getTracks().forEach(track => {
peerConnection.addTrack(track, localStream);
});
console.log('received offer:' + received_offer)
my_offer = new RTCSessionDescription(JSON.parse(received_offer));
peerConnection.setRemoteDescription(my_offer);
// collectIceCandidates(peerConnection, calleeCandidatesString, callerCandidatesString);
peerConnection.addEventListener("track", event => {
console.log("Got remote track:", event.streams[0]);
event.streams[0].getTracks().forEach(track => {
console.log("Add a track to the remoteStream:", track);
remoteStream.addTrack(track);
});
});
const answer = await peerConnection.createAnswer(constraints);
console.log("Created answer:", answer);
await peerConnection.setLocalDescription(answer);
peerConnection.onicecandidate = function (e) {
if (e.candidate == null) {
// --> send the answer to the server
}
}
function check_if_there_is_an_answer() {
// retrieve answer from server. this function is executed several times until the answer is received.
// when there is an aswer:
start_remote_connection(answer);
}
async function start_remote_connection(passed_answer) {
my_answer = new RTCSessionDescription(JSON.parse(passed_answer));
peerConnection.setRemoteDescription(my_answer);
peerConnection.addEventListener("track", event => {
console.log("Got remote track:", event.streams[0]);
event.streams[0].getTracks().forEach(track => {
console.log("Add a track to the remoteStream:", track);
remoteStream.addTrack(track);
});
console.log("stream remoto: " + JSON.stringify(remoteStream.getVideoTracks()));
});
document.getElementById("video1").srcObject = localStream;
document.getElementById("video2").srcObject = remoteStream;
}
async function hangUp(e) {
const tracks = document.getElementById("video1").srcObject.getTracks();
tracks.forEach(track => {
track.stop();
});
remoteStream.getTracks().forEach(track => track.stop());
peerConnection.close();
document.getElementById("video1").srcObject = null;
document.getElementById("video2").srcObject = null;
}
// collect ICE Candidates function below
async function collectIceCandidates(peerConnection, localName, remoteName) {
const candidatesCollection = null;
peerConnection.addEventListener("icecandidate", event => {
if (event.candidate) {
const json = event.candidate.toJSON();
candidatesCollection.add(json);
}
});
}
// collect ICE Candidates function above
function registerPeerConnectionListeners() {
peerConnection.addEventListener("icegatheringstatechange", () => {
console.log(
`ICE gathering state changed: ${peerConnection.iceGatheringState}`);
});
peerConnection.addEventListener("connectionstatechange", () => {
console.log(`Connection state change: ${peerConnection.connectionState}`);
});
peerConnection.addEventListener("signalingstatechange", () => {
console.log(`Signaling state change: ${peerConnection.signalingState}`);
});
peerConnection.addEventListener("iceconnectionstatechange ", () => {
console.log(
`ICE connection state change: ${peerConnection.iceConnectionState}`);
});
}
window.onload = startMedia();
If the caller uses chrome and the callee uses FireFox (on localhost, same PC) the code works fine and both users can share their screen.
output with chrome
If the caller uses FireFox and the callee uses Chrome (still on localhost) the code still works fine, but the connection is not established and users cannot see the screen of the other person. I get no error in the console.
output with FireFox
In particular, with FF I am not getting "connection state change: connecting" and then "connection state change: connected".
My guess is that FF and chrome manage the async/await differently, and somehow with FF some values are not ready when actually needed, but cannot figure out why ...
with safari (MacOS) it does not work!!
I then tried it between the computer (with chrome) and an Android phone (chrome browser). It worked the first time I test it, and then never again :(
Does anyone of you has a clue ?
I am trying achieve something where I can directly send data to react and where in react whenever it receives it does something.
So my electron.js is in below format.
// ./public/electron.js
const path = require("path");
const { app, BrowserWindow, ipcMain} = require("electron");
const isDev = false; //require("electron-is-dev"); //false
let splash = null;
let win = null;
let etmf_obj = null;
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
enableRemoteModule: true,
preload: path.join(__dirname, "./preloadDist.js"),
},
});
// win.loadFile("index.html");
win.loadURL(
isDev
? "http://localhost:3000"
: `file://${path.join(__dirname, "../build/index.html")}`
);
// Open the DevTools.
if (!isDev) {
win.webContents.openDevTools({ mode: "undocked" });
}
}
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
function restartApp() {
console.log("restarting app..");
app.exit();
app.relaunch();
}
//IPC SECTION
ipcMain.handle("notify", (event, args) => {
console.log("from react I got" + args);
console.log("hello from electron via react"); //this one works as expected
});
ipcMain.on("splashDone", function () {
console.log("splash done");
});
ipcMain.on("relaunchApp", function () {
restartApp();
});
ipcMain.on("closeAll", function () {
app.quit();
});
ipcMain.on("callAnim", function (args) {
win.webContents.send("showAnimation", args);// trying to send data directly to
//react here but don't know whether its right way or not
});
and my preload file preloadDist.js is in below format
const { ipcRenderer, contextBridge } = require("electron");
contextBridge.exposeInMainWorld("electron", {
notificationApi: {
sendNotification(message) {
ipcRenderer.invoke("notify", message);
},
},
batteryApi: {},
filesApi: {},
splashStatus: {
splashDone() {
ipcRenderer.invoke("splashDone")
}
},
});
and react to call function of or to send data I am do this
for example to send notification data :
<button
className="speak_border"
onMouseEnter={() => setHovermic(true)}
onMouseLeave={() => setHovermic(false)}
onClick={() => {
soundwave();
window.electron.notificationApi.sendNotification(
"From react Hi!");
}}
>
and to receive data I am not able to figure out but as I am doing win.webContents.send("showListenAnimation", args);
I am not able to understand how this will be received at the react end
what I tried is:
useEffect(() => {
try {
window.electron.on(
"showAnimation",
function (event, data) {
if (data) {
setAnim(true);
}
if (!data) {
setAnim(false);
}
}
);
} catch (e) {
console.log("issue with on getting data");
}
});
But this way I am getting error and not able to figure out the way to receive, but sending data from react to electron is working perfectly fine!
Please guide on this and how to achieve with about preload.js and electron.js
format.
I want to subscribe to the topic with SockJS and Stomp Client I put the subscribe on the client inside onConnect function to make sure that the Client is connected, This my configuration for:
import getEnvVars from "./environment";
import { socketUrl } from "../services/GlobalUrls";
import SockJS from "sockjs-client";
import { Client } from "#stomp/stompjs";
/**
* Please notice that this import not used on this file
* but used on the library of this file
* so please don't delete it or the app will throw an error
* */
import * as encoding from "text-encoding";
const url = getEnvVars().apiUrl + socketUrl;
let _stompClient = null;
const webSocket = () => {
//const [message, newMessage] = useState();
_stompClient = new Client({
brokerURL: url,
connectHeaders: {},
debug: (str) => {
console.log(str);
},
reconnectDelay: 500,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
logRawCommunication: false,
webSocketFactory: () => {
return SockJS(url);
},
onStompError: (frame) => {
console.log("Stomp Error", frame);
},
onConnect: (frame) => {
console.log("Stomp Connect", frame);
if (_stompClient.connected) {
_stompClient.subscribe("topic/notification", (message) => {
console.log("message");
if (message.body) {
let notification = JSON.parse(message.body);
if (notification.type == "MESSAGE") {
console.log("MESSAGE", notification);
} else if (notification.type == "INVITATION") {
console.log("INVITATION", notification);
} else if (notification.type == "REMOVED") {
console.log("REMOVED", notification);
}
}
});
}
},
onDisconnect: (frame) => {
console.log("Stomp Disconnect", frame);
},
onWebSocketClose: (frame) => {
console.log("Stomp WebSocket Closed", frame);
},
onWebSocketError: (frame) => {
console.log("Stomp WebSocket Error", frame);
},
});
_stompClient.activate();
return _stompClient;
};
export default webSocket;
On my react native component:
useEffect(() => {
webSocket();
}, []);
My debug show this:
Opening Web Socket...
accept-version:1.0,1.1,1.2
heart-beat:4000,4000
Web Socket Opened...
heart-beat:0,0
version:1.2
content-length:0
id:sub-0
destination:topic/notification/8
>>> CONNECT
accept-version:1.0,1.1,1.2
heart-beat:4000,4000
Received data
<<< CONNECTED
heart-beat:0,0
version:1.2
content-length:0
connected to server undefined
Stomp Connect FrameImpl {
"_binaryBody": Uint8Array [],
"command": "CONNECTED",
"escapeHeaderValues": false,
"headers": Object {
"heart-beat": "0,0",
"version": "1.2",
},
"isBinaryBody": true,
"skipContentLengthHeader": false,
}
>>> SUBSCRIBE
id:sub-0
destination:topic/notification
The same debug showed on the angular app and I got the message but on my react native app I got nothing.
Angular setup:
const ws = new SockJS(this.globalService.BASE_URL + "/socket");
this.stompClient = Stomp.over(ws);
this.stompClient.debug = () => {};
const that = this;
this.stompClient.connect({}, function(frame) {
that.stompClient.subscribe(
"/topic/notification",
message => {
if (message.body) {
let notification = JSON.parse(message.body);
if (notification.type == "MESSAGE") {
that.messageListService.setNotificationObs(notification);
} else if (notification.type == "INVITATION") {
that.messageListService.setInvitationNotificationObs(notification);
} else if (notification.type == "REMOVED") {
that.messageListService.removeInvitationNotificationObs(notification);
}
}
}
);
});
Okay i find out the right way to configure the Client, and maybe this will help anyone on the future here
I need to instantiate the Client _stompClient = new Client(); then configure it like that :
_stompClient.configure({
...
onConnect: (frame) => {
console.log("onConnect");
_stompClient.subscribe("/topic/notification", (message) => {
console.log(message.body);
});
},
...
});
_stompClient.activate();
And i got my message on the debug.
Answered Here
I am trying to build a simple Chatroom where multiple users can post the messages.I have setup the node web socket and it's broadcasting for a single message, but it closes the connection immediately after that.
This includes react on the front-end and node.js on the backend.
For simplicity i am storing and retrieving all the messages in a json file.
I am using ws: a node.js websocket library to setup the socket connection.
In client side i am using browsers WebSocket instance and listening on the same port.
// In server.js (Backend)
const server = http.createServer(doOnRequest)
const WebSocket = require('ws')
const wss = new WebSocket.Server({ port: 1994 })
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN){
client.send(data);
}
});
});
ws.on('close', () => {
console.log('server conn closed');
setTimeout(() => {
console.log('closed by server console. log');
}, 2000);
})
});
function doOnRequest(request, response) {
// This functions handles all the get and post calls and stores
it in a file
}
const server = http.createServer(doOnRequest)
server.listen(3001);
// IN Chatroom.js ( UI )
const URL = 'ws://localhost:1994'
class Chatroom extends React.Component {
ws = new WebSocket(URL)
constructor(props) {
////// binding classes declaring state ////
}
componentDidMount() {
this.ws.onopen = () => {
console.log('connected')
}
this.ws.onmessage = evt => {
// on receiving a message, add it to the list of messages
let x = this.state.messageList;
x ? x.push(JSON.parse(evt.data)) : [JSON.parse(evt.data)];
this.setState({
messageList: x,
value: ''
});
}
this.ws.onclose = () => {
console.log('disconnected')
}
this.renderOlderMessages();
}
renderOlderMessages() {
// render older messages using GET request
}
addNewMessage(chatObj) {
// let res = a Post request (with Request body as chatObj).
res.then(() => {
this.ws.send(JSON.stringify(chatObj))
let x = this.state.messageList;
x ? x.push(chatObj) : [chatObj];
this.setState({
messageList: x,
value: ''
});
});
}
render() {
return (
<div>
/// render old messages ///
</div>
<div>
<form>
Input ---> New message ---> Submit
</form>
</div>
)
}
}
I am setting up a multi-paged electron application, however whenever I start my application it opens all the pages, and anytime I click a button that is supposed to bring the user to the next page, it skips ahead and opens the other pages as well.
I believed the issue was with setting the parent/child relation of each window, however when commenting or removing those properties the issue persists.
const{app, BrowserWindow, ipcMain} = require('electron');
import{fstat} from 'fs';
import{resolve} from 'path';
const packagejson = require('../package.json')
app.commandLine.appendSwitch('touch-events', 'enabled');
if (require('electron-squirrel-startup')) {
app.quit();
}
let mainWindow;
let startWindow;
let setOriginsWindow;
const createWindow = () => {
startWindow = new BrowserWindow({
width: 800,
height: 600,
});
startWindow.loadURL(`file://${__dirname}/index.html`);
startWindow.webContents.openDevTools();
startWindow.on('closed', () => {
startWindow = null;
});
};
app.on('ready', createWindow);
ipcMain.on('set-origins', (event) => {
setOriginsWindow = new BrowserWindow({
})
setOriginsWindow.on('close', function() {setOriginsWindow = null});
setOriginsWindow.loadURL(`file://${__dirname}/set_origin_page.html`)
setOriginsWindow.once('ready-to-show', () => {
setOriginsWindow.show();
});
setOriginsWindow.openDevTools();
if(packagejson.ENV == "dev"){
setOriginsWindow.openDevTools();
}
})
// parent:startWindow,
// fullscreen: true,
// modal:true,
// show:false
ipcMain.on('start-procedure', (event) => {
mainWindow = new BrowserWindow({
})
mainWindow.on('close', function () {mainWindow = null});
mainWindow.loadURL(`file://${__dirname}/main_page.html`);
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
mainWindow.openDevTools();
if(packagejson.ENV == "dev"){
mainWindow.openDevTools();
}
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (startWindow === null) {
createWindow();
}
});
'''
The 1st page to open should be a splashscreen with button that when pressed, will open page 2. Page 2 has a button that when pressed will open page 3.
Electron is not good for multipage apps, and displays a blank screen for around a quarter of a second when changing pages. Instead, you might want to create a file with all pages combined and switch between them with DOM methods
For Example
var splash_screen = document.getElementById('splash-screen');
var second_screen = document.getElementById('second-screen');
var third_screen = document.getElementById('third-screen');
document.removeChild(second_screen)
document.removeChild(third_screen)
var splash_button_click = () => {
document.removeChild(splash_screen);
document.appendChild(second_screen);
}