From d5ea6709679acefb31c8a20e80b7d995df5ef652 Mon Sep 17 00:00:00 2001 From: casperlamboo Date: Tue, 23 Jan 2018 12:19:43 +0100 Subject: [PATCH 1/4] add ip in settings config for the doodle3d printer --- package-lock.json | 21 ++++--- package.json | 1 + src/interface/Settings.js | 56 +++++++++++------ test.js | 122 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 174 insertions(+), 26 deletions(-) create mode 100644 test.js diff --git a/package-lock.json b/package-lock.json index 8e6597c..21fcd11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,8 +54,8 @@ "react-notification-system-redux": "1.2.0", "react-redux": "5.0.6", "react-resize-detector": "1.1.0", - "react-svg-inline": "2.0.1", - "redux-form": "7.2.0", + "react-svg-inline": "2.1.0", + "redux-form": "7.2.1", "redux-undo": "1.0.0-beta9-9-7", "reselect": "3.0.1", "semver": "5.4.1", @@ -6942,9 +6942,9 @@ } }, "react-svg-inline": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/react-svg-inline/-/react-svg-inline-2.0.1.tgz", - "integrity": "sha512-9YVqJ80g1gPWAvD9CS/z4cKPD45ZSMjjzwxFAmQJiMEoAo1Ajhz92WirXag3ftltDN5lPNkVWx/KOnEWB/PaMQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/react-svg-inline/-/react-svg-inline-2.1.0.tgz", + "integrity": "sha512-GzRID5IcEQ8dnnaUtTb9MDTAbhuaOiVKKAVLgrCNuehHsg3DuZbe82bjc9JhmPv0zsDWhDrJwzADNgzEvE6VeQ==", "requires": { "classnames": "2.2.5", "prop-types": "15.6.0" @@ -7058,9 +7058,9 @@ } }, "redux-form": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-7.2.0.tgz", - "integrity": "sha512-qbgeI19drwnm9FeGAotDA1vsZO8q94XF7IxPDuJmSXxDYX2rqzhND6NROahCBJfBK5xM1cchvmgscO2rry1EEw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-7.2.1.tgz", + "integrity": "sha512-KWV+rq+L1QGoRSKoJXbGS8Mw2q4ta5FVyGxW5ZYnAEjXZAukvUCkqDUzobBmOqiRHvrZ3/ssEA7kJFdu7rV8+w==", "requires": { "deep-equal": "1.0.1", "es6-error": "4.1.1", @@ -8271,6 +8271,11 @@ "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" }, + "validate-ip": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/validate-ip/-/validate-ip-1.0.1.tgz", + "integrity": "sha1-615PY+HRq8buRuGK4gaXv1vtBto=" + }, "validate-npm-package-license": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", diff --git a/package.json b/package.json index 8b655e4..473f113 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "react-resize-detector": "^1.1.0", "shortid": "^2.2.8", "three": "^0.88.0", + "validate-ip": "^1.0.1", "webpack-bundle-analyzer": "^2.9.2" }, "devDependencies": { diff --git a/src/interface/Settings.js b/src/interface/Settings.js index ec94401..d28b5ee 100644 --- a/src/interface/Settings.js +++ b/src/interface/Settings.js @@ -18,6 +18,7 @@ import materialSettings from '../settings/material.yml'; import qualitySettings from '../settings/quality.yml'; import update from 'react-addons-update'; import SettingsIcon from 'material-ui-icons/Settings'; +import validateIp from 'validate-ip'; const styles = { textFieldRow: { @@ -79,6 +80,7 @@ class Settings extends React.Component { open: false, name: '', printer: '', + ip: '', error: null }, managePrinter: { @@ -102,25 +104,22 @@ class Settings extends React.Component { let state = _.cloneDeep(this.state); - const removeAddPrinterError = () => { - state = update(state, { addPrinter: { error: { $set: null } } }); - }; - switch (fieldName) { case 'managePrinter.printer': case 'managePrinter.name': + case 'managePrinter.ip': state = _.set(state, fieldName, value); + state = update(state, { managePrinter: { error: { $set: null } } }); break; case 'addPrinter.printer': - state = update(state, { addPrinter: { printer: { $set: value } } }); - state = update(state, { addPrinter: { name: { $set: printerSettings[value].title } } }); - removeAddPrinterError(); - break; - case 'addPrinter.name': - state = update(state, { addPrinter: { name: { $set: value } } }); - removeAddPrinterError(); + case 'addPrinter.ip': + state = _.set(state, fieldName, value); + if (fieldName === 'addPrinter.printer') { + state = update(state, { addPrinter: { name: { $set: printerSettings[value].title } } }); + } + state = update(state, { addPrinter: { error: { $set: null } } }); break; case 'activePrinter': @@ -204,12 +203,13 @@ class Settings extends React.Component { constructSettings(localStorage) { if (!localStorage.active) return defaultSettings; - const { printer, material, quality, advanced } = localStorage.printers[localStorage.active].settings; + const { ip, settings: { printer, material, quality, advanced } } = localStorage.printers[localStorage.active]; let settings = { ...defaultSettings, printer, material, quality + ip }; settings = _.merge({}, settings, printerSettings[printer]); @@ -225,10 +225,14 @@ class Settings extends React.Component { } addPrinter = () => { - const { name, printer } = this.state.addPrinter; + const { name, printer, ip } = this.state.addPrinter; if (!name || !printer) { - this.setState({ addPrinter: { ...this.state.addPrinter, error: 'Please enter a name and printer' } }); + this.setState(update(this.state, { addPrinter: { error: { $set: 'Please enter a name and printer' } } })); + return; + } + if (printer === 'doodle3d_printer' && !validateIp(ip)) { + this.setState(update(this.state, { addPrinter: { error: { $set: 'Please enter a valid IP adress' } } })); return; } @@ -237,7 +241,7 @@ class Settings extends React.Component { active: id, printers: { ...this.state.localStorage.printers, - [id]: { name, settings: { printer, material: 'pla', quality: 'medium', advanced: {} } } + [id]: { name, ip, settings: { printer, material: 'pla', quality: 'medium', advanced: {} } } } }; this.setState({ localStorage }); @@ -250,11 +254,22 @@ class Settings extends React.Component { }; editPrinter = () => { - const { localStorage: { active, printers }, managePrinter: { printer, name } } = this.state; + const { localStorage: { active, printers }, managePrinter: { printer, name, ip } } = this.state; + + if (!name) { + this.setState(update(this.state, { managePrinter: { error: { $set: 'Please enter a name' } } })); + return; + } + if (printer === 'doodle3d_printer' && !validateIp(ip)) { + this.setState(update(this.state, { managePrinter: { error: { $set: 'Please enter a valid IP adress' } } })); + return; + } + const localStorage = update(this.state.localStorage, { printers: { [active]: { name: { $set: name }, + ip: { $set: ip }, settings: { printer: { $set: printer } } @@ -288,7 +303,7 @@ class Settings extends React.Component { closeAddPrinterDialog = () => this.setAddPrinterDialog(false); openAddPrinterDialog = () => this.setAddPrinterDialog(true); - setAddPrinterDialog = (open) => this.setState({ addPrinter: { name: '', printer: '', error: null, open } }); + setAddPrinterDialog = (open) => this.setState({ addPrinter: { ip: '', name: '', printer: '', error: null, open } }); closeManagePrinterDialog = () => this.setManagePrinterDialog(false); openManagePrinterDialog = () => this.setManagePrinterDialog(true); @@ -299,7 +314,9 @@ class Settings extends React.Component { managePrinter: { open, name: printers[active].name, - printer: printers[active].settings.printer + ip: printers[active].ip, + printer: printers[active].settings.printer, + error: null } }); } @@ -415,6 +432,7 @@ class Settings extends React.Component { ))} + {(addPrinter.printer === 'doodle3d_printer') && } {addPrinter.error &&

{addPrinter.error}

} + {(managePrinter.printer === 'doodle3d_printer') && } + {managePrinter.error &&

{managePrinter.error}

}
); diff --git a/test.js b/test.js new file mode 100644 index 0000000..d448d41 --- /dev/null +++ b/test.js @@ -0,0 +1,122 @@ +import 'babel-polyfill' +import React from 'react'; +import { render } from 'react-dom'; +import injectTapEventPlugin from 'react-tap-event-plugin'; +// import './fetch.js'; + +injectTapEventPlugin(); + +const IP = 'http://10.0.0.109'; +const DEFAULT_GCODE = `; Generated with Doodle3D Slicer V0.0.18 +G28 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +G1 X30 Y30 +G1 X90 Y30 +; test +`; + +const CIRCLE = `; Generated with Doodle3D Slicer V0.0.18 +G28 +G1 X50 Y70 +G1 X56.180339887498945 Y69.02113032590307 +G1 X61.75570504584947 Y66.18033988749895 +G1 X66.18033988749895 Y61.75570504584947 +G1 X69.02113032590307 Y56.180339887498945 +G1 X70 Y50 +G1 X69.02113032590307 Y43.819660112501055 +G1 X66.18033988749895 Y38.24429495415054 +G1 X61.75570504584947 Y33.819660112501055 +G1 X56.18033988749895 Y30.97886967409693 +G1 X50 Y30 +G1 X43.819660112501055 Y30.978869674096927 +G1 X38.24429495415054 Y33.819660112501055 +G1 X33.819660112501055 Y38.24429495415053 +G1 X30.97886967409693 Y43.81966011250105 +G1 X30 Y49.99999999999999 +G1 X30.978869674096927 Y56.180339887498945 +G1 X33.81966011250105 Y61.75570504584946 +G1 X38.24429495415053 Y66.18033988749895 +G1 X43.81966011250105 Y69.02113032590307 +; test +`; + +// export function fetch(url, data = {}, onProgress) { +// return new Promise((resolve, reject) => { +// const request = new Request(url, data); +// const xhr = new XMLHttpRequest(); +// +// xhr.onload = () => { +// const { status, statusText, responseURL: url } = xhr; +// resolve(new Response(xhr.response, { status, statusText, url })); +// } +// xhr.onerror = () => reject(new TypeError('Network request failed')); +// xhr.ontimeout = () => reject(new TypeError('Network request failed')); +// +// xhr.open(request.method, url); +// +// if (request.credentials === 'include') { +// xhr.withCredentials = true +// } else if (request.credentials === 'omit') { +// xhr.withCredentials = false +// } +// if (xhr.upload && onProgress) xhr.upload.onprogress = onProgress; +// if (xhr.responseType) xhr.responseType = 'blob'; +// +// request.headers.forEach((value, name) => { +// xhr.setRequestHeader(name, value) +// }); +// +// xhr.send(data.body); +// }); +// } + +class Print extends React.Component { + home = () => fetch(`${IP}/set?code=G28`, { method: 'GET', mode: 'no-cors' }); + status = () => fetch(`${IP}/inquiry`, { method: 'GET', mode: 'no-cors' }) + .then(response => response.text()) + .then(result => console.log('result: ', result)); + start = () => fetch(`${IP}/set?code=M565`, { method: 'GET', mode: 'no-cors' }); + stop = () => fetch(`${IP}/set?cmd={P:X}`, { method: 'GET', mode: 'no-cors' }); + upload = async () => { + const gcode = this.refs.gcode.value; + + const headers = new Headers(); + headers.append('Content-Disposition', 'form-data; name="file"; filename="doodle.gcode"'); + headers.append('Content-Type', 'application/octet-stream'); + headers.append('Accept', 'application/json'); + + const body = new FormData(); + const file = new File([gcode], 'doodle.gcode', { type: 'application/octet-stream' }); + body.append('file', file); + + const result = await fetch(`${IP}/upload`, { method: 'POST', mode: 'no-cors', headers, body }); + }; + + render() { + return ( + + + + + +
+