flapjax get last element from eventstream - node.js

I am trying to implement a small chatservice using flapjax. I use an eventStream to get all the clients that connect to the server, and when broadcasting a message (the function on 'message') I map over this eventStream with the function that emits the message to the current client.
// Event stream yielding received clients
var clientReceiverE = receiverE();
// Event stream collecting all the clients
var clientsE = clientReceiverE.collectE([], function (client, clients) {return clients.concat([client]);});
socket.on('connection', function(client) {
clientReceiverE.sendEvent(client);
for (i = 0; i < chatMessages.length; i++) {
client.emit('message', chatMessages[i]);
}
client.on('message', function(message) {
chatMessages.push(message);
//for (i = 0; i < clients.length; i++) {
// clients[i].emit('message', message);
//}
mapE(clientReceiverE, function(client) {console.log(client); client.emit('message', message); return client});
});
client.on('nickname', function(name) {
});
});
The registring of the clients on the eventstream succeeds with this code, but the mapE doesn't result in a loop over all this clients. Does anybody know what is wrong here?

If you are still not guessed :) I think it's because mapE doesn't produce any action itself, mapE only creates and returns another EventStream which behaves like a given source, but with modified value by means of a given function.

You should not be using mapE like that. In your code you are attempting to recreate the mapE event bindings with each client.on('message', ...).
This problem is solved using a receiverE. This function is used to translate, external event streams into flapjax EventStream 's.
// Event stream yielding received clients
var clientReceiverE = receiverE();
// Event stream collecting all the clients
var clientsE = clientReceiverE.collectE([], function (client, clients) {return clients.concat([client]);});
var clientsB = clientsE.startsWith(undefined); //Turn the event stream into a behaviour (event + value)
var messagesE = receiverE();
messagesE.mapE(function(messagePacket){
var clients = clientsB.valueNow(); //Grab current value of client list behaviour
if(clients==undefined){
return;
}
var from = messagePacket.client;
for(var index in clients){
clients[index].emit('message', messagePacket.message);
console.log(messagePacket.message);
}
});
socket.on('connection', function(client) {
clientReceiverE.sendEvent(client);
client.on('message', function(message) {
messagesE.sendEvent({client: client, message: message});
});
});
The difference is this. The flapjax tree is isolated from the WebSocket event code and there is no shared state between them.

Related

mqtt broker + node js + dht11 sensor

I have a question about MQTT broker. My code is here and it works with Mosca server.
var mqtt = require('mqtt');
var scanf = require('scanf');
var client = mqtt.connect('mqtt://localhost');
client.on('message', function (topic, message) {
// message is Buffer
console.log(message.toString())
//client.end()
})
client.on('connect', function () {
setInterval(function() {
console.log('Please scan data');
var data = scanf('%s');
console.log('Message Sent');
while(data==0){
client.subscribe('/sensors/#');
break;
}
if(data==1){
client.unsubscribe("/sensors/#");
}
},500);
});
I am trying to take sensor data after enter 0 but I entered 0 they come all of them data until that time. Arduino ide goes on sending data every 500ms but I just want to take data when I entered 0.
There are a number of problems with this.
Firstly scanf('%s') will block until a enter is pressed which is not what you want inside a setInterval() callback.
Next your while loop, it doesn't do what you think it does.
You should only call client.subscribe('/sensors/#') once, this tells the client to inform the broker that it this client is to be told about all messages that match the topic "/sensors/#". After that the MQTT client will receive all messages published until client.unsubscribe('/sensors/#') is called.
Also since scanf('%s') is only called once the data will never change
this means that the loop will either run forever or never run at all depending on what key is pressed.
What you want is something like this:
var mqtt = require('mqtt');
var scanf = require('scanf');
var data = "0";
var client = mqtt.connect('mqtt://localhost');
client.on('message', function (topic, message) {
if (data == "1") {
console.log(message.toString())
}
})
client.on('connect', function () {
client.subscribe('/sensors/#');
});
do {
data = scanf('%s');
} while (true)
This will start and subscribe to topic, it will then wait for you to enter 1, after that it will print every matching message, if you then enter 0 it will stop printing out values until you enter 1 again.
p.s. good MQTT topic design says that topics should not start with a leading '/'

How do I output a stream of tuples from a Storm spout with emit() and sync()?

