From 743a1fb79e587ea632dd033ee69bb54a7efa44da Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Fri, 18 Apr 2014 12:32:27 -0600 Subject: [PATCH 1/8] testing telehash over serial support --- lib/bitlash-stream.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/bitlash-stream.js b/lib/bitlash-stream.js index 91dd281..8e3a1d2 100644 --- a/lib/bitlash-stream.js +++ b/lib/bitlash-stream.js @@ -5,6 +5,7 @@ var through = require('through'); var _prompt = ">".charCodeAt(0); var bindexof = require('buffer-indexof'); var empty = new Buffer(0); +var thprefix = new Buffer("telehash:"); module.exports = function(serialPort){ var delim = new Buffer("\n") , state = 'start' @@ -52,6 +53,10 @@ module.exports = function(serialPort){ bufs = empty; } }).on('line',function(buf){ + if(bindexof(buf,thprefix) == 0) + { + console.log("telehash packet"); + } if(state == 'prompt') { // i can ignore data comming from here until a command is issued debug('prompt###',buf+''); From db1a99c044d5ac5a8718e3233a42f72908457e5d Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Fri, 18 Apr 2014 12:59:38 -0600 Subject: [PATCH 2/8] prototyping telehash bridge via serial --- lib/bitlash-stream.js | 16 +++++++++++++++- package.json | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/bitlash-stream.js b/lib/bitlash-stream.js index 8e3a1d2..f734548 100644 --- a/lib/bitlash-stream.js +++ b/lib/bitlash-stream.js @@ -6,6 +6,9 @@ var _prompt = ">".charCodeAt(0); var bindexof = require('buffer-indexof'); var empty = new Buffer(0); var thprefix = new Buffer("telehash:"); +var telehash = require("telehash").init({id:require("path").resolve("id.json"),seeds:{}},function(err){ + if(err) console.log("telehash init failed",err); +}); module.exports = function(serialPort){ var delim = new Buffer("\n") , state = 'start' @@ -55,7 +58,18 @@ module.exports = function(serialPort){ }).on('line',function(buf){ if(bindexof(buf,thprefix) == 0) { - console.log("telehash packet"); + buf = buf.slice(thprefix.length); + var packet = telehash.pdecode(new Buffer(buf.toString(),"hex")); + if(packet) + { + if(packet.js.type == "ping") + { + var js = {type:"pong",from:telehash.parts}; + var out = telehash.pencode(js,telehash.keys["1a"]); + console.log("writing pong",out.toString("hex")); + serialPort.write("telehash(\""+out.toString("hex")+"\")"+"\n"); + } + } } if(state == 'prompt') { // i can ignore data comming from here until a command is issued diff --git a/package.json b/package.json index 7c6598b..e549844 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "url": "https://github.com/Pinoccio/client-node-pinoccio/issues" }, "dependencies": { + "telehash":"0.2.x", "hyperquest": "~0.2.0", "xtend": "~2.1.1", "concat-stream": "~1.2.1", From c681970fc560045e4bb8b69e8421a0da0884cbd4 Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Sun, 20 Apr 2014 19:08:47 -0600 Subject: [PATCH 3/8] more debugging to bridge packets over serial --- lib/bitlash-stream.js | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/bitlash-stream.js b/lib/bitlash-stream.js index f734548..f2377ba 100644 --- a/lib/bitlash-stream.js +++ b/lib/bitlash-stream.js @@ -16,6 +16,21 @@ module.exports = function(serialPort){ , q = [] ; + telehash.deliver("local",function(to,msg){ + console.log("writing bytes",msg.length); + var out; + while(msg.length) + { + out = "telehash(\""+msg.slice(0,100).toString("hex")+"\")\n"; + console.log(out); + serialPort.write(out); + msg = msg.slice(100); + } + out = "telehash(0)\n"; + console.log(out); + serialPort.write(out); + }); + var s = through(function(command){ if(typeof command == 'string') command = {command:command}; if(!command || !command.command) return; @@ -32,6 +47,7 @@ module.exports = function(serialPort){ serialPort.on('data',function(buf){ s.emit('log',buf); s.lastData = Date.now(); +// console.log("BUF",buf); var idx; while((idx = bindexof(buf,delim)) > -1){ @@ -56,19 +72,30 @@ module.exports = function(serialPort){ bufs = empty; } }).on('line',function(buf){ - if(bindexof(buf,thprefix) == 0) + if(bindexof(buf,thprefix) >= 0) { - buf = buf.slice(thprefix.length); - var packet = telehash.pdecode(new Buffer(buf.toString(),"hex")); + var raw = new Buffer(buf.slice(bindexof(buf,thprefix)+thprefix.length).toString(),"hex"); + var packet = telehash.pdecode(raw); if(packet) { + console.log("got packet"); if(packet.js.type == "ping") { - var js = {type:"pong",from:telehash.parts}; - var out = telehash.pencode(js,telehash.keys["1a"]); - console.log("writing pong",out.toString("hex")); - serialPort.write("telehash(\""+out.toString("hex")+"\")"+"\n"); + var js = {type:"pong",from:telehash.parts,trace:packet.js.trace}; + var msg = telehash.pencode(js,telehash.cs["1a"].key); + console.log("writing pong"); + var out = ""; + while(msg.length) + { + out += "telehash(\""+msg.slice(0,100).toString("hex")+"\")"+";"; + msg = msg.slice(100); + } + serialPort.write(out+"telehash(0)\n"); + }else{ + telehash.receive(raw, {type:"local"}); } + }else{ + console.log("packet decode failed?",raw.length,raw.toString("hex")); } } if(state == 'prompt') { From 420f1b6ca6b25134c12cbafd27b0a2932fe9fd29 Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Mon, 21 Apr 2014 06:15:54 -0600 Subject: [PATCH 4/8] convert to using command queue to send, and more debug --- lib/bitlash-stream.js | 54 +++++++++++++++++-------------------------- lib/serial.js | 3 ++- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/lib/bitlash-stream.js b/lib/bitlash-stream.js index f2377ba..46cd5b7 100644 --- a/lib/bitlash-stream.js +++ b/lib/bitlash-stream.js @@ -13,28 +13,26 @@ module.exports = function(serialPort){ var delim = new Buffer("\n") , state = 'start' , running = false - , q = [] + , q = [] ; - telehash.deliver("local",function(to,msg){ - console.log("writing bytes",msg.length); - var out; + function packet2serial(msg) + { while(msg.length) { - out = "telehash(\""+msg.slice(0,100).toString("hex")+"\")\n"; - console.log(out); - serialPort.write(out); + s.command("telehash(\""+msg.slice(0,100).toString("hex")+"\")\n"); msg = msg.slice(100); } - out = "telehash(0)\n"; - console.log(out); - serialPort.write(out); + s.command("telehash(0)\n"); + } + telehash.deliver("local",function(to,msg){ + packet2serial(msg); }); var s = through(function(command){ if(typeof command == 'string') command = {command:command}; if(!command || !command.command) return; - + debug("queuing",command.command); q.push(command); run(); }); @@ -47,21 +45,15 @@ module.exports = function(serialPort){ serialPort.on('data',function(buf){ s.emit('log',buf); s.lastData = Date.now(); -// console.log("BUF",buf); + bufs = Buffer.concat([bufs,buf]); +// console.log("BUF",bufs.length,bufs.toString("utf8")); var idx; - while((idx = bindexof(buf,delim)) > -1){ - bufs = Buffer.concat([bufs,buf.slice(0,idx+1)]); - this.emit('line',bufs); - bufs = empty; - buf = buf.slice(idx+1); - } - - if(buf.length){ - bufs = Buffer.concat([bufs,buf]) + while((idx = bindexof(bufs,delim)) > -1){ + this.emit('line',bufs.slice(0,idx+1)); + bufs = bufs.slice(idx+1); } - if(bufs[0] == _prompt){// the prompt is not followed by a new line this just helps keep the state machine in a single block. // TODO // sometimes when you connect to serial a bit of data from the previous run may get flushed. @@ -72,9 +64,11 @@ module.exports = function(serialPort){ bufs = empty; } }).on('line',function(buf){ - if(bindexof(buf,thprefix) >= 0) + var thindex = bindexof(buf,thprefix); + if(thindex >= 0) { - var raw = new Buffer(buf.slice(bindexof(buf,thprefix)+thprefix.length).toString(),"hex"); + var raw = new Buffer(buf.slice(thindex+thprefix.length).toString(),"hex"); + buf = buf.slice(0,thindex); var packet = telehash.pdecode(raw); if(packet) { @@ -83,14 +77,7 @@ module.exports = function(serialPort){ { var js = {type:"pong",from:telehash.parts,trace:packet.js.trace}; var msg = telehash.pencode(js,telehash.cs["1a"].key); - console.log("writing pong"); - var out = ""; - while(msg.length) - { - out += "telehash(\""+msg.slice(0,100).toString("hex")+"\")"+";"; - msg = msg.slice(100); - } - serialPort.write(out+"telehash(0)\n"); + packet2serial(msg); }else{ telehash.receive(raw, {type:"local"}); } @@ -100,7 +87,7 @@ module.exports = function(serialPort){ } if(state == 'prompt') { // i can ignore data comming from here until a command is issued - debug('prompt###',buf+''); + debug('between###',buf+''); } else { @@ -136,6 +123,7 @@ module.exports = function(serialPort){ state = 'result'; var command = q.shift(); running = command; + debug('sending '+command.command,q.length); serialPort.write(command.command.trim()+"\n"); } } diff --git a/lib/serial.js b/lib/serial.js index d7785e9..b5e0752 100644 --- a/lib/serial.js +++ b/lib/serial.js @@ -64,7 +64,8 @@ module.exports = function(){ function serialConnect(com,cb){ var serialPort = new serialport.SerialPort(com, { - baudrate: 115200 + baudrate: 115200, + buffersize: 16*1024 }); serialPort.on('open',function(err){ if(err) return cb(err); From eeb98257e74ad5947b942466d143c0d20dc1ec0d Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Fri, 25 Apr 2014 18:06:17 -0600 Subject: [PATCH 5/8] add dedicated bridge script to do easier testing --- bridge.js | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 bridge.js diff --git a/bridge.js b/bridge.js new file mode 100644 index 0000000..5683f3f --- /dev/null +++ b/bridge.js @@ -0,0 +1,121 @@ +var serialport = require('serialport'); + +var bindexof = require('buffer-indexof'); +var delim = new Buffer("\n"); +var thprefix = new Buffer("telehash:"); +var prompt = new Buffer("> "); +var telehash = require("telehash"); +//telehash.debug(console.log); +var self = telehash.init({id:require("path").resolve("id.json"),seeds:{}},function(err){ + if(err) console.log("telehash init failed",err); +}); +var serial; + +function die(err) +{ + console.log(err); + process.exit(1); +} + +function packet2serial(msg) +{ + if(!msg.length) return; + var header = new Buffer(3); + header[0] = 42; + header[1] = (msg.length-1) / 256; + header[2] = msg.length - (header[1] * 256); + console.log(" OUT",header[1],header[2],msg.length,msg.toString("hex")); + serial.write(Buffer.concat([header,msg])); +} + +self.deliver("serial",function(to,msg){ + packet2serial(msg); +}); + +serialport.list(function (err, ports) { + if(err) return cb(err); + var com; + ports.forEach(function(port) { + if(port.pnpId.indexOf('Pinoccio') > -1 || port.manufacturer.indexOf('Pinoccio') > -1) com = port.comName; + }); + if(!com) die("no scout found"); + console.log(com); + + serial = new serialport.SerialPort(com, { + baudrate: 115200, + buffersize: 16*1024 + }); + + serial.on('open',function(err){ + if(err) die(err); + process.stdin.pipe(serial); + // send ping hello + setTimeout(function(){ + packet2serial(self.pencode(self.ping())); + },5*1000); + }).on('error',function(err){ + console.error('serial error: ',err); + }).on('data',function(buf){ + while(buf.length) + { + serialIn(buf.slice(0,1)); + buf = buf.slice(1); + } + }); +}); + +function doLine() +{ + // line based handling +} + +function doPacket(raw) +{ + var packet = self.pdecode(raw); + if(packet) + { + self.receive(raw, {type:"serial"}); + }else{ + console.log("packet decode failed?",raw.length,raw.toString("hex")); + } +} + +var bufS = new Buffer(0); +var modeS = 0; +var lenS; +function serialIn(c) +{ + switch(modeS) { + case 0: // first char on new line + // detect read packet start + if(c[0] == 42) return modeS = 2; + // fall through + modeS = 1; + case 1: // normal serial stuff + if(c[0] == 13) return; + process.stdout.write(c); + bufS = Buffer.concat([bufS,c]); + if(c[0] != 10) return; + doLine(bufS); + bufS = new Buffer(0); + modeS = 0; + break; + case 2: // read big len + lenS = 256 * c[0]; + modeS = 3; + break; + case 3: // read big len + lenS += c[0]; + modeS = 4; + break; + case 4: // read packet bytes + bufS = Buffer.concat([bufS,c]); + if(bufS.length != lenS) return; + console.log(" got packet len",lenS,bufS.toString("hex")); + doPacket(bufS); + bufS = new Buffer(0); + modeS = 0; + } +} + + From 465ba25b591bcc27fa279fe3c826a83ab0ec2de1 Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Fri, 25 Apr 2014 18:08:37 -0600 Subject: [PATCH 6/8] cleanups --- .gitignore | 1 + lib/bitlash-stream.js | 60 ++++++++++--------------------------------- 2 files changed, 14 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index c287156..73ad83b 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ results npm-debug.log node_modules pinoccio-api.js +id.json diff --git a/lib/bitlash-stream.js b/lib/bitlash-stream.js index 46cd5b7..91dd281 100644 --- a/lib/bitlash-stream.js +++ b/lib/bitlash-stream.js @@ -5,34 +5,17 @@ var through = require('through'); var _prompt = ">".charCodeAt(0); var bindexof = require('buffer-indexof'); var empty = new Buffer(0); -var thprefix = new Buffer("telehash:"); -var telehash = require("telehash").init({id:require("path").resolve("id.json"),seeds:{}},function(err){ - if(err) console.log("telehash init failed",err); -}); module.exports = function(serialPort){ var delim = new Buffer("\n") , state = 'start' , running = false - , q = [] + , q = [] ; - function packet2serial(msg) - { - while(msg.length) - { - s.command("telehash(\""+msg.slice(0,100).toString("hex")+"\")\n"); - msg = msg.slice(100); - } - s.command("telehash(0)\n"); - } - telehash.deliver("local",function(to,msg){ - packet2serial(msg); - }); - var s = through(function(command){ if(typeof command == 'string') command = {command:command}; if(!command || !command.command) return; - debug("queuing",command.command); + q.push(command); run(); }); @@ -45,15 +28,20 @@ module.exports = function(serialPort){ serialPort.on('data',function(buf){ s.emit('log',buf); s.lastData = Date.now(); - bufs = Buffer.concat([bufs,buf]); -// console.log("BUF",bufs.length,bufs.toString("utf8")); var idx; - while((idx = bindexof(bufs,delim)) > -1){ - this.emit('line',bufs.slice(0,idx+1)); - bufs = bufs.slice(idx+1); + while((idx = bindexof(buf,delim)) > -1){ + bufs = Buffer.concat([bufs,buf.slice(0,idx+1)]); + this.emit('line',bufs); + bufs = empty; + buf = buf.slice(idx+1); } + if(buf.length){ + bufs = Buffer.concat([bufs,buf]) + } + + if(bufs[0] == _prompt){// the prompt is not followed by a new line this just helps keep the state machine in a single block. // TODO // sometimes when you connect to serial a bit of data from the previous run may get flushed. @@ -64,30 +52,9 @@ module.exports = function(serialPort){ bufs = empty; } }).on('line',function(buf){ - var thindex = bindexof(buf,thprefix); - if(thindex >= 0) - { - var raw = new Buffer(buf.slice(thindex+thprefix.length).toString(),"hex"); - buf = buf.slice(0,thindex); - var packet = telehash.pdecode(raw); - if(packet) - { - console.log("got packet"); - if(packet.js.type == "ping") - { - var js = {type:"pong",from:telehash.parts,trace:packet.js.trace}; - var msg = telehash.pencode(js,telehash.cs["1a"].key); - packet2serial(msg); - }else{ - telehash.receive(raw, {type:"local"}); - } - }else{ - console.log("packet decode failed?",raw.length,raw.toString("hex")); - } - } if(state == 'prompt') { // i can ignore data comming from here until a command is issued - debug('between###',buf+''); + debug('prompt###',buf+''); } else { @@ -123,7 +90,6 @@ module.exports = function(serialPort){ state = 'result'; var command = q.shift(); running = command; - debug('sending '+command.command,q.length); serialPort.write(command.command.trim()+"\n"); } } From d6e9c99940a02072c15bbe6f81b5a096b2951005 Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Sat, 26 Apr 2014 09:51:40 -0600 Subject: [PATCH 7/8] massive debug yet, but more solid --- bridge.js | 65 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/bridge.js b/bridge.js index 5683f3f..0742bf3 100644 --- a/bridge.js +++ b/bridge.js @@ -17,18 +17,55 @@ function die(err) process.exit(1); } +// we have to write small blocks to not fill up the device buffer +var outQ = []; +var outBusy = false; +function writer(buf) +{ + if(buf) outQ.push(buf); + if(!outQ.length || outBusy) return; + + // new packet + console.log(" 42",outQ[0].length); + serial.write(new Buffer("2a","hex")); + + outBusy = true; + writeBlock(); +} + +function writeBlock() +{ + if(!outBusy) return; + + // all done + if(outQ[0].length == 0) + { + console.log(" done"); + outQ.shift(); + serial.write(new Buffer("00","hex")); + outBusy = false; + return writer(); + } + + console.log(" block",outQ[0].length); + one = new Buffer(1); + one[0] = (outQ[0].length > 32)? 32 : outQ[0].length; + serial.write(one); + serial.write(outQ[0].slice(0,32)); + outQ[0] = outQ[0].slice(32); +} + function packet2serial(msg) { if(!msg.length) return; - var header = new Buffer(3); - header[0] = 42; - header[1] = (msg.length-1) / 256; - header[2] = msg.length - (header[1] * 256); - console.log(" OUT",header[1],header[2],msg.length,msg.toString("hex")); - serial.write(Buffer.concat([header,msg])); + writer(msg); } +var dedup = ""; self.deliver("serial",function(to,msg){ + // serial is reliable but slow so ignore identical resent packets + if(msg.toString() == dedup) return; + dedup = msg.toString(); packet2serial(msg); }); @@ -48,7 +85,7 @@ serialport.list(function (err, ports) { serial.on('open',function(err){ if(err) die(err); - process.stdin.pipe(serial); +// process.stdin.pipe(serial); // send ping hello setTimeout(function(){ packet2serial(self.pencode(self.ping())); @@ -64,9 +101,9 @@ serialport.list(function (err, ports) { }); }); -function doLine() +function doLine(line) { - // line based handling + if(line.length > 1) process.stdout.write(line); } function doPacket(raw) @@ -81,8 +118,8 @@ function doPacket(raw) } var bufS = new Buffer(0); -var modeS = 0; var lenS; +var modeS = 0; function serialIn(c) { switch(modeS) { @@ -93,7 +130,6 @@ function serialIn(c) modeS = 1; case 1: // normal serial stuff if(c[0] == 13) return; - process.stdout.write(c); bufS = Buffer.concat([bufS,c]); if(c[0] != 10) return; doLine(bufS); @@ -104,9 +140,11 @@ function serialIn(c) lenS = 256 * c[0]; modeS = 3; break; - case 3: // read big len + case 3: // read little len lenS += c[0]; - modeS = 4; + if(lenS == 0) writeBlock(); + // read packet if any + modeS = (lenS) ? 4 : 0; break; case 4: // read packet bytes bufS = Buffer.concat([bufS,c]); @@ -115,6 +153,7 @@ function serialIn(c) doPacket(bufS); bufS = new Buffer(0); modeS = 0; + break; } } From 7d666827f1261d9b5d7e20f886355823ef580f64 Mon Sep 17 00:00:00 2001 From: Jeremie Miller Date: Sat, 26 Apr 2014 14:46:47 -0600 Subject: [PATCH 8/8] clean up debug --- bridge.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bridge.js b/bridge.js index 0742bf3..1f803f3 100644 --- a/bridge.js +++ b/bridge.js @@ -26,7 +26,7 @@ function writer(buf) if(!outQ.length || outBusy) return; // new packet - console.log(" 42",outQ[0].length); +// console.log(" 42",outQ[0].length); serial.write(new Buffer("2a","hex")); outBusy = true; @@ -40,14 +40,14 @@ function writeBlock() // all done if(outQ[0].length == 0) { - console.log(" done"); +// console.log(" done"); outQ.shift(); serial.write(new Buffer("00","hex")); outBusy = false; return writer(); } - console.log(" block",outQ[0].length); +// console.log(" block",outQ[0].length); one = new Buffer(1); one[0] = (outQ[0].length > 32)? 32 : outQ[0].length; serial.write(one);