open serialport and log data automatically under various events - node.js

I am using a COM3 port and iam using the serialport module to read from the serialport. What I want is an automatic logging system which logs the data from serialport under the following events.
1.close program and reopening the program
2.restart my pc
3.unplug the usb cable and plug it again
4.restart the Arduino device
I want to open the serialport and log data received from it automatically whenever the above events occur. How to handle these cases.
Currently, this is the code iam using
var fs = require('fs');
const SerialPort = require('serialport')
const Readline = require('#serialport/parser-readline')
const port = new SerialPort('COM3')
const parser = new Readline()
port.pipe(parser)
parser.on('data', function (data) {
const index = data.indexOf('*#SENSOR_DATA')
if(index != -1){
fs.appendFileSync("sensor_data.txt", new Date(), 'utf8')
fs.appendFileSync("sensor_data.txt", data, 'utf8')
}
})
port.on('error', function(err) {
fs.appendFileSync("sensor_data.txt", new Date(), 'utf8')
fs.appendFileSync("sensor_data.txt", err, 'utf8')
console.log(err);
})
port.write('ROBOT PLEASE RESPOND\n')
How can I handle the above mentioned cases?

close program and reopening the program
Logging the data from the port on starting of the program, should be straight forward, i.e. the running of your script.
Closing of the program, depends on what you scenarios you want to handle, graceful or non graceful exits of the program. To implement this you can add event listeners on the nodeJS process object. You can register event handlers for when the process is going to exit to do some action.
process.on('SIGINT', () => {
// read my data from Serial
process.exit(-1);
})
restart my pc
Depending on what your OS is, you could configure your nodejs process as a service, or you could run it via cron. For example cron (depending on the OS) has the option for scheduling jobs on reboot. Regardless of your OS, you will be able to schedule jobs or create a service to ensure your process starts when your machine restarts.
unplug the usb cable and plug it again &
restart the Arduino device
For this I would look at the different parsers that are available for serialport. For example the ReadyParser.

Related

Can't get hidraw0 device to open in nodeJS app

Good evening!
I'm trying to setup a barcode scanner app using the Node SerialPort package, used on a Raspberry Pi 4, and I'm having a hard time getting the code to either recognise the device
I've identified that the path is /dev/hidraw0 as this is what I was able to ascertain from a dmesg output.
When I run cat /dev/hidraw0 it opens and when I scan a barcode it outputs %""'#''!'&" to the console (I know it's gibberish, but different problem for a different day). BUT, when I reference this path in my nodeJS code, I get the below error:
Serial port error: Error: Error: Invalid argument setting custom baud rate of 9600
I've confirmed on the manufacturer website that the default baud rate is 9600. I have tried removing the baudRate option in the below code, but it still says the same error.
This is the code I'm using right now:
// Use the serialport module to get scanner data
const SerialPort = require('serialport');
const Readline = require('#serialport/parser-readline')
// Open the serial port with some configuration
const port = new SerialPort('/dev/hidraw0', {baudRate: 9600});
const parser = new Readline()
port.pipe(parser)
// When the port is open just say so
port.on('open', function() {
console.log('Serial port open');
});
// Check for errors on the serial interface
port.on('error', function(err) {
console.log(`Serial port error: ${err}`);
});
// Pass scanner data onto web server
port.on('data', function(data) {
console.log('Scan prompted');
});
The USB Scanner I'm using is the Zebra LS2208 and I would love some help or guidance on what may be causing this.
Thanks in advance!
In case anyone else comes around this, I was not able to get the device working with the NPM package I referenced, but as this module used node-hid, I decided to use that one and was able to get my scanner recognised and working properly.

Attaching event emitter to socket.connected

I am currently writing an Electron app, for which in the main process I want to talk to a server over websockets.
Part of my main process' code base depends on the user's socket connection status. I require the socket.io-client library
const socket = require('socket.io-client')(host);
which gives me access to the variable socket.connected, which is true or false according to whether a connection is established to the server.
Thus, what I would like is to attach an event emitter to this variable. I have made it to work with polling
var events = require('events').EventEmitter;
var event = new events();
// Emits successfully every 200ms 'Connection: true|false'
event.on('status', function(status){
console.log('Connection: ', status);
});
setInterval(function() {
let status = socket.connected;
event.emit('status', status);
}, 200);
but was wondering whether this truly is the way to implement it. To me it seems strange to have to resort to polling in an async framework like nodejs. On the other, I could not find other ways to implement. Best-case scenario would be to attach somehow an event emitter directly to socket.connected, but was unable to find how to do that. Could anybody advise me on a better way to implement?
Thanks
You can get notified of the completion of a client connection with the connect event:
socket.on('connect', function() {
// client socket is now connected to the server
});
socket.on('disconnect', function() {
// client socket is now disconnected from the server
});
Documentation for client events here: http://socket.io/docs/client-api/#manager(url:string,-opts:object). There are other events in that doc if you also want to see other things like a reconnect.

How to access a Child Process' sockets in NodeJS?

