node.js and bluetooth barcode-scanner - node.js

I am struggling quite a while now to get a solid, long-term connection to a bluetooth barcode scanner from Inateck using node.js. The process is running in the background (linux, no input-focus) that's why I configured the scanner as a SPP device.
The connection is basically working as long as the scanner doesn't automatically switch off to save power, which is after about 5 minutes.
My first approach was to use the bluetooth-serial-port package. It discovers the scanner, reads the barcodes but when the scanner switches off, I don't know how to re-connect. I added an interval timer to check the connection and try to connect again if isOpen() returns false (which works once). When I press the button on the scanner it switches back on and I can re-connect but after a view seconds isOpen() returns false even if the connection is established, and I don't get any further readings. Here is my code:
var btSerial = new (require('bluetooth-serial-port')).BluetoothSerialPort();
var btInterval = null;
btSerial.on('found', function (address, name) {
btSerial.findSerialPortChannel(address, function (channel) {
if (address === '00:06:11:68:15:81') {
btSerial.connect(address, channel, function () {
console.log('connected to ' + address);
btInterval = setInterval(function () {
if (!btSerial.isOpen()) {
btSerial.close();
clearInterval(btInterval);
console.log('lost connection - try to reconnect');
btSerial.inquire();
}
}, 5000);
}, function () {
console.log('cannot connect to ' + address);
});
}
}, function () {
console.log('found nothing');
});
});
btSerial.on('finished', function () {
console.log('finished');
});
btSerial.on('data', function (buffer) {
console.log(buffer.toString('utf-8'));
});
btSerial.inquire();
The output looks like this:
finished
connected to 00:06:11:68:15:81
found nothing
... scanning works ...
lost connection - try to reconnect
finished
connected to 00:06:11:68:15:81
... scanning works ...
lost connection - try to reconnect
finished
... that's it - no more scans ...
^C
An other idea was to use nodes fs() an read directly from '/dev/rfcomm0'.
scanner = fs.createReadStream('/dev/rfcomm0', {bufferSize: 1});
scanner.on('open', function () {
logger.info('Scanner connected');
});
scanner.on('end', function () {
logger.info('End of data stream');
});
scanner.on('close', function () {
logger.info('Scanner disconnected');
});
scanner.on('error', function (error) {
logger.error('Scanner error');
});
scanner.on('data', function (chunk) {
logger.info(chunk.toString('ascii', 0, 13));
}
});
});
Connecting is done by the OS automatically when reading from the device and I do receive the codes via on('data',..). But I do have the same problem when the scanner switches off after a while. I do receive the on('close',..) event but reconnecting using fs.createReadStream() again doesn't work any more.
Maybe someone of you already had to deal which such a problem and can give me a hint how to handle this. I appreciate every suggestion.
Thanks,
Max

That's not the way I wanted to go for but a bash script to launch my node app when the scanner is available, does the job:
#!/bin/bash
echo "Press CTRL+C to stop..."
while :
do
if hcitool scan | grep -q "00:06:11:68:15:81"; then
# BT scanner found
node .
fi
sleep 1
done

Related

Node stream pipeline stops prematurely

Think of this piece of code as a relay between a NAT-ted service (input) and an external service (output) that wants to communicate with the input.
This relay is on a public server and opens two ports in order to relay:
port 4040 where input connects and forwards the TCP traffic from target service
port 4041 where some external client connects to the relay
The relay should pipe what it receives from input on port 4040 to the external client on port 4041.
I can see both services connecting to the relay but the data flow just stops after, what I suspect the output socket closing. In the following example I used a stream.pipeline but I also tried with simple .pipe directly on the sockets with same results
import net from "net"
import stream from "stream";
export default () => {
const inputServer = net.createServer();
const outputServer = net.createServer();
inputServer.listen(4040, "0.0.0.0", () => {
console.log('TCP Server is running on port ' + 4040 + '.');
});
outputServer.listen(4041, "0.0.0.0", () => {
console.log('TCP Server is running on port ' + 4041 + '.');
});
let inSocket = null;
inputServer.on('connection', (sock) => {
inSocket = sock;
});
outputServer.on('connection', (sock) => {
if (inSocket) {
stream.pipeline(inSocket, sock, (err) => {
if (err) {
console.error('Pipeline failed.', err);
} else {
console.log('Pipeline succeeded.');
}
})
stream.pipeline(sock, inSocket, (err) => {
if (err) {
console.error('Pipeline failed.', err);
} else {
console.log('Pipeline succeeded.');
}
})
}
});
}
My goal is to keep an open socket to the input service and relay with any output will connect.
data flow just stops after, what I suspect the output socket closing
pipeline or .pipe() will automatically close the output stream when the input stream ends so it won't keep your input stream open for successive input stream connections.
Using .pipe(), you can override that behavior by passing an option:
inSocket.pipe(sock, {end: false});
and
sock.pipe(inSocket, {end: false});
You will then need some separate error handling for each stream as .pipe() doesn't do as complete error handling as pipeline() does.
In this way, you let each stream close itself when the client chooses rather than having the server close it when a given streaming operation is complete.
I don't see a similar option for pipeline().
I'm also curious how you plan to use this. Do you intend for there to be one long connected inSocket and many separate connections to the outputServer? Do you intend or need more than one outputServer connection at once? Or just one at at time. Since you're not auto destroying, I wonder if you need to do some manual cleanup (unpiping, for example) when any socket disconnects? .pipe() is also famous for not unwinding all its event listeners which can sometimes lead to GC issues if you don't manually clean up things properly.

