import { test } from 'tap'; import SmoothieRunner from '../src/server/controllers/Smoothie/SmoothieRunner'; // $10 - Status report mask:binary // Report Type | Value // Machine Position | 1 // Work Position | 2 // Planner Buffer | 4 // RX Buffer | 8 // Limit Pins | 16 test('SmoothieRunnerLineParserResultStatus: all zeroes in the mask ($10=0)', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Idle', }); t.end(); }); const line = ''; runner.parse(line); }); test('SmoothieRunnerLineParserResultStatus: old status format', (t) => { t.test('6-axis', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Idle', mpos: { x: '200.0000', y: '200.0000', z: '0.0000', a: '0.0000', b: '0.0000', c: '0.0000', }, wpos: { x: '200.0000', y: '200.0000', z: '0.0000', } }); t.end(); }); const line = ''; runner.parse(line); }); t.end(); }); test('SmoothieRunnerLineParserResultStatus: new status format', (t) => { t.test('6-axis', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Idle', mpos: { x: '200.0000', y: '200.0000', z: '0.0000', a: '0.0000', b: '0.0000', c: '0.0000', }, wpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, feedrate: '4000.0', feedrateOverride: '100.0', }); t.end(); }); const line = ''; runner.parse(line); }); t.test('Laser', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Idle', mpos: { x: '200.0000', y: '200.0000', z: '0.0000', a: '0.0000', b: '0.0000', c: '0.0000', }, wpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, feedrate: '4000.0', feedrateOverride: '100.0', laserPower: '0.0000', laserIntensity: '0.8000', }); t.end(); }); const line = ''; runner.parse(line); }); t.test('Home', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Home', mpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, wpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, currentFeedrate: '4000.0', feedrate: '4000.0', feedrateOverride: '100.0', }); t.end(); }); const line = ''; runner.parse(line); }); t.test('Run', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Run', mpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, wpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, currentFeedrate: '4000.0', feedrate: '4000.0', feedrateOverride: '100.0', }); t.end(); }); const line = ''; runner.parse(line); }); t.test('Idle', (t) => { const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { t.equal(raw, ''); t.same(status, { activeState: 'Idle', mpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, wpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, feedrate: '4000.0', feedrateOverride: '100.0', }); t.end(); }); const line = ''; runner.parse(line); }); t.test('state transition', (t) => { let lineNumber = 0; const lines = [ '', '', ]; const expectedResults = [ { // Run activeState: 'Run', mpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, wpos: { x: '15.8250', y: '15.8250', z: '0.0000', }, currentFeedrate: '4000.0', feedrate: '4000.0', feedrateOverride: '100.0', }, { // Idle activeState: 'Idle', mpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, wpos: { x: '200.0000', y: '200.0000', z: '0.0000', }, feedrate: '4000.0', feedrateOverride: '100.0', } ]; const runner = new SmoothieRunner(); runner.on('status', ({ raw, ...status }) => { const index = lineNumber - 1; t.equal(raw, lines[index]); t.same(status, expectedResults[index]); if (lineNumber === lines.length) { t.end(); } }); lines.forEach((line, index) => { lineNumber = index + 1; runner.parse(line); }); }); t.end(); }); test('SmoothieRunnerLineParserResultOk', (t) => { const runner = new SmoothieRunner(); runner.on('ok', ({ raw }) => { t.equal(raw, 'ok'); t.end(); }); const line = 'ok'; runner.parse(line); }); test('SmoothieRunnerLineParserResultError', (t) => { const runner = new SmoothieRunner(); runner.on('error', ({ raw, message }) => { t.equal(raw, 'error: Expected command letter'); t.equal(message, 'Expected command letter'); t.end(); }); const line = 'error: Expected command letter'; runner.parse(line); }); test('SmoothieRunnerLineParserResultAlarm', (t) => { const runner = new SmoothieRunner(); runner.on('alarm', ({ raw, message }) => { t.equal(raw, 'ALARM: Probe fail'); t.equal(message, 'Probe fail'); t.end(); }); const line = 'ALARM: Probe fail'; runner.parse(line); }); test('SmoothieRunnerLineParserResultParserState', (t) => { test('#1', (t) => { const runner = new SmoothieRunner(); runner.on('parserstate', ({ raw, ...parserstate }) => { t.equal(raw, '[G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F2540. S0.]'); t.same(parserstate, { modal: { motion: 'G0', // G0, G1, G2, G3, G38.2, G38.3, G38.4, G38.5, G80 wcs: 'G54', // G54, G55, G56, G57, G58, G59 plane: 'G17', // G17: xy-plane, G18: xz-plane, G19: yz-plane units: 'G21', // G20: Inches, G21: Millimeters distance: 'G90', // G90: Absolute, G91: Relative feedrate: 'G94', // G93: Inverse Time Mode, G94: Units Per Minutes program: 'M0', spindle: 'M5', coolant: 'M9' }, tool: '0', feedrate: '2540.', spindle: '0.' }); t.equal(runner.getTool(), 0); t.end(); }); const line = '[G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F2540. S0.]'; runner.parse(line); }); test('#2', (t) => { const runner = new SmoothieRunner(); runner.on('parserstate', ({ raw, ...parserstate }) => { t.equal(raw, '[G0 G54 G17 G21 G90 G94 M0 M5 M7 M8 T2 F2540. S0.]'); t.same(parserstate, { modal: { motion: 'G0', // G0, G1, G2, G3, G38.2, G38.3, G38.4, G38.5, G80 wcs: 'G54', // G54, G55, G56, G57, G58, G59 plane: 'G17', // G17: xy-plane, G18: xz-plane, G19: yz-plane units: 'G21', // G20: Inches, G21: Millimeters distance: 'G90', // G90: Absolute, G91: Relative feedrate: 'G94', // G93: Inverse Time Mode, G94: Units Per Minutes program: 'M0', spindle: 'M5', coolant: ['M7', 'M8'] }, tool: '2', feedrate: '2540.', spindle: '0.' }); t.equal(runner.getTool(), 2); t.end(); }); const line = '[G0 G54 G17 G21 G90 G94 M0 M5 M7 M8 T2 F2540. S0.]'; runner.parse(line); }); t.end(); }); test('SmoothieRunnerLineParserResultParameters:G54,G55,G56,G57,G58,G59,G28,G30,G92', (t) => { const lines = [ '[G54:0.000,0.000,0.000]', '[G55:0.000,0.000,0.000]', '[G56:0.000,0.000,0.000]', '[G57:0.000,0.000,0.000]', '[G58:0.000,0.000,0.000]', '[G59:0.000,0.000,0.000]', '[G28:0.000,0.000,0.000]', '[G30:0.000,0.000,0.000]', '[G92:0.000,0.000,0.000]' ]; const runner = new SmoothieRunner(); let i = 0; runner.on('parameters', ({ name, value, raw }) => { if (i < lines.length) { t.equal(raw, lines[i]); } if (name === 'G54') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G55') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G56') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G57') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G58') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G59') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G28') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G30') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } if (name === 'G92') { t.same(value, { x: '0.000', y: '0.000', z: '0.000' }); } ++i; if (i >= lines.length) { t.end(); } }); lines.forEach(line => { runner.parse(line); }); }); test('SmoothieRunnerLineParserResultParameters:TLO', (t) => { const runner = new SmoothieRunner(); runner.on('parameters', ({ name, value, raw }) => { t.equal(raw, '[TLO:0.000]'); t.equal(name, 'TLO'); t.equal(value, '0.000'); t.end(); }); runner.parse('[TLO:0.000]'); }); test('SmoothieRunnerLineParserResultParameters:PRB', (t) => { const runner = new SmoothieRunner(); runner.on('parameters', ({ name, value, raw }) => { t.equal(raw, '[PRB:0.000,0.000,1.492:1]'); t.equal(name, 'PRB'); t.same(value, { result: 1, x: '0.000', y: '0.000', z: '1.492' }); t.end(); }); runner.parse('[PRB:0.000,0.000,1.492:1]'); }); test('SmoothieRunnerLineParserResultVersion', (t) => { const runner = new SmoothieRunner(); runner.on('version', ({ raw, ...others }) => { t.equal(raw, 'Build version: edge-3332442, Build date: xxx, MCU: LPC1769, System Clock: 120MHz'); t.same(others, { build: { version: 'edge-3332442', date: 'xxx' }, mcu: 'LPC1769', sysclk: '120MHz' }); t.end(); }); const line = 'Build version: edge-3332442, Build date: xxx, MCU: LPC1769, System Clock: 120MHz'; runner.parse(line); }); test('Not supported output format', (t) => { const runner = new SmoothieRunner(); runner.on('others', ({ raw }) => { t.equal(raw, 'Not supported output format'); t.end(); }); const line = 'Not supported output format'; runner.parse(line); });