Auto-connecting to specific device with serialport in Node.js - javascript

I am pretty new to node and asynchronous programming (I come from a C background), and I am having trouble auto-connecting to a port that has a device with a certain vendorID using serialport in Node.js. I have everything working separately, ie. I can connect to a port, and I can find a port with a certain vendorID, but I can not connect to the port that I found. Here is the code I have so far:
var SerialPort = require('serialport');
var MYport;
SerialPort.list(function (err, ports) {
ports.forEach(function(port) {
if(port.vendorId == 9999){
console.log('Found It')
MYport = port.comName.toString();
console.log(MYport);
}
});
});
var port = new SerialPort(MYport, {
parser: SerialPort.parsers.readline('\n')
});
When this is run I get an error due to the fact that MYport is not defined at the time that the port is created and connected to.
I know that I will most likely have to use a call back function but I just can't figure it out.
Thanks for the help

SerialPort.list is async function,
so you need place the connection to serialport after emit callback of async function.
like this:
var SerialPort = require('serialport');
var MYport;
SerialPort.list(function (err, ports) {
ports.forEach(function(port) {
if(port.vendorId == 9999){
console.log('Found It')
MYport = port.comName.toString();
console.log(MYport);
}
});
var port = new SerialPort(MYport, {
parser: SerialPort.parsers.readline('\n')
});
});

Related

Using Socket.IO from Node.js to connect to external server

Background: I have a node.js server running on my localhost (call this Server A); and an external server running node.js at https://example.net:3000 (call this Server B). I do not control or have access to Server B (it is a dashboard site for an IoT device in my home), but I need to connect to is using socket.io and emit a specific message.
I can connect to it easily from a flat javascript file (client-side), but need it running server side (ultimate goal is to make it into something I can call with an HTTP request); and examples such as How to connect two node.js servers with websockets? suggest I should be able to use socket.io-client from node.js with nearly the same code to achieve the same results. But when I run the code from node.js, I cannot connect to the socket.
Below is the code that works successfully in flat javascript file. I know it works because I see 'socket connect' in the console, and I can also test for the the socket emit at the end.
var myemail = "email#gmail.com";
var device_id = '12345';
// Create SocketIO instance, connect
var socket = io.connect('https://example.net:3000');
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
...and below is the code I cannot get to work when running from my node.js instance. I'd expect a message 'socket connect' in the command line log and get nothing.
var express=require('express');
var http=require('http');
var app=express();
var server = http.createServer(app);
//Variables
var myemail = "email#gmail.com";
var device_id = '12345';
var io = require('socket.io-client');
var socket = io.connect('https://example.net:3000');
//Connect listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "45678");
Any ideas?
UPDATE
Ran debug utility, results included as linked image below. Key thing I see is that engine.io tries to do an xhr poll, and gets a 503 response back from the server. (Obviously not a true 'temporary error' with the server as again, this all works from running client-side js in chrome).
debugging output image link
Solved this - issue was that the server I was connecting to required use of https, so I needed to add
{secure: true, rejectUnauthorized: false}
after the url to connect to.
Full working example:
const myemail = email#email.com;
const device_id = 12345;
io = require('socket.io-client');
var socket = io.connect('https://server.net:3000',{secure: true, rejectUnauthorized: false});
function doStuff(){
//Listener
socket.on('connect', function(){
try {
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
} catch(e) {
console.log(e);
}
});
socket.emit("/" + device_id, "003021");
}
doStuff();
I think the line causing the issue is :
var socket = io.connect('https://example.net:3000');
I managed to make a working example using this code :
const myemail = "email#gmail.com";
const device_id = '12345';
var socket = require('socket.io-client')('https://example.net:3000');
socket.on('connect', function(){
try{
console.log('socket connect');
socket.emit('configure', {email:myemail, deviceid:device_id});
}catch(e){ console.log(e); }
});

why web socket behave differently on nodejs ?

