Skip to content

Commit f8e613f

Browse files
committed
Prepare for initial release
1 parent edcde86 commit f8e613f

File tree

8 files changed

+300
-374
lines changed

8 files changed

+300
-374
lines changed

package.json

+8-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,15 @@
3636
"peerDependencies": {},
3737
"dependencies": {
3838
"classnames": "^2.2.5",
39+
"cncjs-controller": "^1.0.1",
3940
"detect-browser": "^1.10.0",
4041
"font-awesome": "^4.7.0",
42+
"lodash.get": "^4.4.2",
43+
"lodash.mapvalues": "^4.6.0",
4144
"node-emoji": "^1.8.1",
4245
"normalize.css": "^7.0.0",
4346
"prop-types": "^15.0.0",
47+
"qs": "^6.5.1",
4448
"react": "^0.14.0 || ^15.0.0",
4549
"react-dom": "^0.14.0 || ^15.0.0",
4650
"socket.io-client": "^1.7.4",
@@ -51,15 +55,15 @@
5155
"devDependencies": {
5256
"babel-cli": "~6.26.0",
5357
"babel-core": "~6.26.0",
54-
"babel-eslint": "~7.2.3",
58+
"babel-eslint": "~8.0.0",
5559
"babel-loader": "~7.1.2",
5660
"babel-plugin-transform-decorators-legacy": "~1.3.4",
5761
"babel-preset-es2015": "~6.24.1",
5862
"babel-preset-react": "~6.24.1",
5963
"babel-preset-stage-0": "~6.24.1",
6064
"coveralls": "~2.13.1",
6165
"css-loader": "~0.28.7",
62-
"eslint": "~4.6.1",
66+
"eslint": "~4.7.1",
6367
"eslint-config-trendmicro": "~1.0.0",
6468
"eslint-loader": "~1.9.0",
6569
"eslint-plugin-import": "~2.7.0",
@@ -76,8 +80,8 @@
7680
"stylus-loader": "~3.0.1",
7781
"tap": "~10.7.2",
7882
"url-loader": "~0.5.9",
79-
"webpack": "~3.5.5",
80-
"webpack-dev-server": "~2.7.1",
83+
"webpack": "~3.6.0",
84+
"webpack-dev-server": "~2.8.2",
8185
"write-file-webpack-plugin": "~4.1.0"
8286
}
8387
}

src/constants/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// Metric and Imperial units
2+
export const IMPERIAL_UNITS = 'in';
3+
export const METRIC_UNITS = 'mm';
4+
15
// Controller
26
export const GRBL = 'Grbl';
37
export const SMOOTHIE = 'Smoothie';

src/index.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
import qs from 'qs';
12
import controller from './lib/controller';
2-
import qs from './lib/querystring';
33
import log from './lib/log';
44
import './styles/vendor.styl';
55
import './styles/app.styl';
66

7-
const params = query.parse(window.location.search.slice(1));
7+
// Query Parameters
8+
// * token (required): An authentication token to enable secure communication.
9+
// * host (optional): Specifies the host to connect to. Defaults to an empty string.
10+
// * widget (optional): Specifies a folder name under 'src/widgets'. Defaults to 'ReactApp'.
11+
const params = qs.parse(window.location.search.slice(1));
812