(xpost github issue)
I'm new to Storm. I found the helpful node-storm library and I have successfully submitted topologies, but I can't get my spout to emit a stream of tuples.
node-storm's wordcount example works fine.
I want a spout that subscribes to a websocket and outputs any messages as tuples.
Here's my attempt so far. I think I have some misconfiguration, because I know I my wsEmitter is emitting future events, but my Storm UI shows zero spout emits.
I suspect that maybe I shouldn't be binding the listener inside the spout function?
Does this function get invoked multiple times? (looks like it... see https://github.com/RallySoftware/node-storm/blob/master/lib/spout.js#L4 )
What does sync actually do and when should I use it?
var storm = require('node-storm');
var wsEmitter = require('./wsEmitter.js')();
wsEmitter.init(); // subscribe to websocket
var futuresSpout = storm.spout(function(sync) {
var self = this;
console.log('subscribing to ws');
wsEmitter.on('future', function(data){ // websocket data arrived
self.emit([data]);
sync();
});
})
.declareOutputFields(["a"]);
Turns out I had two problems. First, my topology wasn't executing because one of my bolts (not shown) failed to set .declareOutputFields().
Second, I need to delay the emits from the spout until the supervisor asks for one emit with nextTick(). I did that by buffering any incoming messages until the supervisor calls the spout:
module.exports = (function(){
var storm = require('node-storm');
var wsEmitter = require('./wsEmitter.js')();
wsEmitter.init();
var queue = [];
var queueEmpty = true;
wsEmitter.on('thing', function(data){
var trade = JSON.parse(data);
trade.timeReported = new Date().valueOf();
queue.push(trade);
queueEmpty = false;
});
return storm.spout(function(sync) {
var self = this;
setTimeout(function(){
if(!queueEmpty){
self.emit([queue.shift()]);
queueEmpty =
( queue.length === 0
? true
: false )
}
sync();
}, 100);
})
.declareOutputFields(['trade'])
})()

Pusher: How to bind to 100s of events?

The push library works as below
var channel = pusher.subscribe('test_channel');
channel.bind('my_event', function(data) {
alert(data.message);
});
However:
Would I be able to do this?
var channel = pusher.subscribe('test_channel');
channel.bind(['my_event1', 'my_event2'....'my_event100'], function(data) {
alert(data.message);
});
In my use case, I have one channel and there are many different events and each client might want to simulantaneously subscribe to 100s of events.
The signature for the channel.bind function is String channelName, Function callback (pusher-js source). You can't pass in an Array of channels`.
If you want the same function to be called then you'll need to pass a reference to the function and call bind multiple times:
var channel = pusher.subscribe('test_channel');
var callback = function(data) {
alert(data.message);
};
var eventName;
for( var i = 0; i < 100; ++i ) {
eventName = 'my_event' + ( i + 1 );
channel.bind( eventName, callback );
}
The single-threaded nature of JS will equate to these event binding happening simultaneously.
You could of course create your own helper function to allow bind( Array eventNames, Function callback ).

Send out real time data to webclients error trapping

Trying to send data from a serial device to web clients. I am using a serial to network proxy, ser2Net to make the data available to a server that acts on the data and sends a manipulated version of the data to web clients. The clients specify the location of the ser2net host and port. The core of this action is coded in node.js as shown here:
function getDataStream(socket, dataSourcePort, host) {
var dataStream = net.createConnection(dataSourcePort, host),
dataLine = "";
dataStream.on('error', function(error){
socket.emit('error',{message:"Source not found on host:"+ host + " port:"+dataSourcePort});
console.log(error);
});
dataStream.on('connect', function(){
socket.emit('connected',{message:"Data Source Found"});
});
dataStream.on('close', function(){
console.log("Close socket");
});
dataStream.on('end',function(){
console.log('socket ended');
dataConnection.emit('lost',{connectInfo:{host:host,port:dataSourcePort}});
});
dataStream.on('data', function(data) {
// Collect a line from the host
line += data.toString();
// Split collected data by delimiter
line.split(delimiter).forEach(function (part, i, array) {
if (i !== array.length-1) { // Fully delimited line.
//push on to buffer and emit when bufferSendCommand is present
dataLine = part.trim();
buffer.push(part.trim());
if(part.substring(0, bufferSendCommand.length) == bufferSendCommand){
gotALine.emit('new', buffer);
buffer=[];
}
}
else {
// Last split part might be partial. We can't announce it just yet.
line = part;
}
});
});
return dataStream;
}
io.sockets.on('connection', function(socket){
var stream = getDataStream(socket, dataSourcePort, host);
//dispense incoming data from data server
gotALine.on('new', function(buffer){
socket.emit('feed', {feedLines: buffer});
});
dataConnection.on('lost', function(connectInfo){
setTimeout(function(){
console.log("Trying --- to reconnect ");
stream = getDataStream(socket, connectInfo.port, connectInfo.host);
},5000);
});
// Handle Client request to change stream
socket.on('message',function(data) {
var clientMessage = JSON.parse(data);
if('connectString' in clientMessage
&& clientMessage.connectString.dataHost !== ''
&& clientMessage.connectString.dataPort !== '') {
stream.destroy();
stream = getDataStream(socket,
clientMessage.connectString.dataPort,
clientMessage.connectString.dataHost);
}
});
});
This works well enough until the serial device drops off and ser2net stops sending data. My attempt to catch the end of the socket and reconnect is not working. The event gets emitted properly but the setTimeout only goes once. I would like to find a way to keep on trying to reconnect while sending a message to the client informing or retry attempts. I am node.js newbie and this may not be the best way to do this. Any suggestions would be appreciated.
Ok I think I figured it out in the dataStream.on('data' ... I added a setTimeout
clearTimeout(connectionMonitor);
connectionMonitor = setTimeout(function(){doReconnect(socket);}, someThresholdTime);
The timeout executes if data stops coming in, as it is repeatedly cleared each time data comes in. The doReconnect function keeps trying to connect and sends a message to the client saying something bad is going on.

node.js simple tcp chat server

I am trying to build a simple tcp chat server, WITHOUT socket.io.
Now, I have no problem broadcasting data across all sockets connected to the server.
My problem is assigning a socket identifier to each connection and retrieving them from an object.
Here is the code:
var net = require('net');
//keep track of sockets
var allSockets = {
sockets: {},
addSocket: function(socket, nick, table) {
this.sockets[table+nick] = socket;
},
removeSocket: function(nick, table) {
if (this.sockets[table+nick] !== undefined) {
this.sockets[table+nick] = null;
delete this.sockets[table+nick];
}
}
};
// create the server
var server = net.createServer(function (socket) {
var connected = false;
var jsoncommand = true;
//first data sent MUST BE json formatted string in this format
//{"nick":"someid","table":"tablenumber"}
var thisnick = "";
var thistable = "";
// get client ip
socket.name = socket.remoteAddress;
//write something on each connect
socket.write("You are connecting from " + socket.name + "\n");
socket.write(socket.name + " joined chat\n");
//handle data streams
socket.on('data', function (data) {
if (jsoncommand) {
//JSON.parse the first data stream
var some = JSON.parse(data);
//assign a socket.id based on nick and table
allSockets.addSocket(socket, some.table, some.nick);
socket.write(some.nick + " joined " + some.table + "\n");
thisnick = some.nick;
thistable = some.table;
connected = true;
//no longer waiting for first stream as JSON
jsoncommand = false;
} else if (connected) {
//write whatever data it recieves (function is below)
broadcast(data, thistable);
} else {
socket.write("You are not connected to any table");
socket.destroy();
connected = false;
jsoncommand = true;
thisnick = "";
thistable = "";
}
});
// remove the socket from allSockets but broadcast
//only to other users on the same table
socket.on('end', function () {
allSockets.removeSocket(thisnick, thistable);
broadcast(thisnick + " has left table " + thistable, thistable);
});
//this function should select from the allSockets object,
//only those, whose property matches "table"
//and write to those sockets only, when called
function broadcast(message, table) {
allSockets.sockets.forEach(function(socket) {
if (socket.hasOwnProperty(table)) {
socket.write(message);
}
});
}
});
server.listen(8000);
console.log("running at port 8000\n");
Just deploy this on your machine and connect with nc to port 8000
and be sure that the first thing you send it is something like
{"nick":"mynick","table":"mytable"}
you will see a message that your nick joined your table.
now if you send it something else, based on the fact that it stored your table name,
it should echo whatever you send it, to you and to other connections with different
nicks but on the same table, but the server dies, throwing an error that the allSockets
object, does not have a "for" or "forEach" method or indexOf, or any other.
SO, how do I correct this?
If my nick is "john" and I joined "my_table", and also "mary", "lisa" and "ana" joine the same "my_table", assuming I don't know their nicks, but I do know they are on "my_table",
HOW do I select from the allSockets object, those sockets that contain "my_table".
I tried hasOwnProperty, but that returns boolean, which only tells me that there are sockets with that property, but how do I put them in a for, or foreach loop in order to write to them.
I know it may be a silly question, or maybe im not even aproaching this correctly, but im a node.js beginner, so any advice is greatly apreaciated.
By the way I put this together from examples across the web.
As for the JSON string, its the first thing being sentby a desktop app on connection. Anyways I chose it for testing purposes so don't bother with it.
I suppose error about forEach happens here:
allSockets.sockets.forEach(function(socket) {
While allSockets.sockets is not Array, but it is object (key > value model, like hash table).
So to loop through each socket in it, you should change loop to:
for(var key in allSockets.sockets) {
var socket = allSockets.sockets[key];
// your logic here
}

Resources