├── package.json ├── readme.md └── cnc /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "dependencies": { 4 | "serialport": "~1.4.0", 5 | "commander": "~2.2.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Gcode Streamer 2 | 3 | A simple utility I use to stream and REPL Gcode to my personal CNC machine which uses the [TinyG](https://github.com/synthetos/TinyG) driver but should work fine with grbl too. I wasn't able to find anything already made that really worked well. 4 | 5 | My own serial port and baud rate are hardcoded. Feel free to use it as a basis for communicating with your own CNC machine. 6 | 7 | 1. It keeps an internal queue of lines from stdin. 8 | 9 | 2. It waits for a response from the driver before sending the next line. 10 | This is important in serial i/o to not exceed the rx buffer which will result in corrupted data. 11 | 12 | 3. It closes the serial port (gracefully) when it sees an M30 13 | 14 | 15 | -------------------------------------------------------------------------------- /cnc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var serialport = require('serialport'); 4 | var SerialPort = serialport.SerialPort; 5 | var repl = require("repl"); 6 | var program = require('commander'); 7 | var exec = require('child_process').spawn; 8 | 9 | program 10 | .version(require('./package.json').version) 11 | .usage('[options] ') 12 | 13 | program.parse(process.argv); 14 | 15 | var args = { 16 | baud: 115200, 17 | portname: '/dev/tty.usbserial-DA00CQJ0', 18 | parity: 'none', 19 | stopbits: 1, 20 | databits: 8, 21 | rtscts: true, 22 | xon: true, 23 | flowControl: true 24 | }; 25 | 26 | var openOptions = { 27 | baudRate: args.baud, 28 | dataBits: args.databits, 29 | parity: args.parity, 30 | stopBits: args.stopbits, 31 | parser: serialport.parsers.readline("\n") 32 | }; 33 | 34 | var port = new SerialPort(args.portname, openOptions); 35 | 36 | var queue = []; 37 | 38 | if(program.args.length > 0) { 39 | var a = Array.prototype.slice(program.args) 40 | exec(a, function (error, stdout, stderr, stdin) { 41 | if (error !== null) { 42 | console.log('exec error: ' + error); 43 | } 44 | else { 45 | stream(stdin, stdout); 46 | } 47 | }); 48 | } 49 | else { 50 | stream(process.stdin, process.stdout); 51 | } 52 | 53 | function stream(stdin, stdout) { 54 | 55 | port.on("open", function () { 56 | 57 | port.flush(); 58 | 59 | var closing = false; 60 | var sending = false; 61 | 62 | function dequeue() { 63 | var cmd = queue.shift(); 64 | 65 | if(!cmd) { 66 | if(closing) { 67 | process.exit(0); 68 | } 69 | return; 70 | } 71 | 72 | sending = true; 73 | port.write(cmd, function (err) { 74 | if (err) { 75 | console.log(err); 76 | } 77 | sending = false; 78 | }); 79 | } 80 | 81 | function eval(cmd, context, filename, callback) { 82 | cmd = cmd.slice(1,-2) + '\n'; 83 | queue.push(cmd); 84 | 85 | if(!sending) { 86 | dequeue(); 87 | } 88 | 89 | if(cmd.match(/M30/i)) { 90 | closing = true; 91 | // port.close(); 92 | } 93 | } 94 | 95 | port.on('data', function (data) { 96 | console.log(data); 97 | dequeue(); 98 | }); 99 | 100 | port.on('error', function (err) { 101 | console.log(err); 102 | }); 103 | 104 | port.on('close', function () { 105 | process.exit(0); 106 | }); 107 | 108 | repl.start({ 109 | prompt: "", 110 | input: stdin, 111 | output: stdout, 112 | eval: eval, 113 | ignoreUndefined: true 114 | }); 115 | }); 116 | } 117 | --------------------------------------------------------------------------------