I have a Nodejs Server.js code :
first Concept :
var http = require('http');
var express = require('express');
var app = express();
var path = require('path');
var conn= http.createServer(app).listen(3000, function () {
console.log("server Running at Port 3000");
});
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({server: conn});
and i have a index.html code with java script :
<html>
<body>
<script src="myscript.js"></script>
</body>
</html>
inside myscript.js i have :
var connection = new WebSocket('ws://localhost:3000');
This is working fine when i open http://localhost:3000 on browser .
second Concept :
my server.js :
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({ port: 3000}) ;
wss.on('connection', function (connection) {
});
wss.on('listening', function () {
console.log("Server started...");
});
and HTML and client java script is similar as above .
This is not working when i open http://localhost:3000 on browser . why ? i want to clarify my doubt . Why the first method working and second is not working ?
To specifically answer your question: why web socket behave differently on nodejs? the answer is: It shouldn't. In the second version of your code you are not serving any HTML or JS files to the client on the port 3000 so the browser can't download any HTML.
If you want it to work as expected then you need to serve some HTML and JS files to the browser that visits http://localhost:3000/ or otherwise it will not be able to connect.
I wrote some example code - both server-side and client-side - on how to use WebSocket to do exactly what you are trying to do here. It's available on GitHub and I originally wrote it for this answer: Differences between socket.io and websockets.
The relevant parts of the source code for your question here are:
WebSocket Server
WebSocket server example using Express.js:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.js
WebSocket Client
WebSocket client example using vanilla JavaScript:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
Source: https://github.com/rsp/node-websocket-vs-socket.io/blob/master/ws.html
Instead of debugging a code that it not working, sometimes it's better to start from something that works and go from there. Take a look at how it all works and feel free to change it and use it in your projects - it's released under MIT license.

fail to connect localhost:8081 using node.js

