This is my first post on stackoverflow so pls forgive me if I'm making post taht already existis. I'm kinda new into HTML and .js, "know basics guy".
I have a mobile app on tablet that has kisok mode browser and I'm using it to connect to my NodeJS Server on RPI (works). I have a lot of HTML's and .js files already in my project.
What I'm trying to find out:
Is it possible to make new seperate HTML or .js file that would do something like remote control with my tablet to server. Example - When I click a button taht same button is clicked on browser on RPI beacuse I have another seperate display on RPI that show same thing and I would use my tablet only as a getter of HTML (so I can show it on tablet) and input method for RPI. (simultaneously on both display but use tablet as input)
Or update all existing HTML and .js on server side (harder way, if this thing is even posbile to do)
Thank you very much for further help!
EXtra edit - code
Here is the server side code!
//var app = require('http').createServer(handler);
//var express = require("express")();
var express = require("express");
//var app = require("express")();
var app = express();
var http = require("http").Server(app);
var path = require("path");
//var io = require('socket.io')(app);
var io = require('socket.io')(http);
var SerialPort = require('serialport');
//previous was app.listen(3000);
http.listen(3000);
//Enabling CORS - for specific localhost port
app.use(function (req, res, next){
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
function handler(req, res){
console.log(req, res);
}
var serialPort = new SerialPort.SerialPort("/dev/ttyAMA0", {
baudrate: 9600,
dataBits: 8,
parity: "none",
stopBits: 1,
flowControl: false
});
var counter = 0;
serialPort.on("open", function () {
console.log("open");
var service = new Service();
serialPort.on("data", function (data) {
var hexData = data.toString('hex');
console.log(data, hexData);
io.emit('hit', data);
});
});
io.on('connection', function(socket){
console.log('Connected');
//nsmrcek - custom code for accepting data from client side
socket.on("message1",function(data){
});
socket.on("message2",function(data){
});
socket.on("message3",function(data){
});
socket.on("message4", function(data){
});
socket.on("message5", function(data){
});
});
app.use(express.static(path.join(__dirname, '/')));
//app.use('/js', express.static(path.join(__dirname,
app.get("/home",function(req,res,next){
//res.send("OK");
//if fails path incorrect
res.sendFile(path.join(__dirname + "/index.html"));
//res.render("index.html");
});
function Service() {
this.mapCodeToHit = function (data) {
"data send from little homemade CPU board via serial port to RPI server" }
I hope this is enough code so You can instruct me where to put more code to simulate click on evry other client while clicking button on one of the clients (alawys 2 clients)
If you created a websocket connection that ran through your server and pushed the updated state of the button to the connected clients this would certainly be possible. I can't give a detailed answer without seeing your code but you could start with the socket.io docs here and ask more questions as you get started.
http://socket.io/
Related
I'm must say I'm very new to back end development,
I'm currently working on an exercise project of making a fake money poker website. I use Node.js socket.io/express-session/passport
At first, I mainly used express with a HTTP server listening on one port. Averagely Like this:
const express = require("express")
const app = express()
app.get('/home',connectEnsureLogin.ensureLoggedIn("/loginPage"),function(req, res) {
//console.log(req.user.username+": sessionId: "+req.sessionID);
return res.sendFile( __dirname+"/website/index.html");
}
);
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log("Poker site Server started on ${PORT})")
The website wasn't working very fast. When a client joined a poker table they needed to ask the server every second for new updates on the state of the game so that was a lot of HTTP requests coming into my server. So I decided without much theoretical certitude that it seemed like a good idea: To have the server use socket.io sockets to hand info for clients that are in poker tables, but when they are not in poker tables and are just browsing the site I use a HTTP server to handle their request. Code wise I feel I haven't really managed to do this correctly. My code with Express, express-session, and passport combined makes sure only to hand information to users authenticated. But since The socket.io servers seem totally separate from all the express code, they don't share the same authentication functionality as the express code. So I need to somehow link my express and socket.io code so I can check if a client is authenticated before handing him any info via sockets. here is the system I'm currently using I didn't put all my code but I tried to summarize the essential parts:
const express = require('express');
const app = express();
//i creat the http server that is somehow linked with my express app when this server is listening
//it will call express handling methods.
const http = require('http').Server(app);
const io = require('socket.io')(http);
const path = require("path");
const passport = require("passport");
const connectEnsureLogin = require('connect-ensure-login');
const AccountInfo = require("./AccountInfo").AcccountInfo;
const expressSession = require('express-session')({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false
});
//passport setup
passport.use(AccountInfo.createStrategy());
passport.serializeUser(AccountInfo.serializeUser());
passport.deserializeUser(AccountInfo.deserializeUser());
//body parser
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//Sessions
app.use(expressSession);
//!!!!here is where I connect socket.io with the sessions i found this in another forum.
// thanks to this code I can access the session that a client is using when their socket connects.
io.use(function(socket, next) {
expressSession(socket.request, socket.request.res, next);
});
//so when a clients socket connects i save his socket.id to his session.
io.on('connection',function(socket) {
console.log(`socket.io connected: ${socket.id}`);
// save socket.io socket in the session
socket.request.session.socketio = socket.id;
socket.request.session.save();
});
//once the clients socket is connected directly after the clients sends a HTTP "PUT" request
//and this code answers it.
app.post('/Table/ConnectSocketToTable',Utilities.ensureLoggedIn(),function(req, res)
{
//I retrieve the socket using the socket.id I had saved in the session.
let socket = io.sockets.sockets.get(req.session.socketio);
let player = GetPlayerFromAnyTable(req.user.username);
if(player==null)//the player can't be in two tables at once
{
//since now we are in an express callback, express made sure that the client is indeed
//authenticated with the middle-ware: "Utilities.ensureLoggedIn()" also just before I made sure
//the client is not in another table. So we are good to go we can now link the socket to the table
//and have the client receive all the info about the state of his table
socket.join("table-"+req.session.passport.table);
req.user.socket = socket;
let table = GetTable(req.session.passport.table);
table.sitPlayer(req.user);
}
else
{
//the player is already connected so we just update his socket to a new one
player.requestUnseat=false;
player.account.socket =io.sockets.sockets.get(req.session.socketio);
}
socket.on('chatMessage', function(data,time) {
socket.to("table-"+req.session.passport.table).emit("chatMessage",req.user.username,data,time);
console.log(`send chat message : ${data}`);
});
socket.on('disconnect', function() {
GetTable(req.session.passport.table).requestUnsitUsername(req.user.username);
console.log(req.user.username +" was disconnected so now requesting unsit");
});
console.log("the socket of "+req.user.username+" has being connected to table-"+req.session.passport.table);
return res.sendStatus(200);
});
So for me, the way I'm doing this seems pretty bad since "app.post('/Table/ConnectSocketToTable'...)" and "io.on('connection',...)" are two different request listening functions I feel I should probably just do everything in one.
So should I do all the checks in the "io.on('connection',...)" function and somehow manage to make sure the client is authenticated within the callback of io.on('connection',callback) ?
or should I find a way to make the socket connection happen in the initial HTTP call the client uses to join a table, which is what I initially wanted?
But really I'm kinda lost because I'm telling myself maybe I don't even need Express anymore and I should just use socket.io for everything. I seem to clearly lack the general understanding that would allow me to know what approach I should be going for so any help is welcome. I started doing this self-made exercise to get into server-side development but also if there is any other recommended exercise to start up with back-end development I'm definitely interested in hearing about it.
From random testing I found out how to authenticate to my express session from the socket code you don't actually have to do it in the callback of io.on('connection',callback) you just need to add a few more middleware functions like this:
//connecting express sessions
io.use(function(socket, next) {
expressSession(socket.request, socket.request.res, next);
});
//connecting passport
io.use(function(socket, next) {
passport.initialize()(socket.request, socket.request.res, next);
});
//connecting passport sessions
io.use(function(socket, next) {
passport.session()(socket.request, socket.request.res, next);
});
//check if client is authenticated returns error if authentication failed
io.use((socket, next) => {
console.log("started socket Connection");
if(!socket.request.isAuthenticated&&socket.request.isAuthenticated())
{
socket.request.session.socketio = socket.id;
socket.request.session.save();
console.log("table "+socket.request.session.passport.table);
console.log("user.username "+socket.request.user.username);
console.log(`is authentificated`);
next();
}
else
{
console.log(`failed socket connection`);
next(new Error("unauthorized"));
}
});```
I am using twitter streaming api & johnny-five with some other modules http , express& socket.io with arduino uno
My script is working fine in laptop. But my production will be on a tablet. I have two tablets and both are responding differently. On hp omni tablet i am receiving following error
Also i have arduino-uno connected on port COM3 but its shows device connected on COM1
As far as i know this error is caused when standard firmata is not uploded in arduino. I have uploaded this program and it work fine in laptop
On Acer Tablet i am not receiving any errors program starts perfectly fine without any issues but i am not receiving tweets with twitter streaming api
I have crossed checked many times it runs perfectly fine on laptop every time i run it but gives two different issues with the tablets
Here is the code i am using
var Twitter = require('twitter');
var five = require("johnny-five");
var express = require('express')
, app = express()
, http = require('http')
, server = http.createServer(app)
, io = require('socket.io').listen(server);
server.listen(8080);
// routing
app.use(express.static(__dirname + '/http'));
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', "http://"+req.headers.host+':80');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
next();
}
);
var client = new Twitter({
consumer_key: 'abc',
consumer_secret: 'abc',
access_token_key: 'abc',
access_token_secret: 'abc'
});
var board = new five.Board();
board.on("ready", function() {
this.pinMode(5, five.Pin.OUTPUT);
this.pinMode(10, five.Pin.INPUT);
//Ask to visit url
console.log("Visit http://localhost:8080");
var randomHashtag = Math.floor((Math.random() * 10000) +1);
var count = 0;//Initialize counter
io.sockets.on('connection', function (socket) {
console.log('Ready to recieve tweets');//Prints Message when Socket.io is ready to recieve tweets
io.emit('stream',{number:randomHashtag});//Send random no when socket initzilize
client.stream('statuses/filter', {track: '#tweetMe'}, function(stream) {
stream.on('data', function(tweet) {
if(tweet.text.search(randomHashtag) > 0){
count++;//Increment pending tweets
randomHashtag = Math.floor((Math.random() * 10000) +1);
io.emit('stream',{number:randomHashtag});
board.digitalWrite(5,1);
console.log(tweet.text);
}
else{
console.log("Tweet Without random No");
}
});
stream.on('error', function(error) {
throw error;
});
});
});
});
As you said it works perfectly fine with other devices and also managed to fix issue with other tablet the possible reason i can think of is corrupt installation of nodejs or other modules you are using
Try to clean re-installation of Nodejs and all modules. May be there is some problem in your modules not in your code.
Another reason you have following issue nodejs maintain two different version
both handle installing of modules a different way.
Use the same version you are using in your laptop.
I resolved issue with HP OMNI tablet by manually telling johnny-five on which port my arduino is connected as mentioned in OFFICIAL DOCUMENTATION
new five.Board({ port: "COM3" });//FOR WINDOWS ONLY
Also i had to reinstall all modules to make it work
(Still not working with Acer tablet though)
Ok, so I have my server.js
var express = require("express"),
app = express(),
bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(__dirname + '/'));
app.post('/message', function(req, res) {
var jsonData = req.body;
if (jsonData.hasOwnProperty('phone1')) {
console.log("Phone 1 is connected to", jsonData.phone1.connection,
"and has a downlink speed of", jsonData.phone1.dl, "Mbps");
} else
if (jsonData.hasOwnProperty('phone2')) {
console.log("Phone 2 is connected to", jsonData.phone2.connection,
"and has a downlink speed of", jsonData.phone2.dl, "Mbps");
}
});
var port = 1337;
app.listen(port);
console.log("Running at Port " + port);
and as you see I want to do stuff when the server gets something posted on /message. I can console.log stuff yes, but I want to change things on the web page this server is serving. The POST requests are coming from another server. This server only presents them.
How can I do that without having to update the page?
I'm also using AngularJS on the client side, so any way for the client side to pick up the JSON data would be nice.
I hope to present the data in my Highcharts gauges and charts but a simple text update on a page element (e.g. <p id="example">) will do just fine for an answer to this question.
I know I can get jquery to node but I still lack the window element to manipulate the presented data. NW.js might do exactly what I want, I haven't still tried it though, but I suspect there might be another solution to this problem.
If you want to push new content to the client (opposite flow to the client requesting data from the server), WebSockets are an option (see http://socket.io/ for a common library).
Alternatively, you could setup long polling on the client side. This is using JavaScript to periodically 'poll' the server for information using setInterval or a similar approach.
Since I only need to send data from the server to the client, I ended up with Server Sent Events (SSE) and my code looks like this on the server side:
var mypage;
app.get('/connect', function(req, res){
res.writeHead(200, {
'Connection': 'keep-alive',
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache'
});
mypage = res;
});
app.post('/message', function(req, res) {
if (mypage !== undefined) {
mypage.write('data: '+ JSON.stringify( req.body ) +'\n\n');
}
});
and on the client side:
$(function () {
var server = new EventSource('/connect'),
point1 = $("#gauge1").highcharts().series[0].points[0],
point2 = $("#gauge2").highcharts().series[0].points[0];
server.onmessage = function(e) {
var jsonData = JSON.parse(e.data);
if (jsonData.hasOwnProperty('phone1')) {
point1.update(parseInt(jsonData.phone1.dl));
if (jsonData.phone1.connection === "3G") {
/* extra functionality */
} else {
/* extra functionality */
}
} else
if (jsonData.hasOwnProperty('phone2')) {
point2.update(parseInt(jsonData.phone2.dl));
if (jsonData.phone2.connection === "3G") {
/* extra functionality */
} else {
/* extra functionality */
}
}
};
});
I got extra help from my other question regarding the data formatting of SSE
Node Webkit was not the answer to my problem, since it doesn't run on the browser.
I still have some problems with receiving many posts. I'm generating every 0.5s a post message but I keep receiving 5 messages then nothing for 2 minutes then again 5 messages. I don't know why that's happening, but it's not part of this problem so I'll post another question about that.
So I have built a html form to interact with Slack. Currently my js code looks like this.
$("#submitemail").click(function(){
$.post(
"https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN",
JSON.stringify({'text':'invite request from: '+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
if anyone were to just copy this right out of my html file they could just run a console command and change the JSON and bombard my slack group with massive amounts of nonsense until they hit the API call limit.
What I am wondering is if I could store this in my index.js (I am using a node.js template) as a var and then call it in the html.
Any options or advice is greatly appreciated I am very new to this.
My structure is:
Slack App
|_node_modules
| |_express
|_public
| |_index.html
| |_node.svg (idk what this does)
|_.gitignore
|_app.json
|_index.js
|_package.json
|_procfile
|_README.md
the code for my index.js is just
var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
I can throw in my full html if you want its just a basic modal w/ a button to click to execute the form and pull the email.
Disclaimer: this code is untested
You would basically do something like this:
index.js (commented to explain what i added):
var express = require('express');
// install request module
var request = require('request');
var app = express();
// make a new route that you can call from the client side
app.get('/getSlackData', function(req, res) {
//variable to hold your response from slack
var slackResponse;
//make the request to slack
var slackUrl = "https://openpgh.slack.com/services/hooks/incoming-webhook?token=MY_SECRET_TOKEN""
request(slackUrl, function (error, response, body) {
if (!error && response.statusCode == 200) {
slackReponse = response;
} else {
console.log(error);
});
return slackResponse;
});
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/public'));
app.listen(app.get('port'), function() {
console.log("Node app is running at localhost:" + app.get('port'))
});
So we added a new route, that is basically an API you can call from the client side, it will return the JSON object that you got from Slack. You can pretty much leave your client side code the same, just change the route you're calling:
$("#submitemail").click(function(){
$.post("/getSlackData",
JSON.stringify({'text':'invite request from:'+$("#email").val(),'username':'Slack Inviter','icon_emoji':':raising_hand:'})
).success(function(){
$("#email").val("");
});
});
I hope I understood your question correctly, this should at least get you pointed in the right direction.
I'm trying to do a ajax post to a heroku server app and have the app return a response to the client web page (on a different server).
It works just fine if I test it locally (using localhost) but when I push to heroku, I get no response.
app.js:
var express = require('express');
var app = express();
app.use(express.bodyParser()).post('/', function(req, res){
res.header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Headers", "X-Requested-With").header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
res.end("test");
});
port = process.env.PORT || 3000;
app.listen(port);
client-side js:
$.post("http://myapp-name-here.heroku.com", {query: "anything", val: "something"},
function(data){
console.log(data);
});
Edited in:
When I open the client-side html page, when it makes the post request, it gets the status "canceled" after a couple of seconds. Any ideas?
myapp-name-here.heroku.com is no longer supported, try myapp-name-here.herokuapp.com