socket emit an event on http PUT - express

I am using expressjs, nedb, and socket.io. Various (non-browser) clients are able to PUT new values into the db successfully. When that happens, I want a message emitted to all browsers connected to the server. I have the following code which is currently not sending a message back to the browser.
// on the server
//***************************************************************
// reachable to the world at http://server/foo
// clients can PUT data into the db
app.put('/foo', jsonParser, function(req, res, next) {
if (!req.body) return res.sendStatus(400);
db.insert(req.body, function (err, newDoc) {
io.sockets.emit('PUT a new value', { added: newDoc._id });
res.send('Success! Find it again with id: ' + newDoc._id);
});
});
// reachable to the world at http://server/
// browser shows a dashboard of events
app.get('/', function(req, res, next) {
// code to serve the dashboard here
});
io.sockets.on('connection', function (socket) {
socket.on('foo', function (data) {
io.sockets.emit('PUT a new value', data);
})
});
// in the browser
//***************************************************************
var socket = io.connect('/');
socket.on('PUT a new value', function (data) {
console.log(data);
});
Data get inserted into the db successfully from different non-browser clients, but the connected browser doesn't receive an update.
What am I doing wrong?

I found a solution which I don't like at all but it works. We can add io object to req or to res in the middleware like that:
app.use(function (req, res, next) {
req.io = io;
next();
});
before app.use('/', routes) and then in our router module we "import" the io object:
app.put('/foo', jsonParser, function(req, res, next) {
if (!req.body) return res.sendStatus(400);
db.insert(req.body, function (err, newDoc) {
var io = req.io; // HERE !!!
io.sockets.emit('PUT a new value', { added: newDoc._id });
res.send('Success! Find it again with id: ' + newDoc._id);
});
});
I know, I know... let's find something else :-)

I have the following app structure generated by express generator. I start the app with $ DEBUG=foo:* npm start
.
|____app.js
|____bin
| |____www
|____data
|____LICENSE
|____node_modules
|____package.json
|____public
| |____stylesheets
| |____javascripts
| |____images
|____README.md
|____routes
| |____index.js
| |____readings.js
| |____sensors.js
| |____users.js
|____views
| |____error.hjs
| |____index.hjs
In app.js
var express = require('express');
var app = express();
var io = require('socket.io')();
app.io = io;
// notice the `(io)` for the routes that need to be socket-aware
var routes = require('./routes/index');
var users = require('./routes/users');
var sensors = require('./routes/sensors');
var readings = require('./routes/readings')(io);
…
// start listening with socket.io
app.io.on('connection', function(socket){
console.log('a user connected');
});
module.exports = app;
Then in ./routes/readings.js
var express = require('express');
var app = express();
var router = express.Router();
module.exports = function(io) {
router.put('/', jsonParser, function(req, res, next) {
if (!req.body) return res.sendStatus(400);
db.insert(req.body, function (err, newDoc) {
io.emit("reading", {id: newDoc._id});
res.send('Success PUTting data! id: ' + newDoc._id);
});
});
return router;
}
Finally, in the index.hjs template for the client-side
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('reading', function (data) {
console.log(data);
});
</script>
The above works. When data are inserted into the db via an http PUT (see readings.js), an event is emitted by io.emit('reading', data) and the browser receives that event and shows it in the console with socket.on('reading', function (data) { … });

Related

send serial port data to front-end with express & node

I want to send serial port data to a browser UI with express. So far my code looks like this:
var SerialPort = require("serialport");
var serialport = new SerialPort("/dev/cu.usbmodem1421");
var express = require('express');
var app = express();
var datenFromA;
serialport.on('open', function(){
console.log('Serial Port Opend');
serialport.on('data', function(data){
datenFromA = data[0];
console.log(datenFromA);
});
});
app.get('/', function (req, res) {
res.send('Hello World')
})
app.listen(3000);
Instead of the 'Hello World' I want to send the value of variable datenFromA to the browser. Any ideas how to pass the value to the app.get function?
Thanks in advance.
Essentially you need to wait until you receive an event. Quick dirty example given below:
const SerialPort = require("serialport");
const serialport = new SerialPort("/dev/cu.usbmodem1421");
const express = require('express');
const app = express();
// Only need to do this once.
serialport.on('open', () => console.log('Serial Port Opend'));
app.get('/', async (req, res) => {
const promise = new Promise((resolve, reject) => {
serialport.on('data', (data, err) => {
if (err) {
reject(err);
return;
}
resolve(data[0]);
});
})
const data = await promise;
res.json(data);
})
app.listen(3000);