I have opened the server.js and the address:http://localhost:8081 on my browser. But then a text "Upgrade Required" appeared at the top left conern of the website.
What is the problem of that? What else do I need to upgrade?
Here is the server.js:
var serialport = require('serialport');
var WebSocketServer = require('ws').Server;
var SERVER_PORT = 8081;
var wss = new WebSocketServer({
port: SERVER_PORT
});
var connections = new Array;
SerialPort = serialport.SerialPort,
portName = process.argv[2],
serialOptions = {
baudRate: 9600,
parser: serialport.parsers.readline('\n')
};
if (typeof portName === "undefined") {
console.log("You need to specify the serial port when you launch this script, like so:\n");
console.log(" node wsServer.js <portname>");
console.log("\n Fill in the name of your serial port in place of <portname> \n");
process.exit(1);
}
var myPort = new SerialPort(portName, serialOptions);
myPort.on('open', showPortOpen);
myPort.on('data', sendSerialData);
myPort.on('close', showPortClose);
myPort.on('error', showError);
function showPortOpen() {
console.log('port open. Data rate: ' + myPort.options.baudRate);
}
function sendSerialData(data) {
if (connections.length > 0) {
broadcast(data);
}
}
function showPortClose() {
console.log('port closed.');
}
function showError(error) {
console.log('Serial port error: ' + error);
}
function sendToSerial(data) {
console.log("sending to serial: " + data);
myPort.write(data);
}
wss.on('connection', handleConnection);
function handleConnection(client) {
console.log("New Connection");
connections.push(client);
client.on('message', sendToSerial);
client.on('close', function () {
console.log("connection closed");
var position = connections.indexOf(client);
connections.splice(position, 1);
});
}
function broadcast(data) {
for (c in connections) {
connections[c].send(data);
}
}
OK, websockets...
The "upgrade required" status marks the start of a websocket handshake. Normally your client sends this first to the WS server. The server answers in a pretty similar manner (details here : https://www.rfc-editor.org/rfc/rfc6455 ), and then proceed to pipe the actual data.
Here, you're opening a connection from your client as regular http, sending a simple GET. What you see on the screen is the server dumbly proceeding with an already corrupted handshake.
That's not how you open a WS client side connection. You don't usually open WS pages from the browser. It ought to be opened from a JavaScript call, such as new WebSocket(uri). So what you want is a regular http server on another port, that serves a page containing the necessary Javascript to open the actual WS connection and do something useful with its data. You'll find a clean example here : http://www.websocket.org/echo.html

Socket.IO not using fallback methods

I have a node server that's running a socket.io server and a client to work with it. Simple story, I need to be able to transfer messages between the two. This is working as intended in browsers that support web sockets but when a fallback method needs to be used its not working.
I should mention that pages are served from an apache server and the node server is only used for a specific page. The code that I am using is below, I've tinkered on this for a while and can't figure out how to fix it.
Also worth mentioning that when the page is opened in IE9(websockets not supported),
logging connection.io.engine.transport.name would give "websocket".
Client:
connection = io(window.location.protocol + '//localhost:8888', {
'reconnect': false,
'max reconnection attempts': 0,
'transports':
[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]
});
connection.on('connect',function () {
console.log("Socket is open");
$('#dc-status').hide();
connection.emit('message',JSON.stringify(info));
connection.on('message',function (e) {
//DO SOMETHING WITH THE DATA RECIEVED
});
});
Server:
var ioserver = require('socket.io');
var io = ioserver.listen(8888);
var http = require("http");
console.log("server started...");
io.set('transports',[
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling'
]);
io.sockets.on('connection', function(ws) {
var req;
var order;
var courier;
var after;
var session;
var options = {};
console.log("New client connected");
// console.log("Transport: " + io.transports[ws.id].name);
ws.on('message', function(data) {
//WORK WITH THE DATA RECEIVED
//NOT RELEVANT TO EXAMPLE
console.log('received: %s', data);
parsedData = JSON.parse(data);
});
ws.on('disconnect', function () {
console.log("Connection closed");
});
});
Ok, so after much struggle with this I have found a solution for making sockets work in old browsers.
As of version 1.0 Socket.io uses Engine.io instead of fallback methods, which takes care of transports.
To get a working solution I skipped using the Socket.io layer and used just Engine.io instead.
In the client you have something like
var connection = eio.Socket('host-address');
and then you just bind the regular events(e.g message, close).
And in the server part instead of require('Socket.IO'), you call require('Engine.IO'), example:
var engineio = require('engine.io');
var wss = engineio.listen(10101);
The binding is the same.

Simulating linux terminal in browser

I have read about Fabrice Bellard's linux simulation in browser.
How does Linux emulator in Javascript by Fabrice Bellard work?
Today I stumbled upon this site, where they are simulating full linux terminal in browser, I am able to run python, perl etc. I know they are running their site on node.js, but I couldn't figure out how they exactly simulating the terminal.
http://runnable.com/UWRl3KlLuONCAACG/read-files-from-filesystem-in-python
The full linux is http://docker.io, the rest is https://github.com/Runnable/dockworker
We're not simulating the terminal but as Kyle says, replicating the terminal over websockets (with an ajax fallback).
In the browser we're using https://github.com/chjj/term.js which was derived from Fabrice Bellard's emulator. It handles the output, and also the keystroke capture.
Let me prefix this by saying it is NOT a good idea to do this.
But, You can spawn a shell and use web-sockets or XMLHttpRequests to push keypresses to the spawned server process. Here's a working example of one that runs on windows. Unfortunately, I didn't get around to hooking up / figuring out Ctrl+c. But, you should get the gist of it.
require("underscore");
var Server = {},
express = require("express"),
path = require("path"),
sys = require("sys"),
application_root = __dirname;
global.Server = Server;
Server.root = application_root;
global.app = express();
Server.setup = require("./lib/setup.js").setup({
//redis: require("./lib/redis-client").createClient(),
app: app,
//mongoose : require("mongoose"),
io : require("socket.io"),
express : express,
port: 1773,
paths : {
views : path.join(application_root,"app","views"),
root : path.join(application_root,"public"),
controllers : path.join(application_root,"app","controllers"),
models : path.join(application_root,"app","models")
}
});
var proc = require('child_process'),
cmd;
app.socket.on('connection', function(socket) {
if (!cmd) {
//console.log('spawning cmd');
cmd = proc.spawn('cmd');
//console.log(cmd?'CMD started':'CMD not started');
if (cmd.stdout) {
//console.log('stdout present');
cmd.stdout.on('data',function(data) {
if (data) {
//console.log("data: "+data);
socket.emit('cmd', ""+data);
}
});
}
if (cmd.stderr) {
cmd.stderr.on('data', function(data) {
//console.log('stderr present');
if (data) {
socket.emit('cmd', ""+data);
}
});
}
cmd.on('exit', function() {
//console.log('cmd exited');
socket.emit('cmd', '[CMD Shutdown]');
if (cmd) {
cmd.kill();
cmd = null;
}
});
}
socket.on('sendCmd', function(data) {
if (data && data.buffer) {
var kB = data.buffer.replace("\r","\n");
if (cmd && cmd.stdin) {
cmd.stdin.write(kB);
}
}
});
socket.on('disconnect', function() {
console.log('connection closed');
if (cmd) {
cmd.stdin.end(); //.kill();
if (cmd) {
cmd.kill();
cmd = null;
}
}
});
});
Edit: Actually, this is a portion of a working example. It's missing the client side where you capture and send the keystrokes to the server. But, it should give you the general idea.

Categories