Using Plotly.js and Node.js to get and plot data - javascript

I'm trying to create a simple webpage which gets data from a microcontroller (MSP432) and plots it on a graph in real time.
I have researched and I'm currently using plotly.js and html to create the graph. I currently have a graph that updates itself with random data in realtime.
I have attached the code for the page below.
I now want to stream the data in, and I have looked at node.js and in particular the serialport library. I think I have installed the serialport npm.
The part where I'm confused is how does the node.js code fit in with my html/plotlyjs index file?
I have never used javascript before. It's my first time with nodejs especially, so I'm confused. Should I just put it inside the <script> tag right in the getX() getY() function?
Also does anyone know how I can go about starting the nodejs code? I'm kind of lost.
This is my index.html file:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="plotly.min.js"></script>
<meta charset="utf-8" />
<title>My Plot Page</title>
</head>
<body>
<p>Plotly plot:</p>
<div id="chart1"></div>
<script>
var counter = 0;
function getX() {
counter++;
return counter;
}
function getY() {
return Math.random();
}
Plotly.plot('chart1', [{
x: [getX()],
y: [getY()],
type: 'line'
}]);
setInterval(function () {
Plotly.extendTraces('chart1', { x: [[getX()]] , y: [[getY()]] }, [0])
}, 200);
</script>
</body>
</html>

Node.js is an open source server environment. It is used to host a webserver and can't be run inside the webbrowser. It can be used to read serial port data and send it to the connected clients.
An example setup would be as below:
---------------------------------------------------------------------------
| MSP432 node.js server web page in browser |
| M <==================> N <===========================> W |
| serial websockets |
---------------------------------------------------------------------------
The nodejs server (N) reads the data from the serial port and manages the MSP432 (M). The server (N) also hosts a webserver (using expressjs) and opens a websocket with the connected webpage (W) to transfer new data. An easy to use websocket library is socket.io.
A simple nodejs webserver can be created by doing:
express --view=pug <your application name>
please note that ejs can also be used instead of pug
ajax can also be used instead of websockets

From experience (I work with data visualization systems), I can tell you Plotly might not be the easiest way to plot real-time data. It can do it for sure, but what it does is re-render the whole plot for every new point, which considering the data structure is not the most efficient method and looks a bit unnatural when updating.
In your use case, I would recommend this plugin instead: http://smoothiecharts.org/ it's lightweight, free, and "smooth". Read the "10 minute tutorial" on their website and you're good to go.
Summarizing, to each smoothiecharts timeseries, you want to use the append() method to add each new data sample. You can call this using a setTimeInterval() JavaScript method to get the value from... a URL (making an AJAX GET request). You want to create a URL that will always return the latest reading from your sensor, and for this you'll need to create a local webserver.
This is where your NodeJS application fits in: Create a simple NodeJS server with a GET method that returns the latest reading from your device. Something like this is enough to return simple content like a number: https://www.tutorialspoint.com/nodejs/nodejs_first_application , you could print a random number first and work on it until it works before continuing.
The hardest part here though is to get your microcontroller's readings into the NodeJS application. I don't know the specifics of the MSP432 or how you're connecting to it, but usually you can write a C script that reads the latest value from it and prints it to the console.
If you manage to do this, you can use the following NodeJS code to execute your C program and read its console output:
var exec = require('child_process').execFile;
var path = 'c:\yourprogram.exe';
var fun = function() {
exec(path, function(err, data) {
console.log(err)
console.log(data.toString());
});
}
fun();
You can easily tweak that code into a function that updates the NodeJS variable that your server returns, and run it in a loop every X milliseconds.
And that would be your full visualization system.

Related

Retrieve part of json file from an external website (sparkfun)