Not getting any response for save

Whenever I request on 8081/list_user there is no response. When I open localhost:8081 I get a response but not for localhost:8081/list_user.Both files are in the same folder is there any issues with that.Please check this issue what's problem in that.
// grab the things we need schema.js file
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// create a schema
var userSchema = new Schema({
name: String,
});
// the schema is useless so far
// we need to create a model using it
var User = mongoose.model('User', userSchema);
// make this available to our users in our Node applications
console.log("Schema")
module.exports = User;
////////////Next file
var express = require('express');
var app = express();
var User = require('./schema');
// This responds with "Hello World" on the homepage
app.get('/', function (req, res) {
console.log("Got a GET request for the homepage",User);
res.send('Hello GET');
})
// This responds a POST request for the homepage
app.post('/', function (req, res) {
console.log("Got a POST request for the homepage");
res.send('Hello POST');
})
// This responds a DELETE request for the /del_user page.
app.delete('/del_user', function (req, res) {
console.log("Got a DELETE request for /del_user");
res.send('Hello DELETE');
})
// This responds a GET request for the /list_user page.
app.get('/list_user', function (req, res) {
console.log("Got a GET request for /list_user");
var newUser = User({
name: 'Peter Quill',
});
// save the user
newUser.save(function(err) {
if (err) throw err;
res.send('User created!');
console.log('User created!');
});
})
// This responds a GET request for abcd, abxcd, ab123cd, and so on
app.get('/find', function(req, res) {
User.find({}, function(err, users) {
if (err) throw err;
// object of all the users
console.log(users);
res.send(users)
});
})
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
})
When I tested .save function the way it was I couldn't even get an error message. What I did was add a connection with my local database (at schema file) to test properly.
mongoose.connect('mongodb://localhost/test');
In order to do this, first you have to certify that you have a local mongodb server running (or you could just connect to an online server), mongoose.connect receives my connection string as parameter ("test" is the database name, if it doesn't exist it will be created automatically). Last thing I did was add new when I create an user.
var newUser = new User({
name: 'teste',
});

How to send a redis object from app.js to html <div>?

I am building a quick Express JS application. I have sent data to Redis from another application.
I did an LPUSH. I was able to do this:
client.lrange('stash', 0, 10, function(err, reply) {
console.log(reply);
});
My goal is to, instead of doing a console.log("..."), I want to send it to a in my index.html.
Any ideas on how to do this?
EDIT: Here is my app.js file:
var express = require('express');
var redis = require('redis');
var app = express();
app.use(express.static('public')); //used to get image
app.engine('html', require('ejs').renderFile); //ejs, not handlebars
function index(req,res, next) {
testController.index(req, res, next);
}
app.get('/', function(req, res){
res.render('index.html');
});
app.get('*', function(req, res){
res.render('404.html');
});
//redis stuff
var client = redis.createClient();
client.on('connect', function() {
console.log('connected');
});
client.lrange('stash', 0, 10, function(err, reply) {
console.log(reply); //instead of this, let's place that into a div
});
//end redis
app.listen(3000, function(){
console.log('My example app is now running! (3000)')
});
from my understanding you could use ejs to plug in data directly into your html. The problem of course is that I don't know how client.lrange works but I know that express reads middleware top to bottom. If lrange is pulling data you need from the db you can save the data to a global var data and on a call to the endpoint of the html you want updated; render it with ejs.
create a place holder for the data
var data;
pull the data from server and save globally
client.lrange('stash', 0, 10, function(err, reply) {
data = reply;
});
render html page with ejs using ejs tags
app.get('/', function(req, res) {
res.render('index.html', {reddisData: data});
});
plug it into your html
<a>
<%= reddisData %>
</a>
all together
var express = require('express');
var path = require('path');
app = express()
app.engine('html', require('ejs').renderFile);
app.set('html', 'ejs');
var data;
client.lrange('stash', 0, 10, function(err, reply) {
data = reply;
});
app.get('/', function(req, res) {
res.render('index.html', {reddisData: data});
});
Hope this helps, if it doesn't work for you the idea is what counts. Look into using ejs to resolve your problem.

Express.js, req.params not being called

So i have been racking my brain for quite awhile now trying to figure this out and I'm still having issues.
So i define a route like this:
var home = require('./routes/home');
var app = express();
app.use('/home/:client', home);
And my home.js code looks like this:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('homeview', { title: 'Welcome',
user: username});
});
router.get('/:client', function(req, res, next) {
var theClient = req.params.client;
console.log(theClient)
});
module.exports = router;
And then when i try to go to this URL:
http://www.localhost:3000/home/client
Nothing happens. For some reason it never gets to the second router.get and never logs anything. Anyone notice whats wrong?
Working solution # https://github.com/rmjoia/expressRoutes
app.js
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
homeRouter = require('./home');
app.use('/home', homeRouter);
app.route('/')
.all(function (request, response, next) {
// Do some plumbing stuff
next();
})
.get(function (request, response, next) {
response.send('OK GET - Hello Stack Overflow');
next();
});
app.listen(port, function (error) {
if (error) {
console.error(error.message);
}
else {
console.info('Server up and running. Listening on port ' + port);
}
})
home.js
var express = require('express');
var homeRouter = express.Router();
var router = (function (router) {
// define the home page route
router.get('/', function (req, res) {
res.send('home route - homepage');
});
// define the about route
router.get('/:client', function (req, res) {
res.send(req.params.client);
});
return homeRouter;
})(homeRouter);
module.exports = router;

