Skip to content

Instantly share code, notes, and snippets.

@robbles
Created November 27, 2012 19:50
Show Gist options
  • Save robbles/4156572 to your computer and use it in GitHub Desktop.
Save robbles/4156572 to your computer and use it in GitHub Desktop.
Create virtual serial ports that hold open an unreliable bluetooth connection with socat
#!/usr/bin/env node
var spawn = require('child_process').spawn;
var extname = require('path').extname;
// where to store the virtual ports while running
var virtual_port_dir = '/tmp/';
// socat displays this when successfully connected
var success_str = 'starting data transfer loop';
// socat binary
//var socat = './testsocat.sh';
var socat = 'socat';
// terminal colors
red   = '\033[31m';
blue  = '\033[34m';
green  = '\033[32m';
reset = '\033[0m';
var paths = process.argv.slice(2);
var numPaths = paths.length;
if(paths.length === 0) {
console.log('usage connectSerialPorts.js [serial port paths]');
process.exit(1);
}
console.log('Connecting ' + numPaths + ' paired serial ports');
var connectPort = function(index, path, callback) {
var self;
var virtual_port = virtual_port_dir + extname(path).slice(1);
console.log('Starting connection to ' + path + ' at ' + virtual_port);
var cliArgs = [
'-d','-d','-d', // Extra debugging
'pty,link=' + virtual_port + ',raw,echo=0', // Create virtual serial port
'file:' + path // Connect to serial port
];
// Run socat to connect virtual serial port to real one
console.log(blue + socat + cliArgs.join(' ') + reset);
child = spawn(socat, cliArgs);
child.on('exit', function() {
if(index in activeStreams) {
// We lost an active connection
console.log(red + 'Connection lost for ' + path + reset);
} else {
console.log('Failed to connect to ' + path);
}
delete activeStreams[index];
// Restart self
children[self.index] = connectPort(index, path, callback);
});
var handleOutput = function(buffer) {
var data = buffer.toString();
//console.log(index + ' stdout: ' + data);
if(data.search('starting data transfer loop') !== -1) {
self.ready = true;
console.log(self.path, ': stream is now active at ' + self.port);
callback();
activeStreams[index] = true;
if(Object.keys(activeStreams).length === numPaths) {
console.log('\n' + green + 'READY TO GO!!!' + reset + '\n');
}
}
};
child.stdout.on('data', handleOutput);
child.stderr.on('data', handleOutput);
self = {
index: index,
path: path,
port: virtual_port,
child: child,
ready: false
};
return self;
};
var children = Object.create(null);
var activeStreams = Object.create(null);
// connect one at a time, waiting for callback
var i = 0;
var connectNext = function() {
if(!paths.length) { return; }
i = i + 1;
var path = paths.shift();
children[i] = connectPort(i, path, connectNext);
};
connectNext();
process.on('SIGINT', function() {
process.exit();
});
process.on('exit', function() {
for(var i=0; i<numPaths; i++) {
console.log('Killing ' + i);
children[i].child.kill('SIGINT');
children[i].child.kill();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment