How to make a socket.io connection between two different interfaces? - javascript

I'm actually trying to make a real-time connection between two different apps. I've found a bunch of tutorials about how to make a chat using socket.io, but that doesn't really help me since it's just the same app duplicated in multiple windows.
I'm making a pick & ban overlay for League of Legends in local development. My first thought was to display the empty overlay on one hand and create an interface to manually update it on the other hand. Socket.io seems to be the right thing to use in my case since it can provide new data without having to reload the component.
This is what I wrote in both apps :
const express = require('express');
const socket = require('socket.io');
// App setup
const app = express();
const server = app.listen(4200, function () {
console.log('Listening to requests on port 4200')
});
// Static files
app.use(express.static('public'));
// Socket setup
const io = socket(server);
io.on('connection', function (socket) {
console.log('Made socket connection', socket.id);
socket.on('change', function (data) {
io.sockets.emit('change', data);
});
});
But I fail to connect them as they have to listen to the same port. What am I doing wrong?
(Forgive my bad English and lack of syntax, I'm doing my best here. :p)

I am certainly not an expert on network programming, but as far as I know you need to have one listening app (backend) and another one to connect to it (client). And you define what happens with all the data (messages) that backend recieves (for example sending the messages it recieves to all the clients in the same chat room).
If I am correct to assume you are trying to connect two listening apps?
simple google search of "nodejs socket server client example" revealed this https://www.dev2qa.com/node-js-tcp-socket-client-server-example/ might wanna take your research in this direction

u can try something like this way
var express = require('express');
var socket = require('socket.io');
// App setup
var app = express();
var server = app.listen(8080, () => {
console.log('App started')
})
// Static file
app.use(express.static('public'))
// Socket SetUp
var io = socket(server);
io.on('connection', socket => {
console.log('made the connection')
socket.on('chat',data => {
io.sockets.emit('chat',data)
});
socket.on('typing',data => {
socket.broadcast.emit('typing',data);
});
})
create another file and
var socket = io.connect('http://localhost:8080')
// Elenment
var message = document.getElementById('message');
handle = document.getElementById('handle');
btn = document.getElementById('send');
output = document.getElementById('output');
feedback = document.getElementById('feedback');
// Emit Events
btn.addEventListener('click', () => {
socket.emit('chat', {
message: message.value,
handle: handle.value
})
})
message.addEventListener('keypress', () => {
socket.emit('typing', handle.value)
})
socket.on('chat',data => {
feedback.innerHTML = '';
output.innerHTML += '<p><strong>' + data.handle +': </strong>' +
data.message + '</p>'
})
socket.on('typing', data => {
feedback.innerHTML = '<p><emp>' + data + ' is typing a message... </emp></p>'
})
details are given here node socket chat app

Ok, figured it out. Here's how it works using express and vue together :
First, setup socket.io in your express server js file :
const express = require('express')
const { Server } = require('socket.io')
const http = require('http')
const app = express()
const server = http.createServer(app)
const io = new Server(server, {
cors: {
origin: '*',
methods: ['GET', 'POST', 'REMOVE']
}
})
const PORT = process.env.PORT || 8080
io.on('connection', (socket) => {
console.log('New socket user')
socket.on('SEND_MESSAGE', data => {
console.log('received message in back')
io.emit('MESSAGE', data)
})
})
server.listen(PORT, () => { console.log(`Server started on port : ${PORT}`)})
As you can see we received from the client "SEND_MESSAGE" and we trigger MESSAGE from the server to forward the information to all the clients. The point I was missing is that we bind SEND_MESSAGE on the socked created from the connection but we emit from the io server.
Now you vue part :
import io from 'socket.io-client'
export default {
data() {
return {
messages: [],
inputMessage: null,
socket: io('http://localhost:8080')
}
},
mounted() {
this.socket.on('MESSAGE', data => {
this.messages.push(data)
})
},
methods: {
sendMessage() {
const message = {
senderID: this.myID,
message: this.inputMessage,
sendAt: new Date()
}
this.socket.emit('SEND_MESSAGE', message)
this.inputMessage = null
},
},
}

Related

Socket.IO disconnect event

My code is working fine when new user joins but when a user left it doesn't show anything
Can anyone tell me error in my code
Here is my server side code
const express = require("express");
const path = require("path");
const http = require("http");
const socketio = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = socketio(server); // socketio expects to be called by raw http server so we did little bit of refactoring
const publicPath = path.join(__dirname, "../public");
const port = process.env.PORT || 3000;
app.use(express.static(publicPath));
// let count = 0;
// server(emit) -> client(receive) -> countUpdated
// client(emit) -> server(receive) -> increment
io.on("connection", (socket) => {
console.log("New web socket connection");
socket.emit("message", "Welcome!");
socket.broadcast.emit("message", "A new user has joined"); // it emits msg to everyone except the user who run this command
socket.on("sendMessage", (message) => {
io.emit("message", message);
socket.on("disconnect", () => {
io.emit("message", "A user has left");
}); // when user disconnect we use socket.on("disconnect")
});
Here is my client side code
const socket = io(); // to communicate with socketio we did this, now we can send events or recieve events from clients
socket.on("message", (message) => {
console.log(message);
});
const form = document.querySelector("#message-form");
form.addEventListener("submit", (e) => {
e.preventDefault();
let message = e.target.elements.message.value; // e.target refers to form and we can select elements of form using the name property we defined in html
socket.emit("sendMessage", message);
});
I am expecting when a user left
It should show "A user has left" in console
Currently you have only start to listen to disconnect event when the client has already sent at least 1 message. Here's the relevant extract:
io.on("connection", (socket) => {
// …
socket.on("sendMessage", (message) => {
// …
socket.on("disconnect", () => {
});
});
});
You should therefore reduce the callback nesting, and start listening to disconnect in the connection handler directly. Which leads to:
io.on("connection", (socket) => {
console.log("New web socket connection");
socket.emit("message", "Welcome!");
socket.broadcast.emit("message", "A new user has joined"); // it emits msg to everyone except the user who run this command
socket.on("disconnect", () => {
io.emit("message", "A user has left");
}); // when user disconnect we use socket.on("disconnect")
socket.on("sendMessage", (message) => {
io.emit("message", message);
});
});

How export variable outside a class module

I found this example to use mqtt in node.js like a class:
mqtt_handler.js:
const mqtt = require('mqtt');
class MqttHandler {
constructor() {
this.mqttClient = null;
this.host = 'YOUR_HOST';
this.username = 'YOUR_USER'; // mqtt credentials if these are needed to connect
this.password = 'YOUR_PASSWORD';
}
connect() {
// Connect mqtt with credentials (in case of needed, otherwise we can omit 2nd param)
this.mqttClient = mqtt.connect(this.host, { username: this.username, password: this.password });
// Mqtt error calback
this.mqttClient.on('error', (err) => {
console.log(err);
this.mqttClient.end();
});
// Connection callback
this.mqttClient.on('connect', () => {
console.log(`mqtt client connected`);
});
// mqtt subscriptions
this.mqttClient.subscribe('mytopic', {qos: 0});
// When a message arrives, console.log it
this.mqttClient.on('message', function (topic, message) {
console.log(message.toString());
});
this.mqttClient.on('close', () => {
console.log(`mqtt client disconnected`);
});
}
// Sends a mqtt message to topic: mytopic
sendMessage(message) {
this.mqttClient.publish('mytopic', message);
}
}
module.exports = MqttHandler;
and then, in app.js:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
var mqttHandler = require('./mqtt_handler.js');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }))
var mqttClient = new mqttHandler();
mqttClient.connect();
// Routes
app.post("/send-mqtt", function(req, res) {
mqttClient.sendMessage(req.body.message);
res.status(200).send("Message sent to mqtt");
});
var server = app.listen(3000, function () {
console.log("app running on port.", server.address().port);
});
Works fine, and the mqtt code written in other file, can help me to write a tidier code.
I would need to be able to use incoming messages directly in app.js, because then I would have to handle them with socket.io, but I would like to leave the mqtt related code separate from app.js. But I can't find a way to export incoming message values directly to app.js.
this.mqttClient.on('message', function (topic, message) {
console.log(message.toString());
});