This question might be quite specific to sparkfun, but I still wish to make it as a general question due to my limited experience in javascript.
I have been using the follow html and javascript (d3.js) file to load json data from sparkfun data server:
index.html
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data_sensor;
var url = "https://data.sparkfun.com/output/w5nEnw974mswgrx0ALOE.json"
d3.json(url, function (error,json) {
if (error) throw error;
data_sensor=json;
console.log(data_sensor)
})
</script>
</body>
After running the script, i will end up with all data array stored in variable data_sensor for post-analyse.
What i wish to do now is to create a dash board that downloads and stores only the latest value. i understand that i could just use the first value in the data_sensor to do so (i.e., data_sensor[0]) but such method becomes quite inefficient with the growth of data.
Thanks!
When I've wanted to load JSON from somewhere I've always used jQuery:
Import jQuery like this:
<script src="jquery-3.2.1.min.js"></script>
Then you can do something like this to get your JSON file:
var data_sensor;
var url = "https://data.sparkfun.com/output/w5nEnw974mswgrx0ALOE.json"
$.getJSON(url, function(data) {
data_sensor = data;
console.log(data_sensor)
});
Hope that helps!
Not an expert here, but their docs state tat you can use paging to get the first 250kb of data:
var url = "https://data.sparkfun.com/output/w5nEnw974mswgrx0ALOE.json?page=1";
You can get your first object/set of data, and I'm afraid there's no general way to take only part of any API response - request is request, it could send you every possible data depending on architecture, from "OK" string to 200MB of data. Carefully reading docs is your best bet.

Display arduino serial data on a web browser via python

I'm looking to get serial data from Arduino displayed from a web browser.
First, I put the data on a local host using bottle in python in json format
from bottle import route, run
import serial
dic = {}
ser = serial.Serial(port='COM6',baudrate=9600,timeout=None)
#route('/test')
def test():
c = ser.readline()
c = (str(c)[2:-5]) #just to get rid of the extra characters
dic["val"] = c
return(dic)
run(host='localhost', port=8080, debug=True)
Then I proceed to read it using javascript
function getArduinoVals(){
$.getJSON("http://localhost:8080/test", function(data){
$('#vals').html(data.val);
});
t = setTimeout("getArduinoVals()",50);
});
}
getArduinoVals();
however, it doesn't seem to load from local host (I tested other URLs). How should I fix this? Thanks!
You could use p5.serialport of p5.js for getting the serial data on the web browser. But you have to run the node server in the back.
https://github.com/vanevery/p5.serialport
You should check the github repo for getting started with p5.serialport.
p5.js is very similar to arduino code style so it's easier and convenient than python.

res.sendfile in Node Express with passing data along

