Need simple data push to browser using node.js - javascript

On the server side, I use node.js to do some distributed asynchronous ping-pong. I now need to display the results as a real-time chart in a client browser. To keep things simple, I am presently using the image-based Google chart URL and restricting the amount of data to be plotted. Eventually this client-side display piece will be rich & interactive.
I understand that one of the ways for my server to push the data out to the browser is Comet. I expect there must be a corresponding socket-something on the browser side, so the two should go together.
Q1: For prototyping: what is the simplest way for me to push string data from node.js to my Firefox 3.6.10 browser? String updates less than 1KB once per second.
Q2: For production: any recommendations for an approach that will work across browsers, including mobile devices? Binary updates order of 100KB per second, no images or video.

I'd really recommend taking a look at http://socket.io/ for Node.js. It works on mobile devices, and supports multiple methods for the Comet effect that you desire, utilizing the best option available to the browser.
It's pretty dead simple too, although it does lack channels, but it's an easy workaround using socket.broadcast(msg, [array containing every user except those 'subscribed'])

Every two seconds server generates a random number r1 in [0,100], then messages client to draw a piechart with r1 and r2=100-r1. Yet to implement the broadcast suggested for multiple clients. Any other suggestions for improvements welcome.
Server side (in coffeescript):
http = require('http')
io = require('socket.io')
server = http.createServer( )
server.listen(8000)
socket = io.listen(server)
myrand = (client) -> setInterval( ->
r1 = Math.floor(Math.random()*101)
r2 = 100-r1
client.send(String(r1) + ',' + String(r2))
, 2000)
socket.on('connection', (client) -> myrand(client))
Client side (index.html with javascript):
<h1>My socket client</h1>
<script src="http://cdn.socket.io/stable/socket.io.js"></script>
<div id="piechart">
Hello World
</div>
<script>
socket = new io.Socket('localhost:8000');
socket.connect();
socket.on('message', function(data){
url = 'http://chart.apis.google.com/chart?cht=p3&chs=250x100&chd=t:' + data + '&chl=Hello|World';
document.getElementById('piechart').innerHTML = "<img src="+ url + "></img>";
});
</script>

Related

Posting Variable Values from Javascript and Reading them with Python (UV4L, WebRTC, Raspberrypi3)

I am working on a project where we plan on controlling a rover through a web-based application. I am using UV4L and its modules on the Raspberry Pi. I have the streaming side set up well, but now I am trying to send data back to the Pi.
I have taken this joystick and put into the demo webpage.
What I want to do is take the X and Y value that this joystick produces and send it back to the Pi and have it print the values. The way I have been attempting to do this is to turn the X and Y values into a JSON and read the JSON with Python. I am relatively new to programming, and have been thrown into the proverbial deep end.
I was trying to use an example I found in another stackoverflow question this is what I produced butchering the code:
var xhr = new XMLHttpRequest();
var url= “webappurl”;
xhr.open(“POST”, url, true);
xhr.setRequestHeader(“Content-Type”, “json”);
xhr.onload= function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var json =JSON.parse(xhr.responseText);
console.log(json.x +”, “ + json.y);
}
};
var data = JSON.stringify({x, y});
xhr.send(data);
Then I did this on the Python Side:
import requests
import simplejson
r = requests.get('webappurl')
c = r.content
j = simplejson.loads(c)
print(j)
The problem I have been having is that everything I find online has a different recommendation on how to do this and I haven't been able to find something in other people's projects I could utilise for our purposes or have the knowledge to adapt, and I need to keep it as direct/simple as possible.
I am under the impression that the joystick may already be built with functions/variables that can be used to trigger or post.
Any recommendations for the best way to go about this or the correct code to do this would be appreciated - I also have the WebRTC data channels available but I don't know if I need to use them to do this.
I also wondered if there was means to send the variable values over the websocket and use python to parse the websocket.
Thank you for your time,
Since you are developing a web application, it seems natural to stay with WebRTC. UV4L supports two-way audio, video and data channels. Here is how data channels work on the UV4L side.
Furthermore, the built-in WebRTC demo page that you can fetch, as an example, from the /stream/webrtc URL on the uv4l server certainly embeds some javascript code using data channels from the client side. You can find some code in this other demo web app here as well.