Acting as a modbus slave through RTU - communication questions

I am using the following code to simulate a modbus slave device:
const modbus = require('jsmodbus')
const SerialPort = require('serialport')
const options = {
baudRate: 115200
}
const socket = new SerialPort("COM4", options)
const server = new modbus.server.RTU(socket)
server.on('connect', function (client) {
console.log("in connect")
console.log(client);
});
server.on('connection', function (client) {
console.log("in connection")
console.log(client);
});
server.on('readHoldingRegisters', function (adr, len) {
console.log("in readHoldingRegisters")
console.log("adr: " + adr);
console.log("len: " + len);
});
The code above does actually simulate a device. The master I have set up can see a slave device when I run this code. The problem is that I can't seem to get the server functions to reach their console.log sections.
I have two theories.
First, my slave device uses the jsmodbus library to simulate a server and my master device uses modbus-serial to communicate. Could this cause a problem?
My second theory is that the code I have above is running all at once and doesn't look around or stay open to see future communications. How would I solve this?
I am open to new theories as well. My goal is eventually to pass modbus data back to the master through the server.on commands.
Edit
I know for sure there is data coming in if I read the data on the serial port directly:
socket.on('readable', function () {
console.log('Data:', socket.read()) //prints incoming buffer data
});
I still am not getting data through the server commands.

How to prevent repeated responses from Node.js server

