Node.Js MQTT Broker - node.js

I am having the following code in node.js.
It connects fine to the broker I have set on my personal website/server, and it is able to send and listen to the events from the server.js.
My problem is that it does not listen to other events that are sent to the broker from other devices. How can I make sure that the code below will manage to listen to all events from the broker?
Thanks
var mqtt = require('mqtt')
var MQTT_TOPIC = "homeGet/light";
var MQTT_ADDR = "mqtt://broker.example.org:80";
var MQTT_PORT = 80;
var client = mqtt.connect(MQTT_ADDR,{clientId: "webClient", keeplive: 1, clean: false, debug:true});
var express = require('express');
var socket = require('socket.io');
//store the express functions to var app
var app = express();
//Create a server on localhost:5000
var server = app.listen(process.env.PORT || 5000);
//var server = app.listen((process.env.PORT || 3000, function(){
//console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
//});
//host content as static on public
app.use(express.static('public'));
console.log("Node is running on port 5000...");
//MQTT
client.on('connect', function () {
client.subscribe(MQTT_TOPIC, { qos: 2 });
client.publish(MQTT_TOPIC, '1000');
});
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString());
client.end();
});
client.on('error', function(){
console.log("ERROR")
client.end()
})
client.on('offline', function() {
console.log("offline");
});
client.on('reconnect', function() {
console.log("reconnect");
});

You have client.end() in your client.on('message',function(message){...}) callback.
This will disconnect the client as soon as it receives it's first message.
Assuming you copied this from the example in the README.md for the mqtt package on npm. That example is specifically set up to receive only one message.

Related

uWebSockets - push events to server

I have a uWebSockets server as it seems to be a lot more performance friendly than socket.io servers.
So I have a server and its connected fine and after some trouble I got the index.html client side to connect, but now I'm not able to push events to the server from the client side. What am I doing wrong?
var WebSocketServer = require('uws').Server,
express = require('express'),
path = require('path'),
app = express(),
server = require('http').createServer(),
createEngine = require('node-twig').createEngine;
var wss = new WebSocketServer({server: server});
wss.on('connection', function (ws) {
ws.on('join', function (value) {
console.log('SOMEONE JUST JOINED');
});
ws.on('close', function () {
//console.log('stopping client interval');
clearInterval(id);
});
});
server.on('request', app);
server.listen(8080, function () {
console.log('Listening on http://localhost:8080');
});
index.html
<script>
var host = window.document.location.host.replace(/:.*/, '');
var server = new WebSocket('ws://' + host + ':8080');
server.onmessage = function (event) {
updateStats(JSON.parse(event.data));
};
server.onopen = function (event) {
server.send("Here's some text that the server is urgently awaiting!");
server.send('join');
};
function something() {
console.log('WORKED');
server.send('join');
}
</script>
You don't have an event listener setup on the server side that does receive and react on the message. Like
ws.on('message', function (msg) {
// Do something with the message received from the client
});

Multiple instances of simple chat with Node.js, Websocket - Socket.IO and Redis

I am trying to create a simple chat App with Node.JS and Websocket using Socket.IO. I inspired myself by this German tutorial and for the single backend instance it works well.
I would like to have 2 instances of the server in the backend, which should sync the chat messages between each other and store the chat history in redis. The client should display the last 10 messages from the current channel, when new chat-room is joined.
I tried to apply the solution from this stackoverflow page but I get some issues. First I get
WebSocket connection to 'ws://localhost:8080/socket.io/?EIO=3&transport=websocket&sid=LEqGvY0CVk9YaSzBAAAA' failed: Connection closed before receiving a handshake response
error in the console. And second, both clients are receiving the 'payload' messages in the 1-sec interval. I probably do not understand how the redis-sync mechanism works and I also do not yet know how to display the chat history.
Here is my code so far:
var conf = require('./config.json');
var cluster = require('cluster');
var os = require('os');
if (cluster.isMaster) {
// we create a HTTP server, but we do not use listen
// that way, we have a socket.io server that doesn't accept connections
var server = require('http').createServer();
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: conf.redisUri, port: conf.redisPort }));
setInterval(function() {
// all workers will receive this in Redis, and emit
io.emit('chat', {time: new Date(), text:'payload'});
}, conf.syncIntervall);
// set number of workers
for (var i = 0; i < conf.numberOfWorkers; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
}
if (cluster.isWorker) {
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var redis = require('socket.io-redis');
// Webserver
//app.listen(conf.defaultPort);
server.listen(conf.defaultPort);
// deliver static files
app.use(express.static(__dirname + '/public'));
// route for the / path
app.get('/', function (req, res) {
// send the index.html in the reponse
res.sendfile(__dirname + '/public/index.html');
});
// Websocket
io.adapter(redis({ host: conf.redisUri, port: conf.redisPort }));
// Callback when a client connects
io.sockets.on('connection', function (socket) {
// store the room name in the socket session for this client
socket.room = 'defaultChannel';
// send client to room 1
socket.join('defaultChannel');
// echo to client they've connected
socket.emit('chat', { time: new Date(), text: 'You have connected to room defaultChannel on the server!' });
socket.emit('chat', { time: new Date(), text: 'Connected to chat worker-node: ' + cluster.worker.id});
// if a message is received
socket.on('chat', function (data) {
// the it will be send to all other clients
console.log('the current channel', socket.room);
socket.broadcast.in(socket.room).emit('chat', { time: new Date(), name: data.name || 'anonymous', text: data.text });
});
// if a client joins a channel
socket.on('join', function (room) {
// store the room name in the socket session for this client
socket.room = room;
// send client to room 1
socket.join(room);
console.log('Client joined room ' + room);
});
});
// Log port number in the console
console.log('Server running under http://127.0.0.1:' + conf.defaultPort + '/');
}