Can WebSockets replace AJAX when it comes to Database requests?

This may seem like an extremely dumb question, but I am currently switching my Website from using the EventSource Polling constructor to the WebSocket standard which is implemented in Node.js.
Originally, all backend on my website was handled with PHP. With the introduction of Node.js, I am trying to switch as much as I can without going outside of the "standard". By standard, I meaning that typically I see WebSocket implementations that send small data, and receive small data back vs. performing database queries and then sending large amounts of data back to the client.
Can WebSockets replace AJAX when it comes to Database requests?
Let's consider a small hello world program in PHP/JavaScript (AJAX) vs Node.js/JavaScript (WebSockets)
PHP/JavaScript (AJAX)
// HelloWorld.php with Laravel in the Backend
Table::update([ 'column' => $_POST['message'] ]);
echo $_POST['message'];
Ajax.js with a custom ajax function
Global.request("HelloWorld.php").post({
message: "Hello World"
}).then(message => alert(message));
Node.js/JavaScript (WebSockets)
// skip all the server setup
server.on('connection', function () {
server.on('message', function (message) {
sqlConnection.query("UPDATE `table` SET `column` = ?", [message], function () {
server.send(message);
});
});
});
WebSocket.js:
let socket = new WebSocket('ws://example.com');
socket.onmessage = function (message) {
alert(message)
}
socket.send("Hello World");
They both essentially do the same thing, in a slightly different way. Now, in this scale it would not make sense to use WebSockets. Though an example, imagine it scaled up to a point where Node.js is processing bigger queries and sending lots of data to the client. Is this acceptable?
Yes, theoretically, you could trigger a db query with websockets. Both HTTP and Websockets are built on TCP which do the job of transferring data of being a the bridge between network requests and responses.
The bigger issue is that Websockets were intended to lessen burden of opening/closing network ports, which you would have to do for ajax. This comes with several application-level benefits including real-time media streaming.
So what's the benefit of sticking with HTTP if you don't have a specific use case for web sockets? That HTTP is built has a robust ecosystem of tools - HTTP is largely plug & play. Think of stuff like security and standardization. Web sockets is a relatively new technology and hasn't developed this same ecosystem.

I am trying to manage a small number of users control of a webpage

So to start off, I have a raspberry pi, running a lighttp server on arch. I have a webpage that will have a max of 10 people connected at a time. Each user will be given the tag "Master," or "observer." The webpage will have controls that only the "Master," can use.
Just a heads up: I am just learning most of this so I may be making some mistakes about how to accomplish this.
My original idea is has follows. When a user connects to the database their IP address would be grabbed and inserted into a SQLite database, along with a user tag, and time of connection. From there I would be able to query the database for the users tag when they tried to execute various commands.
Whatever I use needs to be very lightweight and not store cookies on the users device.
Here is the JavaScript I currently have, it probably isn't the most efficient, but I plan on getting it working then making it look nice.
This code is supposed to connect the databases and insert the user.
<script type="text/javascript" src="http://l2.io/ip.js?var=myip"></script>
<script type="application/javascript">
var db = openDatabase('userCon.contbl.sqlite', '1.0', 'contbl', 1024);
db.transaction(function(transaction) {
var ip = myip;
var conStatus = "master"
var date = new Date();
console.log('Inserting into the database ' + ip + ',' + conStatus +',' + date);
transaction.executeSql('INSERT INTO contbl(ipAd, conType, lastActive) VALUES (?,?,?,?)',[ip,conStatus,date], function(transaction, results) {
}, function (transaction, err){
console.log(err.message+":Error"); // here an error
});
});
</script>
<script type="application/javascript" src="http://jsonip.appspot.com/?callback=getip"> </script>
I am unable to connect to the SQLite database I created on the pi, which after my research may be because SQLite is supposed to be run locally and not on a server.
Is there some sort of work around to point to the SQLite database on the pi, or is there a better resource to use for this type of task?
EDIT:
I guess my original post was not specific enough. The basic idea is I need to be able to pass a tiny bit of information from a webpage, back to the server hosting it. i.e. User connect to the server and sends its IP then the server tags that IP as an Observer of Controller. From there the server will treat each person viewing the webpage differently based on how the user was tagged.
My original plan was to use a really light weight database like SQLite, but as I found out, SQLite is local use only. I need to do this on a sever with lower then 10 connections.
My hope is someone has a suggestion, or an example to solve this problem.
The most common way for javascript running on a web page to talk to a server these days is some kind of RESTful web service.
You'll want to find a server-side programming language that runs on the Pi. Maybe node.js? It's like javascript but on a server, see here: http://weworkweplay.com/play/raspberry-pi-nodejs/
You then write whatever methods you want in the server-side language, methods which talk to the database, then have your client-side javascript call those methods. Google "REST services node.js" and you'll find plenty of how-tos.
If the SQLite database is running on the server, and this code runs in the user's browser, it can't connect to the database. The only interaction between the browser and your server is HTTP, unless there's a gigantic security hole in your server.