Is there any way to redirect to an HTML file from a Node.JS application with something like: res.sendFile of express and pass a JSON data along to the html file?
I know this is late but I wanted to offer a solution which no one else has provided. This solution allows a file to be streamed to the response while still allowing you to modify the contents without needing a templating engine or buffering the entire file into memory.
Skip to the bottom if you don't care about "why"
Let me first describe why res.sendFile is so desirable for those who don't know. Since Node is single threaded, it works by performing lots and lots of very small tasks in succession - this includes reading from the file system and replying to an http request. At no point in time does Node just stop what it's doing and read an entire from the file system. It will read a little, do something else, read a little more, do something else. The same goes for replying to an http request and most other operations in Node (unless you explicitly use the sync version of an operation - such as readFileSync - don't do that if you can help it, seriously, don't - it's selfish).
Consider a scenario where 10 users make a request for for the same file. The inefficient thing to do would be to load the entire file into memory and then send the file using res.send(). Even though it's the same file, the file would be loaded into memory 10 separate times before being sent to the browser. The garbage collector would then need to clean up this mess after each request. The code would be innocently written like this:
app.use('/index.html', (req, res) => {
fs.readFile('../public/index.html', (err, data) => {
res.send(data.toString());
});
});
That seems right, and it works, but it's terribly inefficient. Since we know that Node does things in small chunks, the best thing to do would be to send the small chunks of data to the browser as they are being read from the file system. The chunks are never stored in memory and your server can now handle orders of magnitude more traffic. This concept is called streaming, and it's what res.sendFile does - it streams the file directly to the user from the file system and keeps the memory free for more important things. Here's how it looks if you were to do it manually:
app.use('/index.html', (req, res) => {
fs.createReadStream('../public/index.html')
.pipe(res);
});
Solution
If you would like to continue streaming a file to the user while making slight modifications to it, then this solution is for you. Please note, this is not a replacement for a templating engine but should rather be used to make small changes to a file as it is being streamed. The code below will append a small script tag with data to the body of an HTML page. It also shows how to prepend or append content to an http response stream:
NOTE: as mentioned in the comments, the original solution could have an edge case where this would fail. For fix this, I have added the new-line package to ensure data chunks are emitted at new lines.
const Transform = require('stream').Transform;
const parser = new Transform();
const newLineStream = require('new-line');
parser._transform = function(data, encoding, done) {
let str = data.toString();
str = str.replace('<html>', '<!-- Begin stream -->\n<html>');
str = str.replace('</body>', '<script>var data = {"foo": "bar"};</script>\n</body>\n<!-- End stream -->');
this.push(str);
done();
};
// app creation code removed for brevity
app.use('/index.html', (req, res) => {
fs
.createReadStream('../public/index.html')
.pipe(newLineStream())
.pipe(parser)
.pipe(res);
});
You get one response from a given request. You can either combine multiple things into one response or require the client to make separate requests to get separate things.
If what you're trying to do is to take an HTML file and modify it by inserting some JSON into it, then you can't use just res.sendFile() because that just reads a file from disk or cache and directly streams it as the response, offering no opportunity to modify it.
The more common way of doing this is to use a template system that lets you insert things into an HTML file (usually replacing special tags with your own data). There are literally hundreds of template systems and many that support node.js. Common choices for node.js are Jade (Pug), Handlebars, Ember, Dust, EJS, Mustache.
Or, if you really wanted to do so, you could read the HTML file into memory, use some sort of .replace() operation on it to insert your own data and then res.send() the resulting changed file.
Well, it's kinda old, but I didn't see any sufficient answer, except for "why not". You DO have way to pass parameters IN static file. And that's quite easy. Consider following code on your origin (using express):
let data = fs.readFileSync('yourPage.html', 'utf8');
if(data)
res.send(data.replace('param1Place','uniqueData'));
//else - 404
Now for example, just set a cookie, in yourPage.html, something like:
<script>
var date = new Date();
document.cookie = "yourCookieName='param1Place';" +
date.setTime(date.getTime() + 3600) + ";path=/";
</script>
And you can plainly pull content of uniqueData from yourCookieName wherever you want in your js
I think the answer posted by Ryan Wheale is the best solution if you actually want to modify something within an HTML file. You could also use cheerio for working with complex logic.
But in regards to this particular question where we just want to pass some data to the client from the server, there's actually no need to read index.html into memory at all.
You can simply add the following script tag somewhere at the top of your HTML file:
<script src="data.js"></script>
And then let Express serve that file with whatever data needed:
app.get("/data.js", function (req, res) {
res.send('window.SERVER_DATA={"some":"thing"}');
});
This data can then easily be referenced anywhere in your client application using the window object as: window.SERVER_DATA.some
Additional context for a React frontend:
This approach is especially useful during development if your client and server are running on different ports such as in the case of create-react-app because the proxied server can always respond to the request for data.js but when you're inserting something into index.html using Express then you always need to have your production build of index.html ready before inserting any data into it.
Why not just read the file, apply transformations and then set up the route in the callback?
fs.readFile(appPath, (err, html) => {
let htmlPlusData = html.toString().replace("DATA", JSON.stringify(data));
app.get('/', (req, res) => {
res.send(htmlPlusData);
});
});
Note that you can't dynamically change data, you'd have to restart the node instance.
You only have one response you can return from the server. The most common thing to do would be to template your file on the server with nunjucks or jade. Another choice is to render the file on the client and then to use javascript to make an ajax call to the server to get additional data. I suppose you could also set some data in a cookie and then read that on the client side via javascript as well.
(Unless you want to template the html file to insert the json data into a script tag). You'll need to expose an api endpoint in express the send along the data to the page, and have a function on the page to access it. for example,
// send the html
app.get('/', (req, res) => res.sendFile('index'));
// send json data
app.get('/data', (req, res) => res.json(data));
Now on the client side you can create a request to access this endpoint
function get() {
return new Promise((resolve, reject) => {
var req = new XMLHttpRequest();
req.open('GET', '/data');
req.onload = () => resolve(req.response);
});
}
// then to get the data, call the function
get().then((data) => {
var parsed = JSON.parse(data);
// do something with the data
});
EDIT:
So arrow functions probably don't work client side yet. make sure to replace them with function(){} in your real code
This is pretty easy to do using cookies. Simply do this:
On the server side -
response.append('Set-Cookie', 'LandingPage=' + landingPageCode);
response.sendFile(__dirname + '/mobileapps.html');
On client side -
<!DOCTYPE html>
<html>
<body onload="showDeferredLandingPageCode()">
<h2>Universal Link Mobile Apps Page</h2>
<p>This html page is used to demostrate deferred deeplinking with iOS</p>
</body>
<script language="javascript">
function showDeferredLandingPageCode() {
alert(document.cookie);
}
</script>
</html>

Output data from TaffyDB

I'm new to JavaScript and am trying to build a script that performs some data management activities(Basically query based data fetching from a database and then displaying it on a webpage).
I generally would do this on the server side with PHP and mysql but my boss want's to see a "sample" before investing in servers etc. (He has no technical knowledge regarding PHP,MySQL etc)
Now without a server I was looking for a way to build a similar system on the client side mostly via javascript. Just to demonstrate the logic I plan on implementing.
For the database part I decided to use TaffyDB, however am having issues getting an output from the database(Display the data on a webpage)
Here's my code
<!DOCTYPE html>
<html>
<head>
<script src="taffydb-master\taffy.js"></script>
<script>
var companies = TAFFY
([
{name:"New York",state:"WA"},
{name:"New Shire",state:"WE"},
{name:"Las Vegas",state:"NV"},
{name:"Boston",state:"MA"}
]);
var cities = new Array();
var cities = companies().select("name");
</script>
</head>
<body>
<script>
document.write = (cities[1]);
</script>
</body>
</html>
I know there's some silly mistake in there but really can't find it. I tried using the developer's tools (Mozilla's default one) but it returns no issues. I basically just get a blank white page when I load this file.
You are using document.write incorrectly. It is a method.
If you change your code to:
<script>
document.write(cities[1]);
</script>
then you will get this output:
New Shire
Also, you should probably wrap the output in some element like so:
<script>
document.write("<p>" + cities[1] + "</p>");
</script>

connecting an web api controller to an html page to display an image

I am new to the web development world and the steps of creating an interaction between a web api and an html page
I found this tutorial but I really don t know how to make a connection to my controller
I have a function that takes a bunch of parameters (strings , ints , bools , etc...)and it returns an Image (type Bitmap) . the function should take these parameters from the HTML page
so I need to do something similar to this in a javascript function:
function()
{
img = mywebapifunction(x,y,z,...);
}
how can I connect the controller to my page and how to write this function ?
EDIT :
I am using the following script (If I understand correctly):
<script src="../../Scripts/jquery-1.7.1.min.js"
type="text/javascript"></script>
Thanks!
So it was even easier than I thought!!!
the code should be as follows :
function()
{
$("#img").attr("src", myapicallstring);
}
where
myapicallstring calls the api function

Categories