I am currently running into a very strange problem.
I am trying to start VLC using a NodeJS child process and then accessing it's Remote Control (RC) interface using socket. The problem occurs when connecting to this socket. I get an error, connection refused. The port is open and the application is allowed from the firewall.
The tricky part is, when I open VLC manually using this interface, and only try to connect on the socket, it works. I am assuming something in the spawned process makes things different causing the error somehow.
Here is the code I am trying to run:
var spawn = require('child_process').spawn;
var file_dir = "V:\\TEST\\";
var files = ["Ika.mkv", "Nami.mkv", "Azu.mkv"];
var player = spawn("C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe", ['--intf="rc"', '--rc-host="localhost:3000"', '--fullscreen', file_dir + files[0]]);
var net = require('net');
var client = net.createConnection(3000, "localhost");
client.on('connect', function() {
console.log('connected to VLC on port 3000');
client.write("add " + file_dir + files[1] + "\n");
client.write("enqueue " + file_dir + files[2] + "\n");
client.write("help" + "\n");
});
client.on('data', function(data) {
console.log(data.toString());
});
client.on('end', function() {
console.log('disconnected from server');
});
I have tried this code on two machines, and I am running into the same problem.
Some questions you may ask:
What operating system? Windows 8.1
Why do I need to use a socket?
VLC doesn't have any interfaces that read and write from standard in or standard out. I have tried many different options and they simply do nothing.
What am I trying to build?
A Media Center with an web interface to it. I am using VLC as a media player.
Can't you use the built in HTTP interface?
It doesn't suit what I want to build. I want more control over managing my media.
Any and all help would be welcome. My thanks.
Turns out for some strange reason not all command line arguments get passed to the VLC instance.
I solved it by grouping together the instancing of the RC interface and the setting the RC mode to localhost:3000
This is the new line to spawn a process
var player = spawn("C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe", ['-I rc --rc-host=\"localhost:3000\"','--fullscreen', file_dir + files[0]]);
This works, only downfall is it also creates a RC console window, but I can live with it.
Thanks to #jfriend00 for helping solve the strange mystery.

Efficient HTTP shutdown with keepalives?

This Node.js server will shutdown cleanly on a Ctrl+C when all connections are closed.
var http = require('http');
var app = http.createServer(function (req, res) {
res.end('Hello');
});
process.on('SIGINT', function() {
console.log('Closing...');
app.close(function () {
console.log('Closed.');
process.exit();
});
});
app.listen(3000);
The problem with this is that it includes keepalive connections. If you open a tab to this app in Chrome and then try to Ctrl+C it, it won't shutdown for about 2 minutes when Chrome finally releases the connection.
Is there a clean way of detecting when there are no more HTTP requests, even if some connections are still open?
By default there's no socket timeout, that means that connections will be open forever until the client closes them. If you want to set a timeout use this function: socket.setTimeout.
If you try to close the server you simply can't because there are active connections, so if you try to gracefully shutdown the shutdown function will hang up. The only way is to set a timeout and when it expires kill the app.
If you have workers it's not as simple as killing the app with process.exit(), so I made a module that does extacly what you're asking: grace.
You can hack some request tracking with the finish event on response:
var reqCount = 0;
var app = http.createServer(function (req, res) {
reqCount++;
res.on('finish', function() { reqCount--; });
res.end('Hello');
});
Allowing you to check whether reqCount is zero when you come to close the server.
The correct thing to do, though, is probably to not care about the old server and just start a new one. Usually the restart is to get new code, so you can start a fresh process without waiting for the old one to end, optionally using the child_process module to have a toplevel script managing the whole thing. Or even use the cluster module, allowing you to start the new process before you've even shut down the old one (since cluster manages balancing traffic between its child instances).
One thing I haven't actually tested very far, is whether it's guaranteed safe to start a new server as soon as server.close() returns. If not, then the new server could potentially fail to bind. There's an example in the server.listen() docs about how to handle such an EADDRINUSE error.

Callback hook into AWS APIs

Does anyone know of a way or has anyone devised a clever workaround to place a callback/hook into the Amazon APIs (http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/query-apis.html) such that for actions like create instance, one can simply be notified via the callback when the instance is in the running state?
I'm thinking that I could write a loop in node.js that simply checks for the desired state and eventually timesout after a certain # of requests but I would like to hear better programmatic approaches :)
Unless the AWS APIs support some kind of notification endpoint (I'm not very familiar with the APIs) you're probably stuck with polling. However, you could use an EventEmitter to hide this behind a clever API that exposes a callback. Pseudo-ish code:
// aws_server.js
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function AwsServer(some_data) {
this.data = some_data;
EventEmitter.call(this);
};
util.inherits(AwsServer, EventEmitter);
AwsServer.prototype.createInstance = function() {
// Do something with an API to create an EC2 instance
console.log("Creating instance, data:", this.data);
// Here, you would begin polling for state changes, etc. waiting for
// the server to change state. We will simulate this with a setTimeout call.
setTimeout(function() {
this.emit('running');
}.bind(this), 3000);
};
module.exports = AwsServer;
// somewhere_else.js
var AwsServer = require('./aws_server')
var newServer = new AwsServer('some_data');
newServer.on('running', function() {
console.log('New instance is running');
});
newServer.createInstance();
Your best bet would be to add a shell script on the servers init.d, which will run whenever the server is stopped or started.
Probably useless for this question but other ways of programmatically detecting whether an instance on is by using Amazon's EC2 shell tools:
ec2-describe-instance-status <ec2 instance id>
As described here. Which will return blank if the machine is not running, and data about it if it is.

Resources