Javascript: DLNA client

I am planning to write a DLNA (upnp) client in javascript. I would like to know if this is possible in the first place or not.
If yes, then where can do I start? What do I need to know to begin? Links to any documentation and tutorials will be highly appreciated. I've tried Googling, but didn't come across much helpful content.
I just need a prod in the right direction.
Thanks! :)
The best place for you to start is the UPnP device architecture doc in the docs bundle from the UPnP forum. This splits the protocol into a number of areas:
Discovery. This requires the ability to send multicast UDP packets and receive unicast UDP. You cannot do this from JavaScript so would require a native helper app to cover this portion if you want to search a network and offer to control any devices found on it. Alternatively, you can skip this section if you somehow already know the address of your target device.
Description. Given an address for a device, fetch (http get) an xml overview of its capabilities. You can do this easily from JavaScript.
Control. Instruct a given device to carry out given actions. Implemented using http post and soap. You can do this easily from JavaScript.
Eventing. A mechanism to be informed of changes in device state. Requires that you run a tcp server so cannot be done from JavaScript. Fortunately, this is often optional as most device services are designed to allow clients to poll state getters as an alternative to eventing. So, you can do this from JavaScript, albeit that your app will be less efficient than a native one.
Presentation. Some devices provide a web app allowing their control. This is hosted in a browser so will use JavaScript and is a good example that the sort of control app you want to write is possible.
In summary then, a JavaScript UPnP client is possible only if you can use native code to handle device discovery. If you decide to try this, open source UPnP stacks exist to handle most of the work of discovery for you.
Take a look at Plug.Play.js - A JavaScript API for communicating with Universal Plug and Play (UPnP) Services obtained via the W3C Network Service Discovery API
https://github.com/rexboy7/plug.play.js
And ssdp.js - (Simple Service Discovery Protocol) A Network Service Discovery API implementation based on the W3C Raw Socket API
https://github.com/schien/ssdp.js
And here is a sample implementation of a DLNA client using the above: https://github.com/mozilla-b2g/gaia/tree/master/tv_apps/dlna-player
EDIT: Based on Firefox OS.
Looking around about this topic and based on André Fiedler answer I found that the libraries he posted about resides on UDPSocket from MDN webarchive.
In the main page you can see the discovery example:
var SSDP_PORT = 1900;
var SSDP_ADDRESS = "239.255.255.250";
var SSDP_DISCOVER_MX = 2;
var SEARCH_TARGET = "urn:schemas-upnp-org:service:ContentDirectory:1";
var SSDP_DISCOVER_PACKET =
"M-SEARCH * HTTP/1.1\r\n" +
"HOST: " + SSDP_ADDRESS + ":" + SSDP_PORT + "\r\n" +
"MAN: \"ssdp:discover\"\r\n" +
"MX: " + SSDP_DISCOVER_MX + "\r\n" +
"ST: " + SEARCH_TARGET + "\r\n" +
"\r\n";
var searchSocket = new UDPSocket({
loopback: true
});
searchSocket.joinMulticastGroup(SSDP_ADDRESS);
searchSocket.onmessage = function (e) {
var msg = String.fromCharCode.apply(null, new Uint8Array(e.data));
console.log(msg);
};
searchSocket.opened.then(function() {
searchSocket.send(SSDP_DISCOVER_PACKET, SSDP_ADDRESS, SSDP_PORT);
setTimeout(function () { searchSocket.close(); }, SSDP_DISCOVER_MX * 1000);
});

