I am using node.js to create a server that brings in serial data. The serial data is successfully showing in the HTML; however, I would like to create a 'var' that can hold the data. Please can someone help?
Here is my index.html page:
<!DOCTYPE html>
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script>
// open a connection to the serial server:
var socket = io.connect('http://localhost:8080');
// when you get a serialdata event, do this:
socket.on('serialEvent', function (data) {
// look for the textDisplay element in the HTML below:
var element = document.getElementById('IDTag');
// set the stuff inside the element's HTML tags to
// whatever the 'value' property of the received data is:
element.innerHTML = data.value;
});
</script>
</head>
<body>
And the latest is:
<div id="IDTag">The RFID Tag ID will show here.</div>
</body>
</html>
and here is my SerialServer.js doc:
/*
serialServer.js
a node.js app to read serial strings and send them to webSocket clients
requires:
* node.js (http://nodejs.org/)
* express.js (http://expressjs.com/)
* socket.io (http://socket.io/#how-to-use)
* serialport.js (https://github.com/voodootikigod/node-serialport)
based on the core examples for socket.io and serialport.js
created 21 Aug 2012
modified 14 Oct 2012
by Tom Igoe
Patches and improvements suggested by Steve Klise, Lia Martinez, and Will Jennings
*/
var serialport = require("serialport"), // include the serialport library
SerialPort = serialport.SerialPort, // make a local instance of serial
app = require('express')(), // start Express framework
server = require('http').createServer(app), // start an HTTP server
io = require('socket.io').listen(server); // filter the server using socket.io
var serialData = {}; // object to hold what goes out to the client
server.listen(8080); // listen for incoming requests on the server
console.log("Listening for new clients on port 8080");
// open the serial port. Change the name to the name of your port, just like in Processing and Arduino:
var myPort = new SerialPort("/dev/tty.usbmodemfa131", {
// look for return and newline at the end of each data packet:
parser: serialport.parsers.readline("\r\n")
});
// respond to web GET requests with the index.html page:
app.get('/', function (request, response) {
response.sendfile(__dirname + '/index.html');
});
// listen for new socket.io connections:
io.sockets.on('connection', function (socket) {
// if there's a socket client, listen for new serial data:
myPort.on('data', function (data) {
// set the value property of scores to the serial string:
serialData.value = data;
// for debugging, you should see this in Terminal:
console.log(data);
// send a serial event to the web client with the data:
socket.emit('serialEvent', serialData);
});
});
Thanks in advance!
First of all, I would advise moving all the javascript to the end of the page, before the closing body tag (instead of the head tag).
Secondly, I find it strange that you run a socket.io server as well as an http server on the same port.
I'm not even sure that is the correct way of running socket.io, I would advise playing around with the official demos instead (they're guaranteed to work).
Related
Im creating a realtime application using socket.io and its been going alright, until i found somthing strange going on when a client connects to the server. The client will connect, and the connection event will properly reflect on the server, but shortly after, a cluster of what i can only describe as "fake clients" start connecting to the server and triggering the connection event a seemingly random number of times. These strange connections that come out of nowhere are causing an increasingly big delay on the servers response to actual clients as more start to join. I created an extreamly basic socket.io boilerplate just to see if the strange bug would persist without all the complexity of my application, and to my suprise it did, and i cant understand why. Any info will be greatly appriciated. Here is my basic server and client setup -
const http = require("http");
const fs = require("fs");
const server = http.createServer();
const io = require("socket.io")(server);
io.on("connection",() => {
console.log("A client has connected!");
});
server.on("request",(req,res) => {
fs.readFile("./index.html",(err,data) => {
if (!err && data) {
res.writeHead(200,{"Content-Type": "text/html"});
res.end(data);
} else {
res.writeHead(500);
res.end();
}
});
});
server.listen(3000,() => {
console.log("Server is active...");
});
note how i am logging that a client connected each time the connection event is triggered. Here is the index.html file and client script -
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.socket.io/3.1.1/socket.io.min.js" integrity=" sha384- gDaozqUvc4HTgo8iZjwth73C6dDDeOJsAgpxBcMpZYztUfjHXpzrpdrHRdVp8ySO " crossorigin="anonymous"></script>
<script type="text/javascript">
const socket = io({autoConnect: false});
socket.connect();
</script>
</head>
<body>
</body>
</html>
Here is the console output i get when i connected a single client to the server. Again, its seemingly random each time.
A client has connected
A client has connected
A client has connected
A client has connected
A client has connected
The first one is genuine, but i have no idea where the rest come from, as they even have a different socket id when i tried to log it out. Any type of feedback is appriciated.
My overall goal is to generate a stream of random numbers in a JavaScript file (which is run using node) and send them to a python script in asynchronous time intervals. Once the numbers are in python, the script will determine if the numbers are even, or not. If they are, the numbers are sent back to the JavaScript file. My main focus is to get the communication between JavaScript and Python.
Once I begin the JavaScript file and python server, they will continue running until I stop them.
Currently, I have been working off the tutorial located here (https://tutorialedge.net/python/python-socket-io-tutorial/). The tutorial uses socket io for JS and aiohttp for python.
I manipulated the html code into a JS code (index.js), which is below:
// index.js
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function(){});
function generateNumber() {
let n = Math.floor(Math.random() * 50);
let json = {
'number': n
}
console.log(json);
return json;
}
(function loop() {
var rand = Math.round(Math.random() * (3000 - 500)) + 500;
setTimeout(function() {
generateNumber();
loop();
}, rand);
}());
function sendMsg() {
socket.emit("message", generateNumber());
}
socket.on("message", function(data) {
console.log(data);
});
I created a function (generateNumber) to produce random numbers outputted in JSON format. I am using JSON because I believe it will allow for data to be easily converted into lists and integers when the numbers reach the python script. The loop function allows the numbers to be created at random intervals continuously and was taken from here: Randomize setInterval ( How to rewrite same random after random interval)
The python server (server.py) shown below, was taken from the tutorial (https://tutorialedge.net/python/python-socket-io-tutorial/):
# server.py
from aiohttp import web
import socketio
# creates a new Async Socket IO Server
sio = socketio.AsyncServer()
# Creates a new Aiohttp Web Application
app = web.Application()
# Binds our Socket.IO server to our Web App
# instance
sio.attach(app)
# we can define aiohttp endpoints just as we normally
# would with no change
async def index(request):
with open('index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
# If we wanted to create a new websocket endpoint,
# use this decorator, passing in the name of the
# event we wish to listen out for
#sio.on('message')
async def print_message(sid, message):
# When we receive a new event of type
# 'message' through a socket.io connection
# we print the socket ID and the message
print("Socket ID: " , sid)
print(message)
# We bind our aiohttp endpoint to our app
# router
app.router.add_get('/', index)
# We kick off our server
if __name__ == '__main__':
web.run_app(app)
As of now, when I run node index.js, random numbers are continuously generated at random intervals and the output can be seen in the terminal. But I am not getting a response on the server side.
I believe the problem is related to the following 2 issues:
First, my current JS code (index.js) was originally a html script that sent a message with a button click hosted on “http://localhost:8080.” I adjusted the script to be a JS script, as well as adding additional functions. So there may be an issue in the following lines of index.js where I setup socket io:
var socket = require('socket.io-client')('http://localhost:8080');
socket.on('connect', function(){});
For clarity, here is the original html code (index.html) that index.js is based off:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<button onClick="sendMsg()">Hit Me</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
<script>
const socket = io("http://localhost:8080");
function sendMsg() {
socket.emit("message", "HELLO WORLD");
}
</script>
</body>
</html>
I also asked a previous question related to the html to JS conversion (Syntax error when trying to convert HTML file to JavaScript containing socket io, SyntaxError: Unexpected token <)
Second, because the tutorial originally used a html file rather than JS, I believe the python script (server.py) is still waiting on output from a html script, so I think these lines in server.py need to be changed:
async def index(request):
with open('index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
But I am unsure how to make the proper changes, I am having issues finding references to my question on the aiohttp site (https://aiohttp.readthedocs.io/en/stable/), or I may be unsure as to what I am looking for.
Both server.py and index.js currently run without errors, but they are not communicating.
Overall, the JS file (index.js) will be sending data to a python server (server.py) using socket io, and the python server, using aiohttp, will be sending back the analyzed data to the same JS script. This will happen continuously until one of the scripts is stopped manually.
If any clarification is needed on anything, please feel free to ask.
I believe, in JS part, you should call sendMsg() somewhere in order to emit a message.
Updated
const io = require('socket.io-client');
const socket = io('http://localhost:8080');
socket.on('message', data => {
console.log('Got from server: ');
console.log(data);
});
function generateNumber() {
const n = Math.floor(Math.random() * 50);
return { number: n };
}
function sendMsg() {
const json = generateNumber();
console.log('Sending to server:');
console.log(json);
socket.emit('message', json);
}
function loop() {
const rand = Math.round(Math.random() * (3000 - 500)) + 500;
console.log(`Setting timeout ${rand}ms`);
setTimeout(() => {
sendMsg();
loop();
}, rand);
}
socket.on('connect', () => {
console.log('Connected to server');
loop();
});
I was using node on both sides. The server side just sends back every received message.
The logs look like this:
Connected to server
Setting timeout 1685ms
Sending to server:
{ number: 21 }
Setting timeout 1428ms
Got from server:
{ number: 21 }
Sending to server:
{ number: 40 }
Setting timeout 2955ms
Got from server:
{ number: 40 }
I'm trying to use socket.io to connect to this websocket api:
https://www.cryptocompare.com/api/#-api-web-socket-
(wss://streamer.cryptocompare.com)
I guess im not really understanding socket.io very much.
I created a blank html document:
<!doctype html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.slim.js"></script>
</head>
<body>
<div id="data-show">
</div>
<button id="connect-sock">Connect</button>
<button id="disconnect-sock">DISConnect</button>
</body>
<script src="index.js"></script>
</html>
index.js:
var socket = io('wss://streamer.cryptocompare.com')
console.log('connected')
var btn = document.getElementById('connect-sock')
var btn2 = document.getElementById('disconnect-sock')
var show = document.getElementById('data-show')
//I also tried adding an event listener to a button so when i clicked it, it would do this:
socket.emit('SubAdd', { subs: ['0~Poloniex~BTC~USD'] } )
//Same result of nothing.
socket.on('SubAdd', function(data){
console.log(data)
})
server.js:
var express = require('express')
var socket = require('socket.io')
var app = express()
var server = app.listen(4000, function(){
console.log("well met")
})
app.use(express.static('public'))
var io = socket(server)
io.on('connection', function(socket){
console.log('well met from socket connection', socket.id)
})
server.js is in a file named 'socket-test'. index.html and index.js are in 'socket-test/public/'
so for some reason, in server.js, socket.id will not log to console. its as if this function is being skipped over. but when i change the address in index.js to http://localhost:4000, i get socket.id in console... not sure whats going on there.
Edit: I rarely get socket id when using the wss://streamer.cryptocompare.com/ , sometimes I do, most of the time i dont. It usually works when I switch to localhost, run the server, stop the server, then switch back to the streamer, but if i reload, i dont get socket.id anymore.
I thought that all I was asking it to do here was emit subs to wss://streamer.cryptocompare then console.log(data) that it returns after emitting the subs.
am I missing something here?
Sorry in advance if its blatantly obvious that I'm missing something. I've only known about socket.io for maybe 3 days now, and only today have I watched a basic tutorial on youtube.
You don't need the Express code because in this case the server you want to talk to is on the cryptocompare server -- not a local server. This is captured in your code when you initialize the io object in the HTML file.
Of course, you could still use Node to talk to the cryptocompare websockets API if you're more comfortable with Node. But then you wouldn't need the in-browser JavaScript. Either way, what you need is to create some kind of client in any runtime that speaks websockets and can talk to the cryptocompare websockets API.
With regard to the code being skipped over -- you're right! It is. socket.io is an event driven WebSockets framework. This means that clients register their interest in certain kinds of events/messages, and when those are triggered special functions known as callbacks are called.
If it helps, you can think of those events like channels in a chat room -- if you're not in the right room, you won't see the messages for that room. So you'll need to know what messages you should be listening for, register your interest in those, and register callback functions for each one.
Thankfully cryptocompare has provided client code examples that should help you get an idea for the kinds of messages you should be listening for.
See here
I can't figure out how to retrieve query parameters on the server side for socket.io
1.2.1
Here's my client side code
var socket = io('http://localhost:3000/',{_query:"sid=" + $('#sid').attr('data-sid') + "&serial=" + $('#serial_tracker').text()});
and the server side:
io.use(function(socket,next){ //find out if user is logged in
var handshake = socket.request;
console.log(socket.request._query);
handshake.sid = handshake.query.sid;
}
socket.request._query is:
{ EIO: '3', transport: 'polling', t: '1419909065555-0' }
Does anyone know how query parameters work in socket io 1.2.1?
Thanks for any help and if you need any more information, just ask me.
When sending handshake query data to socket.io, use the following property name in the object:
{
query: 'token=12345'
}
I see above you used _query for a property name instead.
You should be able to access the query information at socket.request._query at that point. I'm not sure if there is a better way to get a hold of that data? I'm guessing yes, since they put an underscore in front of it, but I haven't found a better way yet.
Here's the full example of a connect query that is working for me (forgive the formatting, I'm copy/pasting this out of different node modules into an inline solution).
Server (using socket 1.2.1 nodejs):
var restify = require('restify');
var api = restify.createServer();
var socketio = require('socket.io');
var io = socketio.listen(api.server); // api is an instance of restify, listening on localhost:3000
io.use(function(socket, next) {
// socket.request._query.token is accessible here, for me, and will be '12345'
next();
});
api.listen(3000, function() {
console.log('%s listening at %s', api.name, api.url);
});
Client (chrome browser using the client library located at https://cdn.socket.io/socket.io-1.2.1.js):
var socket = io.connect('http://localhost:3000/', { query: 'token=12345' });
I have been trying to find any post that can explain if it is possible to re-render one 'new' item (append) to a jade template list.
Say that we have a list of log-entries and upon first request we render a fetched list from a MongoDB collection 'logs', using res.render and Jades each functionality.
Since we like to retrieve updates from the database we also have a MongoWatch attached to that collection that listens for changes. Upon update can we execute some code that appends to that first list in the Jade-template?
/* app.js */
/*
Display server log
*/
app.get ('/logs', function(req, res, next) {
// Using Monk to retrieve data from mongo
var collection = db.get('logs');
collection.find({}, function(e,docs){
// watch the collection
watcher.watch('application.logs', function(event){
// Code that update the logs list with the new single entry event.data?
});
// Request resources to render
res.render('logs', { logs: docs } );
});
});
<!-- logs.jade -->
extends layout
block content
div
each log in logs
div.entry
p.url= log.url
Maybe i should use the template engine in another fashion, i am quite new to Express, Jade and really appreciate all you guys that spends your time answering problems like these..
// Regards
Ok, so i have looked up the suggestion from Jonathan Lenowski, thanks by the way!, and i came up with a solution to my problem. Thought i'd follow up and perhaps help someone else along the way..
Basically i am now using as suggested socket.io
So first install the socket.io npm module by adding it to package.json and run npm install, i used 'latest' as version.
Next to use the 'socket.io.js' on the client-side you actually have to copy the file from the installed socket.io module to your javascript folder.
Path (seen from project root is): 'node_modules/socket.io/node_modules/socket.io-client/dist/'
Setup DB, Watcher, Webserver, Socket and controller on server-side
/*
SETUP DATABASE HANDLE
in app.js
*/
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:'+app.get('port')+'/application');
/* SETUP DATABASE UPDATE WATCH */
var watcher = new MongoWatch({ format: 'pretty', host: 'localhost', port: app.get('port') });
/* START WEBSERVER AND SETUP WEBSOCKET */
var server = Https.createServer({key: certData.serviceKey, cert: certData.certificate}, app);
var io = require('socket.io').listen(server);
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
/*
Display server log - controller
*/
app.get ('/logs', function(req, res, next) {
// Using Monk to retrieve data from mongo
var collection = db.get('logs');
collection.find({}, function(e,docs){
// watch the collection logs in database application
watcher.watch('application.logs', function(event){
io.sockets.emit('logs', { log: event.data });
});
// Request resources to render
res.render('logs', { logs: docs } );
});
});
Include the socket.io javascript in layout
/*
Add client side script
in layout.jade
*/
script(type='text/javascript' src='/javascripts/socket.io.js')
Use the client
/*
SETUP DATABASE HANDLE
in logs.jade
*/
extends layout
block content
script.
var socket = io.connect('https://localhost:4431');
socket.on('logs', function (data) {
console.log(data.log);
// Here we use javascript to add a .log-entry to the list
// This minor detail i leave to the developers own choice of tools
});
div.row#logs
div.col-sm-12
div.header-log Some application
div.logs-section
each log in logs
div.log-entry.col-sm-12(data-hook=log.status)
p.method= log.method
p.url= log.url
p.status(style='color: #'+log.color+' !important')= log.status
p.response-time= log.time
p.content-length= log.length
p.datetime= log.date
Use the functionality, remember that this flow is triggered by actually adding a row in the database 'application' and the collection 'logs'.
I use ssl thus with regular http we create a 'http' server instead and connect from the client with a standard address prefix of http://...
Also as an additional note, in order to use MongoWatch it is required of you to setup the MongoDB with replication set. Which is a mirror database that can be used as a fallback (dual purpose).
Cheers! And once again thanks to Jonathan!