913
window.addEventListener('message', (event) => {
1014
// TODO: event.origin
@@ -20,7 +24,8 @@ window.addEventListener('message', (event) => {
2024
}
2125

2226
const { type, payload } = { ...action };
23-
if (type === 'update') {
27+
if (type === 'change') {
28+
// Do not close the port if the port parameter is empty
2429
const { port } = { ...payload };
2530
port && controller.openPort(port);
2631
}
@@ -45,12 +50,12 @@ import(`./widgets/${widget}`)
4550
}
4651

4752
// Connect to a socket.io server
48-
const host = ''; // e.g. http://localhost:8000
53+
const host = params.host || ''; // e.g. http://localhost:8000
4954
const options = {
5055
query: 'token=' + params.token
5156
};
5257
controller.connect(host, options, () => {
53-
// Post a message to the parent window
58+
// Use the postMessage API for inter-frame communication
5459
window.parent.postMessage({
5560
token: params.token,
5661
action: {

src/lib/controller.js

+2-279
Original file line numberDiff line numberDiff line change
@@ -1,283 +1,6 @@
1+
import Controller from 'cncjs-controller';
12
import io from 'socket.io-client';
2-
import ensureArray from './ensure-array';
3-
import log from './log';
4-
import {
5-
GRBL,
6-
SMOOTHIE,
7-
TINYG,
8-
WORKFLOW_STATE_IDLE
9-
} from '../constants';
103

11-
const noop = () => {};
12-
13-
class CNCController {
14-
socket = null;
15-
16-
callbacks = {
17-
//
18-
// Socket.IO Events
19-
//
20-
// Fired upon a connection including a successful reconnection.
21-
'connect': [],
22-
// Fired upon a connection error.
23-
'connect_error': [],
24-
// Fired upon a connection timeout.
25-
'connect_timeout': [],
26-
// Fired when an error occurs.
27-
'error': [],
28-
// Fired upon a disconnection.
29-
'disconnect': [],
30-
// Fired upon a successful reconnection.
31-
'reconnect': [],
32-
// Fired upon an attempt to reconnect.
33-
'reconnect_attempt': [],
34-
// Fired upon an attempt to reconnect.
35-
'reconnecting': [],
36-
// Fired upon a reconnection attempt error.
37-
'reconnect_error': [],
38-
// Fired when couldn't reconnect within reconnectionAttempts.
39-
'reconnect_failed': [],
40-
41-
//
42-
// System Events
43-
//
44-
'startup': [],
45-
'config:change': [],
46-
'task:start': [],
47-
'task:finish': [],
48-
'task:error': [],
49-
'serialport:list': [],
50-
'serialport:change': [],
51-
'serialport:open': [],
52-
'serialport:close': [],
53-
'serialport:error': [],
54-
'serialport:read': [],
55-
'serialport:write': [],
56-
'gcode:load': [],
57-
'gcode:unload': [],
58-
'feeder:status': [],
59-
'sender:status': [],
60-
'workflow:state': [],
61-
'Grbl:state': [],
62-
'Grbl:settings': [],
63-
'Smoothie:state': [],
64-
'Smoothie:settings': [],
65-
'TinyG:state': [],
66-
'TinyG:settings': []
67-
};
68-
69-
context = {
70-
xmin: 0,
71-
xmax: 0,
72-
ymin: 0,
73-
ymax: 0,
74-
zmin: 0,
75-
zmax: 0
76-
};
77-
78-
// User-defined baud rates and ports
79-
baudrates = [];
80-
ports = [];
81-
82-
loadedControllers = [GRBL, SMOOTHIE, TINYG];
83-
port = '';
84-
type = '';
85-
state = {};
86-
settings = {};
87-
workflowState = WORKFLOW_STATE_IDLE;
88-
89-
get connected() {
90-
return !!(this.socket && this.socket.connected);
91-
}
92-
connect(host = '', options = {}, next = noop) {
93-
if (typeof next !== 'function') {
94-
next = noop;
95-
}
96-
97-
this.socket && this.socket.destroy();
98-
this.socket = io.connect(host, options);
99-
100-
Object.keys(this.callbacks).forEach((eventName) => {
101-
if (!this.socket) {
102-
return;
103-
}
104-
105-
this.socket.on(eventName, (...args) => {
106-
//log.debug(`socket.on('${eventName}'):`, args);
107-
108-
if (eventName === 'serialport:open') {
109-
const { controllerType, port } = { ...args[0] };
110-
log.debug(`Established a connection to the serial port ${JSON.stringify(port)}`);
111-
112-
this.port = port;
113-
this.type = controllerType;
114-
}
115-
if (eventName === 'serialport:close') {
116-
const port = this.port;
117-
log.debug(`The serial port ${JSON.stringify(port)} is disconected`);
118-
119-
this.port = '';
120-
this.type = '';
121-
this.state = {};
122-
this.settings = {};
123-
this.workflowState = WORKFLOW_STATE_IDLE;
124-
}
125-
if (eventName === 'workflow:state') {
126-
this.workflowState = args[0];
127-
}
128-
if (eventName === 'Grbl:state') {
129-
this.type = GRBL;
130-
this.state = { ...args[0] };
131-
}
132-
if (eventName === 'Grbl:settings') {
133-
this.type = GRBL;
134-
this.settings = { ...args[0] };
135-
}
136-
if (eventName === 'Smoothie:state') {
137-
this.type = SMOOTHIE;
138-
this.state = { ...args[0] };
139-
}
140-
if (eventName === 'Smoothie:settings') {
141-
this.type = SMOOTHIE;
142-
this.settings = { ...args[0] };
143-
}
144-
if (eventName === 'TinyG:state') {
145-
this.type = TINYG;
146-
this.state = { ...args[0] };
147-
}
148-
if (eventName === 'TinyG:settings') {
149-
this.type = TINYG;
150-
this.settings = { ...args[0] };
151-
}
152-
153-
this.callbacks[eventName].forEach((callback) => {
154-
callback.apply(callback, args);
155-
});
156-
});
157-
});
158-
159-
this.socket.on('startup', (data) => {
160-
const { loadedControllers, baudrates, ports } = { ...data };
161-
162-
this.loadedControllers = ensureArray(loadedControllers);
163-
164-
// User-defined baud rates and ports
165-
this.baudrates = ensureArray(baudrates);
166-
this.ports = ensureArray(ports);
167-
168-
if (next) {
169-
next(null);
170-
171-
// The callback can only be called once
172-
next = null;
173-
}
174-
});
175-
}
176-
disconnect() {
177-
this.socket && this.socket.destroy();
178-
this.socket = null;
179-
}
180-
on(eventName, callback) {
181-
let callbacks = this.callbacks[eventName];
182-
if (!callbacks) {
183-
log.error('Undefined event name:', eventName);
184-
return;
185-
}
186-
if (typeof callback === 'function') {
187-
callbacks.push(callback);
188-
}
189-
}
190-
off(eventName, callback) {
191-
let callbacks = this.callbacks[eventName];
192-
if (!callbacks) {
193-
log.error('Undefined event name:', eventName);
194-
return;
195-
}
196-
if (typeof callback === 'function') {
197-
callbacks.splice(callbacks.indexOf(callback), 1);
198-
}
199-
}
200-
openPort(port, options, callback) {
201-
this.socket && this.socket.emit('open', port, options, callback);
202-
}
203-
closePort(port, callback) {
204-
this.socket && this.socket.emit('close', port, callback);
205-
}
206-
listPorts() {
207-
this.socket && this.socket.emit('list');
208-
}
209-
// @param {string} cmd The command string
210-
// @example Example Usage
211-
// - Load G-code
212-
// controller.command('gcode:load', name, gcode, context /* optional */, callback)
213-
// - Unload G-code
214-
// controller.command('gcode:unload')
215-
// - Start sending G-code
216-
// controller.command('gcode:start')
217-
// - Stop sending G-code
218-
// controller.command('gcode:stop', { force: true })
219-
// - Pause
220-
// controller.command('gcode:pause')
221-
// - Resume
222-
// controller.command('gcode:resume')
223-
// - Feed Hold
224-
// controller.command('feedhold')
225-
// - Cycle Start
226-
// controller.command('cyclestart')
227-
// - Status Report
228-
// controller.command('statusreport')
229-
// - Homing
230-
// controller.command('homing')
231-
// - Sleep
232-
// controller.command('sleep')
233-
// - Unlock
234-
// controller.command('unlock')
235-
// - Reset
236-
// controller.command('reset')
237-
// - Feed Override
238-
// controller.command('feedOverride')
239-
// - Spindle Override
240-
// controller.command('spindleOverride')
241-
// - Rapid Override
242-
// controller.command('rapidOverride')
243-
// - Energize Motors
244-
// controller.command('energizeMotors:on')
245-
// controller.command('energizeMotors:off')
246-
// - G-code
247-
// controller.command('gcode', 'G0X0Y0', context /* optional */)
248-
// - Load a macro
249-
// controller.command('macro:load', '<macro-id>', context /* optional */, callback)
250-
// - Run a macro
251-
// controller.command('macro:run', '<macro-id>', context /* optional */, callback)
252-
// - Load file from a watch directory
253-
// controller.command('watchdir:load', '/path/to/file', callback)
254-
command(cmd, ...args) {
255-
const { port } = this;
256-
if (!port) {
257-
return;
258-
}
259-
this.socket && this.socket.emit.apply(this.socket, ['command', port, cmd].concat(args));
260-
}
261-
// @param {string} data The data to write.
262-
// @param {object} [context] The associated context information.
263-
write(data, context) {
264-
const { port } = this;
265-
if (!port) {
266-
return;
267-
}
268-
this.socket && this.socket.emit('write', port, data, context);
269-
}
270-
// @param {string} data The data to write.
271-
// @param {object} [context] The associated context information.
272-
writeln(data, context) {
273-
const { port } = this;
274-
if (!port) {
275-
return;
276-
}
277-
this.socket && this.socket.emit('writeln', port, data, context);
278-
}
279-
}
280-
281-
const controller = new CNCController();
4+
const controller = new Controller(io);
2825

2836
export default controller;

src/lib/ensure-array.js

-11
This file was deleted.

0 commit comments

Comments
 (0)