We're running into a problem where we're getting multiple responses sent from our Node server to a web client which are connected by a socket server (socket.io). By listening with Docklight, I can see that we're really only getting a single response from the serial device, but for some reason the Node server is sending multiples, and they accumulate, so the first time you send a serial command (and it doesn't matter what commands) might only get a couple, next time a couple more, next time a couple more and so on. So if you run several serial commands, you'll get back lots of multiple responses.
Our environment is Windows 7 64 bit, Node V 4.5.0, serialport V 4.0.1. However, this needs to run on Windows, Mac & Linux when we're done. The dev team (me & one other guy) are both fairly new to Node, but otherwise capable developers.
I think what's happening is I'm not using the .flush() & .drain() functions properly and the serialport buffer still contains serial data. Our proprietary devices return either S>, or <Executed/> prompts when a command has completed, so I store the serial response in a buffer until I see one or the other, then process the data (in this example just providing a boolean response whether the device is responding with one or the other or not). For example, if I send a <CR><LF> to one of our devices, it should respond with S> (or <Executed/> depending).
The client calls into the server with this:
socket.on('getDeviceConnected', readDeviceResponse);
function readDeviceResponse(isDeviceResponding) {
console.log('getDeviceConnected');
console.log(isDeviceResponding);
}
function getDeviceConnected() {
console.log("Sending carriage return / line feed.");
socket.emit('getDeviceConnected', '\r\n');
}
And on the server, here's what I'm trying:
socket.on('getDeviceConnected', function (connectionData) {
//write over serial buffer before the write occurs to prevent command accumulation in the buffer.
serialBuffer = '';
sbeSerialPort.write(connectionData, function (err, results) {
//since there's no way to tell if the serial device hasn't responded, set a time out to return a false after allowing one second to elapse
setTimeout(function () {
console.log('Inside getDeviceConnected setTimeout');
console.log('Is serial device responding:', isSerialDeviceResponding);
if (!isSerialDeviceResponding) {
console.log('Serial device timed out.');
socket.emit('getDeviceConnected', false);
}
}, 1000);
if (err) {
console.log('Serial port error level:', err);
}
if (results) {
if (results === 2) {
console.log('Serial port is responding');
}
}
});
sbeSerialPort.on('data', function (serialData) {
isSerialDeviceResponding = true;
console.log('Does S> prompt exist?', serialData.lastIndexOf('S>'));
while(!serialData.lastIndexOf('S>') > -1 || !serialData.lastIndexOf('<Executed/>') > -1){
serialBuffer += serialData;
break;
}
if (isSerialDeviceResponding) {
socket.emit('getDeviceConnected', true);
isSerialDeviceResponding = true;
}
sbeSerialPort.flush(function (err, results) {
if (err) {
console.log(err);
return;
}
if(results){
console.log('Serial port flush return code:', results);
}
});
});
I'm not very sure about the .flush() implementation here, and I've omitted the .drain() part because neither of them seems to do much of anything (assuming they were correctly implemented).
How do I insure that there is no data left in the serialport buffer when the .write() command is complete? Or do you see other problems with how I'm handling the serial data?
Edit, Source code up on pastebin.com:
Server.js
Client.js
HTML

Open terminal, execute command, and enter interactive mode

I am writing a home automation web app. I have music that streams from Google music to my speakers and I use vlc to output the sound. What I cannot do is seem to pause the song remotely. For example, cvlc url will open and stream the url, then it enters an interactive mode where pause can be typed and it will pause.
When I try to do this from my node.js app, nothing happens. It just continues to play.
var terminal = require('child_process').spawn('bash');
terminal.stdout.on('data', function (data) {
console.log(data);
});
terminal.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
terminal.stdin.write('cvlc "' + req.url +'" & \n');
terminal.stdin.write('pause');
try putting a '\n' after you pause command:
terminal.stdin.write('pause\n');
Also, I am not familiar with cvlc, yet, if you start it in the BG, not sure that you can write to its stdin, hence it might ignore all in all your 'pause' command, did you try invoking it without the '&'?
Also, why start a bash and then run cvlc? Why not:
var terminal = require('child_process').spawn('cvlc');
Last but not least, are you sure the default path is sufficient?
I never actually figured this out via terminal. Instead I used VLC's http server option and then did get requests to control pause and play.
Spawn:
var term = spawn.spawn('cvlc',['-I', 'http',req.url,'localhost:8080']);
Pause:
var req = http.get('http://:password#localhost:8080/requests/status.xml?command=pl_pause', function (r) {
r.on('data', function () { /* do nothing */
});
});
And Play:
var reqd = http.get('http://:password#localhost:8080/requests/status.xml?command=pl_play', function (r) {
r.on('data', function () { /* do nothing */
});
r.on('error', function (err) { /* do nothing */
console.log(err)
});
});
Hope that helps someone with a VLC control problem. I was doing this through a headless Raspberry Pi. I was trying to avoid paying for a Chromecast for my speakers and succeeded.

NodeJS socket.io-client doesn't fire 'disconnect' or 'close' events when the server is killed

I've written up a minimal example of this. The code is posted here: https://gist.github.com/1524725
I start my server, start my client, verify that the connection between the two is successful, and finally kill the server with CTRL+C. When the server dies, the client immediately runs to completion and closes without printing the message in either on_client_close or on_client_disconnect. There is no perceptible delay.
From the reading I've done, because the client process is terminating normally there isn't any chance that the STDOUT buffer isn't being flushed.
It may also be worth noting that when I kill the client instead of the server, the server responds as expected, firing the on_ws_disconnect function and removing the client connection from its list of active clients.
32-bit Ubuntu 11.10
Socket.io v0.8.7
Socket.io-client v0.8.7
NodeJS v0.6.0
Thanks!
--- EDIT ---
Please note that both the client and the server are Node.js processes rather than the conventional web browser client and node.js server.
NEW ANSWER
Definitely a bug in io-client. :(
I was able to fix this by modifying socket.io-client/libs/socket.js. Around line 433, I simply moved the this.publish('disconnect', reason); above if (wasConnected) {.
Socket.prototype.onDisconnect = function (reason) {
var wasConnected = this.connected;
this.publish('disconnect', reason);
this.connected = false;
this.connecting = false;
this.open = false;
if (wasConnected) {
this.transport.close();
this.transport.clearTimeouts();
After pressing ctrl+c, the disconnect message fires in roughly ten seconds.
OLD DISCUSSION
To notify client of shutdown events, you would add something like this to demo_server.js:
var logger = io.log;
process.on('uncaughtException', function (err) {
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: err.toString(), stack: err.stack});
}
logger.error(err);
logger.error(err.stack);
//todo should we have some default resetting (restart server?)
app.close();
process.exit(-1);
});
process.on('SIGHUP', function () {
logger.error('Got SIGHUP signal.');
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: 'server disconnected with SIGHUP'});
}
//todo what happens on a sighup??
//todo if you're using upstart, just call restart node demo_server.js
});
process.on('SIGTERM', function() {
logger.error('Shutting down.');
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: 'server disconnected with SIGTERM'});
}
app.close();
process.exit(-1);
});
Of course, what you send in the broadcast.send(...) (or even which command you use there) depends on your preference and client structure.
For the client side, you can tell if the server connection is lost using on('disconnect', ...), which you have in your example:
client.on('disconnect', function(data) {
alert('disconnected from server; reconnecting...');
// and so on...
});

Resources