Node.js - Is this a good structure for frequently updated content?

As a follow-up to my question yesterday about Node.js and communicating with clients, I'm trying to understand how the following would work.
Case:
So, I have this website where content is updated very frequently. Let's assume this time, this content is a list of locations with temperatures. (yes, a weather service)
Now, every time a client checks for a certain location, he or she goes to a url like this: example.com/location/id where id corresponds to the id of the location in my database.
Implementation:
At the server, checktemps.js loops (every other second or so) through all the locations in my (mySQL) database and checks for the corresponding temperature. It then stores this data is an array within checktemps.js. Because temperatures can change all the time, it's important to keep checking for updates in the database.
When a request to example.com/location/id is made, checktemps.js looks into the array with a record with id = id. Then, it responds with the corresponding temperature.
Question:
Plain text, html or an ajax call is not relevant at the moment. I'm just curious if I have this right? Node.js is a rather unusual thing to get a grasp on, so I try to figure out if this is logical?
At the server, checktemps.js loops
(every other second or so) through all
the locations in my (mySQL) database
and checks for the corresponding
temperature. It then stores this data
is an array within checktemps.js
This is extremely inefficient. You should not be doing looping(every other second or so).
Modules
Below I would try and make a list of the modules(both node.js modules as other modules) I would use to do this efficient:
npm is a package manager for node. You can use it to install and publish your node
programs. It manages dependencies and does other cool stuff.
I hope sincerely that you already know about npm, if not i recommend you to learn about it as soon as possible. In the beginning you just need to learn how to install packages, but that is very easy. You just need to type npm install <package-name>. Later I would really like to advice you to learn to write your own packages to manage the dependencies for you.
Express is a High performance, high class web development for Node.js.
This sinatra-style framework from TJ is really sweet and you should read the documentation/screencasts available to learn it's power.
Socket.IO aims to make realtime apps possible in every browser and
mobile device, blurring the
differences between the different
transport mechanisms.
Redis is an open source, advanced
key-value store. It is often referred
to as a data structure server since
keys can contain strings, hashes,
lists, sets and sorted sets.
Like Raynos said this extremely fast/sexy database has pubsub semantics, which are needed to do your question efficiently. I think you should really play with this database(tutorial) to appreciate it's raw power. Installing is easy as pie: make install
Node_redis is a complete Redis client for node.js. It supports all Redis commands, including MULTI, WATCH, and PUBLISH/SUBSCRIBE.
Prototype
I just remembered I helped another user out in the past with a question about pubsub. I think when you look at that answer you will have a better understanding how to do it correctly. The code has been posted a while back and should be updated(minor changes in express) to:
var PORT = 3000,
HOST = 'localhost',
express = require('express'),
io = require('socket.io'),
redis = require('redis'),
app = module.exports = express.createServer(),
socket = null;
app.use(express.static(__dirname + '/public'));
if (!module.parent) {
app.listen(PORT, HOST);
console.log("Express server listening on port %d", app.address().port)
socket = io.listen(app);
socket.on('connection', function(client) {
var subscribe = redis.createClient();
subscribe.subscribe('pubsub'); // listen to messages from channel pubsub
subscribe.on("message", function(channel, message) {
client.send(message);
});
client.on('message', function(msg) {
});
client.on('disconnect', function() {
subscribe.quit();
});
});
}
I have compressed the updated code with all the dependencies inside, but you while still need to start redis first.
Questions
I hope this gives you an idea how to do this.
With node.js you could do it even better. The request/response thingy is manifested in our heads since the beginning of the web. But you can do just one ajax request if you open the website/app and never end this call. Now node.js can send data whenever you have updates to the client. Search on youtube for Introduction to Node.js with Ryan Dahl (the creator of node.js), there he explains it. Then you have realtime updates without having to do requests by the client all the time.

Categories