I am not able to connect to mqtt server from node.js - node.js

I am completely new to mqtt and node.js i want to get data from mqtt server at regular intervals and populate in my html5 page
Here is the sample code that am try to connect but not sure it is right way or not
var mqtt = require('mqtt');
// connect to the message server
var client = mqtt.connect('mqtt://test.mosquitto.org');
// publish 'Hello mqtt' to 'test'
client.publish('test', 'Hello mqtt');
// terminate the client
client.end()

Assuming you really are working purely with node.js you haven't given the client time to actually connect before trying to publish a message.
The node.js mqtt module README has a full example (which it appears you've copied and removed most of the important bits from). I have removed the subscription part from the demo code, but this is the bare minimum needed to publish a message.
var mqtt = require('mqtt');
var client = mqtt.connect('mqtt://test.mosquitto.org');
client.on('connect', function () {
client.publish('test', 'Hello mqtt');
client.end();
});

Following code upload data on hivemq MQTT Broker at regular interval.
var mqtt = require('mqtt');
// connect to the message server
var client = mqtt.connect('mqtt://broker.hivemq.com');
client.on('connect', function () {
setInterval(function () { client.publish('mytopic', 'Hello mqtt') }, 1000)
})
If you want to retrieve that data then use the following function
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
client.end()
})

Related

Strange numbers in SocketIo events data

I'm trying to learn SocketIo in NodeJS. I'm using .on and .emit functions with same event name but server dont see incoming event emitted by client but client recive some strange numbers as data to event.
I was trying to change .on to .addListener but this is still not working.
Server:
const io = require('socket.io');
const server = io.listen(8089);
server.on('connect', socket => {
console.log('New connection!') // this line is working fine!
socket.on('ping', incomingMessage => {
console.log('Incoming message!');
socket.emit('pong', incomingMessage);
});
});
Client code:
Im using cdn from: https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js
const server = io('http://127.0.0.1:8089');
server.on('connect', () => {
server.on('pong', message => {
console.log('Incoming message! ', message);
});
server.emit('ping', 'test message');
})
But i dont see 'Incoming message' in server side terminal. Client sucessfully connected to server socket and after ~ 5 seconds i recive strange messages like:
- Incoming message! 1
- Incoming message! 3
- Incoming message! 4
in webbrowser console (using Opera)
Ok so i fixed this issue :v the problem was ping-pong event names that already was used by socket.io if i changed event names everything is working fine.

Send object to client via Socket.io (Node.js)