Connect multiple Serialports from Arduino with NodeJs

I'm having trouble connecting 4 arduinos using serialports and NodeJs.
When I connect all the ports only one is actually working and collecting the data message while all the others are ignored.
If I declare the serial ports separately they all work fine so the problem is not the Arduino code.
Here's how i declare all the serialports:
// Load HTTP module to create server, handle requests and send back static files (html, css, js)
const http = require('http');
// Load file system module to load files from computer
const fs = require('fs');
// Load path module to read paths from urls
const path = require('path');
// Load serialport module to communicate with arduino
const SerialPort = require('serialport');
// Open up connection with Arduino board
const serial = new SerialPort('/dev/cu.usbserial-1411140', {
baudRate: 115200
}, function() {
console.log('1411140 ready');
})
const SerialPort1 = require('serialport');
const serial1 = new SerialPort1('/dev/cu.usbserial-141120', {
baudRate: 115200
}, function() {
console.log('141120 ready');
})
const SerialPort2 = require('serialport');
const serial2 = new SerialPort2('/dev/cu.usbmodem-1411301', {
baudRate: 115200
}, function() {
console.log('1411301 ready');
})
const SerialPort3 = require('serialport');
const serial3 = new SerialPort3('/dev/cu.usbserial-1411130', {
baudRate: 115200
}, function() {
console.log('1411130 ready');
})
// Define port on which the webpage will be served from
const port = 8080;
This is how i read the arduino data
const io = require('socket.io')(server);
// do stuff when a client connects
io.on('connection', (socket) => {
console.log('a new client connected');
// let the client know that it's connected
socket.emit('greetings', 'You are now connected to the server through Socket IO');
// when receiving data from Arduino, tell the client what to do accordingly
serial.on('data', forwardMessage);
// log if an user disconnects
socket.on('disconnect', () => {
console.log('client disconnected');
// remove listener from Node EventEmitter
serial.removeListener('data', forwardMessage);
});
function forwardMessage(data) {
let message = data.toString().replace(/\n*/, '');
//riceve messaggi dal device corrispondente. Attenzione al nome messo anche sul codice Arduino
if (message.includes('Coinv')) {
socket.emit('CoinvChange', message.substring(7));
}
if (message.includes('Impor')) {
socket.emit('ImporChange', message.substring(7));
}
if (message.includes('Piace')) {
socket.emit('PiaceChange', message.substring(7));
}
if (message.includes('Cresc')) {
socket.emit('CrescChange', message.substring(7));
}
if (message.includes('Press')) {
socket.emit('PressChange', message.substring(7));
}
}
});
And finally this is how i use the message
const socket = io();
// log on browser console when socket is connected to server
socket.on('greetings', (message) => {
console.log(message);
});
// Caricamento Petali
socket.on('CoinvChange', (message) => {
console.log('coinv');
if(message<=6){
getFlowerObject ("petali", 1);
}
if(message>7 && message <=9) {
getFlowerObject ("petali", 2);
}
if(message>12) {
getFlowerObject ("petali", 3);
}
});
// Caricamento Sepali
socket.on('ImporChange', (message) => {
console.log('Impor');
if(message<=2){
getFlowerObject ("sepali", 1);
}
if(message>3 && message <=7) {
getFlowerObject ("sepali", 2);
}
if(message>8) {
getFlowerObject ("sepali", 3);
}
});
Thank you for your help!
Well, in the second snipped, you call just serial.on('data', forwardMessage);, and serial just refers to the firt one.
If you want to interact with the other ones, you have to call the same method also on serial1, serial2 and serial3, which you never use, instead.
As a sidenote, it's enugh to use const SerialPort = require('serialport'); just at the beginning (of the first snippet), then you can do
const serial1 = new SerialPort(...)
...
const serial2 = new SerialPort(...)
...