Node js, Call WebSocket server from http server

I have a node js ( supported by express js ) http application. So I had a server.js file as follows(not there complete code).
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
I later added websocket server to there. So it is like this now.
// app server
var app = require('./app/app');
var server = http.createServer(app);
server.listen(port, host);
server.on('error', onError);
server.on('listening', onListening);
/**
* websocker Server
*/
var WebSocket = require('ws');
var wsServer = http.createServer();
var url = require('url');
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({ server: wsServer });
var express = require('express');
var wsApp = express();
var port = 1337;
wsApp.use(function (req, res) {
res.send({ msg: 'hello' });
});
wss.on('connection', function connection(ws) {
console.log((new Date()) + ' Connection from origin ');
ws.on('message', function incoming(message) {
console.log('received: %s', message);
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
var json = JSON.stringify({ type:'message', data: {hello : 'hello'} });
ws.send(json);
});
wsServer.on('request', wsApp);
wsServer.listen(port, function () { console.log('Ws server Listening on ' + wsServer.address().port); });
Now these two are working happily. What I want is on a POST call to the http server, I want to trigger the web socket server to broadcast something to all clients. My problem is How I can trigger websocket server from http server?
Routes of http server is defined in app.js file. from there how can I call websocker server function?
If you encapsulate your ws functionality in one single javascript file (e.g: websocket.js) you could export your websocket object as a module.
module.exports = wss;
and then require it in your http controller
var wss = require(websocket.js)
In this case it should be easy to use wss.send({...}) wherever you like.
This peace of code is working to me:
//websocket.js
'use strict';
var io = require('socket.io');
var callme;
function Websocket(server) {
var server = io(server);
server.on('connection', function(socket){
console.log('Do something here');
});
callme = function (val) {
//you my choose a specific cliente if you want, read the socket.io doc
server.emit('I may emit it ' + val);
console.log("Called " + val);
return 'Somebody got it';
}
}
Websocket.route = function(req, res, next) {
if(typeof callme == 'function'){
res.send(callme(req.param('t')));
}else{
res.send('Websocket server is not running');
}
};
module.exports = Websocket;
On the express app definition, I put
var Websocket = require('./websocket');
app.use('/blablabla', Websocket.route);
Then, on the server js file, which run the application, I put
var server = http.createServer(app);
var s = new Websocket(server);
This last line works like the tradicional io(server); would work.
After that, when you request the address /blablabla the route will execute your websocket method.
My solution is not in production yet, let me know if somebody got an error.

How to emit message from client side [node.js + socket.io]

I am trying to emit message from client side with socket.io ...
Here is my client code:
var socket = io.connect('http://localhost/');
socket.on('connect', function(data){
setStatus('connected');
socket.emit('subscribe', {channel:'update.comment'});
});
Server:
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
Also I get this error message in console:
GET
http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1
404 (Not Found)
Full serever:
var app = require('express')();
var http = require('http').Server(app);
var redis = require('ioredis');
var io = require('socket.io')(http);
redisClient = redis.createClient();
//look for connection errors and log
redisClient.on("error", function (err) {
console.log("error event - " + redisClient.host + ":" + redisClient.port + " - " + err);
});
io.sockets.on('connection', function (socket) {
socket.emit('message', { text : 'Welcome!' });
//on subscription request joins specified room
//later messages are broadcasted on the rooms
socket.on('subscribe', function (data) {
socket.join(data.channel);
redisClient.subscribe(data.channel);
});
});
redisClient.on('ready', function(data) {
console.log('#redis ready');
});
redisClient.on("message", function(channel, message){
console.log(channel);
var resp = {'text': message, 'channel':channel};
io.sockets.in(channel).emit('message', resp);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
New Problem Recognized:
Your server is listening on port 3000, but you are attempting to connect on port 80. The error message http://localhost/socket.io?EIO=3&transport=polling&t=1442169984269-1 has no port number on it so that defaults to port 80.
That error message means that your server-side socket.io code is not initialized correctly and thus is not listening for the HTTP request that starts all webSocket connections so when the browser tries to connect on that URL to initiate a socket.io connection, there's nobody on the server-side listening so the web server returns a 404 error back to the browser.
If you are using Express, this is the minimal socket.io initialization to hook it into your server:
var express = require('express');
var app = express();
var server = app.listen(8081);
var io = require('socket.io').listen(server);
For a plain HTTP server, this is the minimal socket.io initialization:
var app = require('http').createServer(handler)
var io = require('socket.io')(app);
app.listen(80);
As always, if you show us the socket.io and web server initialization code you are using, we can help you better with your specific code issue.

Simple node.js socket server

I am trying to create a simple node.js server that will allow my socket based iOS app to send it's GPS coordinates to the server, and the server will broadcast the GPS coordinate to all connected iOS clients. Similarly, the clients are connected to the server using sockets. I tried using some sample code from Heroku's web server. CODE IS EDITED TO INCLUDE ANURAG'S ANSWER
var WebSocketServer = require("ws").Server
var http = require("http")
var express = require("express")
var app = express()
var port = process.env.PORT || 5000
app.use(express.static(__dirname + "/"))
var server = http.createServer(app)
server.listen(port)
console.log("http server listening on %d", port)
var wss = new WebSocketServer({server: server})
console.log("websocket server created")
var connectionList = [];
wss.on("connection", function(ws) {
console.log("connection");
connectionList.push(ws);
})
wss.on("message", function(data, id) {
var mes = server.unmaskMessage(data);
var str = server.convertToString(mes.message);
console.log(str);
var i;
for(i = 0; i < connectionList.lenth; i++) {
wss.sendMessage(one, str, connectionList[i]);
}
});
How do I modify this code to be able to receive messages from my app (via sockets) and then send that message to all other iOS clients connected. (The message is just a simple string)
BONUS QUESTION: Because Heroku makes you use it's environments port (rather than your own specified one), in my iOS app, when I connect to the server, would I just specify the Port that is printed to the console when the server is started.
Any help is appreciated, Thank you! :)
EDIT: For broadcasting to the clients, the code is:
wss.on('connection', function(ws) {
ws.on('message', function(message) {
wss.broadcast(message);
});
});
However how do I receive messages from a client, and how do I make the received message the message to be broadcasted to the other clients.
On getting the connection you need to store those connections.
Then you can send message to all those devices connect to your server using those connections.
You may try something like this:
var connectionList = [];
wss.on("connection", function(ws) {
connectionList.push(ws);
})
wss.on("message", function(data, id) {
var mes = server.unmaskMessage(data);
var str = server.convertToString(mes.message);
console.log(str);
var i;
for(i = 0; i < connectionList.lenth; i++) {
wss.sendMessage(one, str, connectionList[i]);
}
});
Read more here: https://www.npmjs.com/package/websocketserver
Here is the complete index.js code sothat the server brodcast received messages to clients:
var WebSocketServer = require("ws").Server
var http = require("http")
var express = require("express")
var app = express()
var port = process.env.PORT || 5000
app.use(express.static(__dirname + "/"))
var server = http.createServer(app)
server.listen(port)
console.log("http server listening on %d", port)
var wss = new WebSocketServer({server: server})
console.log("websocket server created")
wss.broadcast = function(data) {
for (var i in this.clients)
this.clients[i].send(data);
};
wss.on("connection", function(ws) {
console.log("websocket connection open");
ws.on('message', function(message) {
console.log("message received by server");
wss.broadcast(message);
})
ws.on("close", function() {
console.log("websocket connection close")
})
})

Resources