I have the following code written on the node.js side:
var filtered = quadtree.filter(function (element) {
return element.x > min
})
console.log(typeof filtered);//object
socket.emit("Sonuç", filtered);
Here's the html code:
socket.on("Sonuç", function (data) {
console.log(data)
});
There is no connection problem between server and client. I have a variable named filtered on the server side, and I learned that this variable is the object of its type. I do not have anything to send it to the client side and print it on the screen. What function should I use in the code section?
I do not know when you send from server to client in time?
If you send it in connection then you need to open the client first, then start the server then the server sends the data and the client can receive the data.
// server
io.sockets.on('connection', function(socket) {
var filtered = {key: 'value'};
socket.emit("Sonuç", filtered);

Simple communication via MQTT between node apps

Hi I'm really new to MQTT and I've read a lot of posts and blogs about it the last days, yet I seem not to fully understand the different parts needed, such as Broker, Clients.
I want two node apps to communicate with each other via a local mqtt service. As far as I understand, this mqtt service is called broker. I managed it to let 2 node apps communicate via a public broker like this:
app1 (sender)
const mqtt = require('mqtt');
// to be changed to own local server/service
const client = mqtt.connect('http://broker.hivemq.com');
client.on('connect', () => {
let id = 0;
setInterval(() => {
client.publish('myTopic', 'my message - ' + ++id);
}, 3000);
});
app2 (receiver)
const mqtt = require('mqtt');
// to be changed to own local server/service
const client = mqtt.connect('http://broker.hivemq.com');
client.on('connect', () => {
client.subscribe('myTopic');
});
client.on('message', (topic, message) => {
console.log('MSG: %s: %s', topic, message);
});
As this worked, I wanted to move on by replacing the public broker with a private one. After a while I found mqtt-server as a node package.
So I tried the following as a third node app, which is supposed to be the broker for app1 and app2:
server (MQTT broker)
fs = require('fs');
mqttServer = require('mqtt-server');
let subscriptions = [];
let servers = mqttServer(
// servers to start
{
mqtt: 'tcp://127.0.0.1:1883',
mqttws: 'ws://127.0.0.1:1884',
},
// options
{
emitEvents: true
},
// client handler
function (client) {
client.connack({
returnCode: 0
});
client.on('publish', (msg) => {
let topic = msg.topic;
let content = msg.payload.toString();
// this works, it outputs the topic and the message.
// problem is: app2 does not receive them.
// do we have to forward them somehow here?
console.log(topic, content);
});
client.on('subscribe', (sub) => {
let newSubscription = sub.subscriptions[0];
subscriptions.push(newSubscription);
console.log('New subscriber to topic:', newSubscription.topic);
});
});
servers.listen(function () {
console.log('MQTT servers now listening.');
});
Problem
After adjusting the connection-Uris (both to ws://127.0.0.1:1884) in app1 and app2 The server app receives all messages that are published and recognises that someone connected and listens to a specific topic.
But: While the server gets all those events/messages, app2 does not receive those messages anymore. Deducing that, something with this broker must be wrong, since using the public broker everything works just fine.
Any help is appreciated! Thanks in advance.
I can't get mqtt-server to work either, so try Mosca.
Mosca only needs a back end if you want to send QOS1/2 messages, it will work with out one.
var mosca = require('mosca');
var settings = {
port:1883
}
var server = new mosca.Server(settings);
server.on('ready', function(){
console.log("ready");
});
That will start a mqtt broker on port 1883
You need to make sure your clients are connecting with raw mqtt not websockets, so makes sure the urls start mqtt://

How to send Redis message to client side when a new message is published in that channel

I am trying to implement a functionality wherein when a user is viewing a page, he should be automatically subscribed a Redis channel unique to that user. And all message published to that Redis channel should be received by the client side.
Below is by client side code,
var socket = io.connect('localhost:5000');
socket.on('connect', function(){
socket.emit("subscribe",$("#app_id").text());
});
socket.on('message', function(message) {
$("#lst").append("<li>" + message + "</li>")
});
And on the nodejs server, I have below code,
var client = redis.createClient();
io.sockets.on('connection', function (socket) {
socket.on("subscribe",function(channel){
client.subscribe(channel);
socket.join(channel);
});
client.on("message", function(channel, message){
socket.broadcast.to(channel).emit('message', message);
});
});
When I open the client page in two separate browsers, its subscribing to the two channels correctly and message published to those Redis channels are shown at client side. But if I refresh the page, the number of messages which I get is double and if I refresh again, it adds up. I guess the listeners getting added-up on each refresh.
I have coded the Redis listener inside the socket.io connection listener because I want to emit the message to the socket.This may be cause of the problem am facing. Dono how else to do it as I need socket instance to send message to client side. Please help on this.
as you already told: remove the listener on disconnect.
Have a look at how-to-remove-redis-on-message-listeners and socket-io-handling-disconnect-event for further reading.
untested sample
var client = redis.createClient();
io.sockets.on('connection', function (socket) {
var broadcast = function(channel, message){
socket.broadcast.to(channel).emit('message', message);
}
socket.on("subscribe",function(channel){
client.subscribe(channel);
socket.join(channel);
});
socket.on('disconnect', function() {
client.unsubscribe(channel);
client.removeListener(broadcast)
})
client.on("message", broadcast);
});

How to reuse redis connection in socket.io?

Here is my code using socket.io as WebSocket and backend with pub/sub redis.
var io = io.listen(server),
buffer = [];
var redis = require("redis");
var subscribe = redis.createClient(); **<--- open new connection overhead**
io.on('connection', function(client) {
console.log(client.request.headers.cookie);
subscribe.get("..", function (err, replies) {
});
subscribe.on("message",function(channel,message) {
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.send(msg);
});
client.on('message', function(message){
});
client.on('disconnect', function(){
subscribe.quit();
});
});
Every new io request will create new redis connection. If someone open browser with 100 tabs then the redis client will open 100 connections. It doesn't look nice.
Is it possible to reuse redis connection if the cookies are same?
So if someone open many browser tabs also treat as open 1 connection.
Actually you are only creating a new redis client for every connection if you are instantiating the client on the "connection" event. What I prefer to do when creating a chat system is to create three redis clients. One for publishing, subscribing, and one for storing values into redis.
for example:
var socketio = require("socket.io")
var redis = require("redis")
// redis clients
var store = redis.createClient()
var pub = redis.createClient()
var sub = redis.createClient()
// ... application paths go here
var socket = socketio.listen(app)
sub.subscribe("chat")
socket.on("connection", function(client){
client.send("welcome!")
client.on("message", function(text){
store.incr("messageNextId", function(e, id){
store.hmset("messages:" + id, { uid: client.sessionId, text: text }, function(e, r){
pub.publish("chat", "messages:" + id)
})
})
})
client.on("disconnect", function(){
client.broadcast(client.sessionId + " disconnected")
})
sub.on("message", function(pattern, key){
store.hgetall(key, function(e, obj){
client.send(obj.uid + ": " + obj.text)
})
})
})
Redis is optimized for a high level of concurrent connections. There is also discussion about multiple database connections and connection pool implementation in node_redis module.
Is it possible to reuse redis
connection if the cookies are same? So
if someone open many browser tabs also
treat as open 1 connection.
You can use for example HTML5 storage on the client side to keep actively connected only one tab and others will handle communication/messages through storage events. It's related to this question.
I had this exact problem, with an extra requirement that clients must be able to subscribe to private channels, and publish to those channels should not be sent to all listeners. I have attempted to solve this problem by writing a miniature plugin. The plugin:
Uses only 2 redis connections, one for pub, one for sub
Only subscribes to "message" once total (not once every redis connection)
Allow clients to subscribe to their own private channels, without messages being sent to all other listening clients.
Especially useful if your prototyping in a place where you have a redis connection limit (such as redis-to-go).
SO link: https://stackoverflow.com/a/16770510/685404
You need to remove the listener when client disconnect.
var io = io.listen(server),
buffer = [];
var redis = require("redis");
var subscribe = redis.createClient();
io.on('connection', function(client) {
console.log(client.request.headers.cookie);
subscribe.get("..", function (err, replies) {
});
var redis_handler = function(channel,message) {
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.send(msg);
};
subscribe.on("message", redis_handler);
client.on('message', function(message){
});
client.on('disconnect', function(){
subscribe.removeListerner('message', redis_handler)
//subscribe.quit();
});
});
See Redis, Node.js, and Socket.io : Cross server authentication and node.js understanding
Using redis as a store has become much simpler since this question was asked/answered. It is built in now.
Note, that if you are using redis because you are using the new node clustering capabilities (utilizing multiple CPUs), you have to create the server and attach the listeners inside of each of the cluster forks (this is never actually explained anywhere in any of the documentation ;) ). The only good code example online that I have found is written in CoffeeScript and I see a lot of people saying this type of thing "just doesn't work", and it definitely doesn't if you do it wrong. Here's an example of "doing it right" (but it is in CoffeeScript)

Resources