NodeJs, Express, Socket.io chat application, how to emit two different types of messages for sender and receivers?

If the title is not clear (I'm sorry if it's not), basically at the moment the messages that I send from the DOM to the server and from the server back to the DOM are all blue bubbles (right side). So even when I'm the receiver of the message (which should be a grey bubble on the left), I receive it on the right.
How can I differentiate between the two so that when I send a message it's blue and when I receive it it's grey (see image for example)?
I'm sorry if it's a stupid question, but I'm only getting started with NodeJs and it's still a little confusing to me sometimes.
JS SERVER SIDE
const path = require("path");
const http = require("http");
const express = require("express");
const socketio = require("socket.io");
//RUN EXPRESS SERVER
const app = express();
//RUN SERVER USING HTTP MODULE REQUIRED BY SOCKET.IO
const server = http.createServer(app);
//INIT SOCKET.IO
const io = socketio(server);
// SET STATIC FOLDER
app.use(express.static(path.join(__dirname, "public")));
//RUN WHEN CLIENT CONNECTS
io.on("connection", (socket) => {
//message only to me when I connect
socket.emit("message", "Welcome to Chat.io");
//message to other users when I connect
socket.broadcast.emit("message", "User has joined the chat");
//message to other users when I disconnect
socket.on("disconnect", () => {
io.emit("message", "User has left the chat");
});
socket.on("chatMessage", (msg) => {
io.emit("message", msg);
});
});
const PORT = 3000 || process.env.PORT;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
JS FRONTEND
const chatForm = document.getElementById("chat-form");
//WE CAN USE THIS BECAUSE OF THE SCRIPT TAG IN chat.html
const socket = io();
//FUNCTION TO CATCH MESSAGES EMITTED FROM SERVER
socket.on("message", (message) => {
console.log(message);
outputMessage(message);
});
//MESSAGE SUBMIT
chatForm.addEventListener("submit", (e) => {
e.preventDefault();
//get chat message from DOM
const msg = e.target.elements.msg.value;
//emit chat message to server
socket.emit("chatMessage", msg);
//clear field
chatForm.reset();
});
//OUTPUT MESSAGE TO DOM FUNCTION
function outputMessage(message) {
const div = document.createElement("div");
div.classList.add("chat-row");
div.innerHTML = `
<div class="bubble-right--container">
<div class="chat-bubble chat-bubble--right">
${message}
</div>
<p class="meta">20.18</p>
</div>`;
document.querySelector(".chat-panel").appendChild(div);
}
I solved! (So happy) maybe it's not the cleanest way, so please feel to give your answer!
Basically after catching the message sent from the DOM on the server, I created two different emits:
socket.on("chatMessage", (msg) => {
socket.broadcast.emit("greyMessage", msg);
socket.emit("blueMessage", msg);
});
Then I caught them on the frontend JS using two different functions:
//CATCH GREY MESSAGES
socket.on("greyMessage", (message) => {
outputGreyMessage(message);
});
//CATCH BLUE MESSAGES
socket.on("blueMessage", (message) => {
outputBlueMessage(message);
});
Now it works!