Defaulting route to /api/:version in MEANJS

I am relatively new to MEANJS, i have also been reading through its documentation to learn more.
so, i am trying to create a rest API using meanjs using its yo generator and removing the angular parts of it, so far it has been a success.
What i am trying to do now is to default the url routes to have a prefix of /api/:version, what i did so far is to append the /api/:version to the routes inside app/ like the following
//app/routes/articles.server.routes.js
'use strict';
...
module.exports = function(app) {
// Article Routes
app.route('/api/:version/articles')
...
app.route('/api/:version/articles/:articleId')
...
// Finish by binding the article middleware
app.param('articleId', articles.articleByID);
};
That works so far, but can i declared this somewhere so that i don't have to add /api/:version every time i create a new route?
I tried implementing the ones stated in express documentation and Remi M's answer in this stackoverflow question with no luck.
Update
meanjs installation comes with an express.js, so i thought that this is the right place to do it and i tried using the router object to solve this problem, although it doesn't work
//config/express.js
'use strict';
...
var express = require('express');
...
var router = express.Router();
module.exports = function(db) {
var app = express();
...
app.use(function(req, res, next) {
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
next();
});
app.use(compress({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
...
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
app.use(function(err, req, res, next) {
if (!err) return next();
console.error(err.stack);
res.status(500).render('500', {
error: err.stack
});
});
app.use(function(req, res) {
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found'
});
});
...
app.use('/api/:version', router); //this is what i add
return app;
};
All of your initial configurations should be on router object and not on app For Ex :
'use strict';
var express = require('express');
var router = express.Router();
module.exports = function(db) {
var app = express();
router.use(function(req, res, next) {
res.locals.url = req.protocol + '://' + req.headers.host + req.url;
next();
});
router.use(compress({
filter: function(req, res) {
return (/json|text|javascript|css/).test(res.getHeader('Content-Type'));
},
level: 9
}));
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(router);
});
router.use(function(err, req, res, next) {
if (!err) return next();
console.error(err.stack);
res.status(500).render('500', {
error: err.stack
});
});
router.use('/bar', function(req, res, next) {
console.log("bar endpoint called");
res.send("bar");
});
router.use(function(req, res) {
res.status(404).render('404', {
url: req.originalUrl,
error: 'Not Found'
});
});
app.use('/api/:version/', router); //this is what i add
return app;
};
Then call app.use("prefixurl",router) as above.
test the BAR API /api/v1/bar