communicate between two modules nodejs

Hello i am trying to emit command using SOCKET to user when setting gets changed through some API..
but I dont know how can i get socket or tell socket to emit the message to user..
Please Help
this is my code
//Socket INIT
class Socket{
constructor(){
//Init variables
}
start(){
//Start socket
this.io.use((socket, next) => this.auth.authDevice(socket, next));
this.io.on('connection',(socket) => this.conn.handleConn(socket));
}
}
//Socket Connection
let socketStack = [];
class Connection{
handleConn(socket){
// store client
socketStack[socket.userid] = socket
}
pushCmd(userid, command){
//cheeck if userid exists in >>socketStack<< and emit
}
}
//Command Emit
class Command {
constructor(id) {
this.userid = id.userid
//socket - Connection class
this.socketConn = new SocketHandler()
}
static push(userid, command) {
//i want to sent it to current socket context. this has empty socketStack..
this.socketConn.pushCmd(userid, command);
}
}
let socket = new Socket();
socket.start() //connection started, all clients connect to //this socket .. I WANT API to use this socket to emit something that //API sends....
You have to make socket to 'listen' on server. For example, I'm using express with node.js, and this is the way I run socket.io:
var app = express();
var server = require('http').createServer(app);
var io = socketio.listen(server);
io.on('connect', function (socket) {
socket.on('exampleCall', function () {
console.log("socket invoked!");
socket.emit("exampleEmit");
});
});
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function () {
var addr = server.address();
console.log("Server listening at", addr.address + ":" + addr.port);
});

Categories

Resources