mirror of
https://github.com/Doodle3D/Doodle3D-Slicer.git
synced 2025-01-03 16:43:47 +01:00
Add malyan controls
not styled yet
This commit is contained in:
parent
6628b9cf13
commit
de2acfe6be
61
src/interface/MalyanControl.js
Normal file
61
src/interface/MalyanControl.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'proptypes';
|
||||||
|
import muiThemeable from 'material-ui/styles/muiThemeable';
|
||||||
|
import injectSheet from 'react-jss';
|
||||||
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
|
import { sleep, getMalyanStatus } from './utils.js';
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class MalyanControl extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
ip: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
status: null,
|
||||||
|
mounted: true
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount = async () => {
|
||||||
|
const { ip } = this.props;
|
||||||
|
while (this.state.mounted) {
|
||||||
|
const status = await getMalyanStatus(ip).catch(() => null);
|
||||||
|
this.setState({ status });
|
||||||
|
await sleep(1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
home = () => {
|
||||||
|
const { ip } = this.props;
|
||||||
|
fetch(`http://${ip}/set?code=G28`, { method: 'GET' });
|
||||||
|
};
|
||||||
|
|
||||||
|
stop = () => {
|
||||||
|
const { ip } = this.props;
|
||||||
|
fetch(`http://${ip}/set?cmd={P:X}`, { method: 'GET' });
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.setState({ mounted: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { status } = this.state;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{status && <span>
|
||||||
|
<p>Nozzle temperature: {status.nozzleTemperature}/{status.nozzleTargetTemperature}</p>
|
||||||
|
<p>Bed temperature: {status.bedTemperature}/{status.bedTargetTemperature}</p>
|
||||||
|
{status.state === 'printing' && <p>Progress: {status.progress}%</p>}
|
||||||
|
</span>}
|
||||||
|
<FlatButton label="Stop" onTouchTap={this.stop} />
|
||||||
|
<FlatButton label="Home" onTouchTap={this.home} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default muiThemeable()(injectSheet(styles)(MalyanControl));
|
@ -14,6 +14,7 @@ import Menu from 'material-ui/Menu';
|
|||||||
import MenuItem from 'material-ui/MenuItem';
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
import { Tabs, Tab } from 'material-ui/Tabs';
|
import { Tabs, Tab } from 'material-ui/Tabs';
|
||||||
import Settings from './Settings.js';
|
import Settings from './Settings.js';
|
||||||
|
import MalyanControl from './MalyanControl.js';
|
||||||
import ReactResizeDetector from 'react-resize-detector';
|
import ReactResizeDetector from 'react-resize-detector';
|
||||||
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
|
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
|
||||||
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
|
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
|
||||||
@ -334,6 +335,7 @@ class Interface extends React.Component {
|
|||||||
{isSlicing && <p>{progress.action}</p>}
|
{isSlicing && <p>{progress.action}</p>}
|
||||||
{isSlicing && <LinearProgress mode="determinate" value={progress.percentage * 100.0} />}
|
{isSlicing && <LinearProgress mode="determinate" value={progress.percentage * 100.0} />}
|
||||||
</div>
|
</div>
|
||||||
|
{settings && settings.printer === 'doodle3d_printer' && <MalyanControl ip={settings.ip} />}
|
||||||
<div className={classes.sliceButtons}>
|
<div className={classes.sliceButtons}>
|
||||||
{onCancel && <RaisedButton
|
{onCancel && <RaisedButton
|
||||||
label="Cancel"
|
label="Cancel"
|
||||||
|
@ -115,6 +115,32 @@ export function fetchProgress(url, data = {}, onProgress) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getMalyanStatus(ip) {
|
||||||
|
return fetch(`http://${ip}/inquiry`, { method: 'GET' })
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(statusText => {
|
||||||
|
const [nozzleTemperature, nozzleTargetTemperature, bedTemperature, bedTargetTemperature, progress] = statusText.match(/\d+/g);
|
||||||
|
const status = { nozzleTemperature, nozzleTargetTemperature, bedTemperature, bedTargetTemperature, progress };
|
||||||
|
|
||||||
|
switch (statusText.charAt(statusText.length - 1)) {
|
||||||
|
case 'I':
|
||||||
|
status.state = 'idle';
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
status.state = 'printing';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
status.state = 'unknown';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sleep(time) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, time));
|
||||||
|
}
|
||||||
|
|
||||||
const GCODE_SERVER_URL = 'https://gcodeserver.doodle3d.com';
|
const GCODE_SERVER_URL = 'https://gcodeserver.doodle3d.com';
|
||||||
const CONNECT_URL = 'http://connect.doodle3d.com/';
|
const CONNECT_URL = 'http://connect.doodle3d.com/';
|
||||||
|
|
||||||
@ -127,6 +153,10 @@ export async function slice(target, name, mesh, settings, updateProgress) {
|
|||||||
break;
|
break;
|
||||||
case 'WIFI':
|
case 'WIFI':
|
||||||
case 'DOODLE3D-WIFI-BOX':
|
case 'DOODLE3D-WIFI-BOX':
|
||||||
|
if (settings.printer === 'doodle3d_printer') {
|
||||||
|
const { state } = await getMalyanStatus(settings.ip);
|
||||||
|
if (state !== 'idle') throw { message: 'printer must be idle before starting a print', code: 1 };
|
||||||
|
}
|
||||||
steps = 2;
|
steps = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -161,7 +191,7 @@ export async function slice(target, name, mesh, settings, updateProgress) {
|
|||||||
const file = new File([gcode], 'doodle.gcode', { type: 'plain/text' });
|
const file = new File([gcode], 'doodle.gcode', { type: 'plain/text' });
|
||||||
body.append('file', file);
|
body.append('file', file);
|
||||||
|
|
||||||
await fetchProgress(`http://${settings.ip}/set?code=M563 S4`, { method: 'GET' });
|
// await fetchProgress(`http://${settings.ip}/set?code=M563 S4`, { method: 'GET' });
|
||||||
await fetchProgress(`http://${settings.ip}/upload`, { method: 'POST', body }, (progress) => {
|
await fetchProgress(`http://${settings.ip}/upload`, { method: 'POST', body }, (progress) => {
|
||||||
updateProgress({
|
updateProgress({
|
||||||
action: 'Uploading',
|
action: 'Uploading',
|
||||||
|
122
test.js
122
test.js
@ -1,122 +0,0 @@
|
|||||||
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 (
|
|
||||||
<span>
|
|
||||||
<button onTouchTap={this.home} type="button">Home</button>
|
|
||||||
<button onTouchTap={this.status} type="button">Status</button>
|
|
||||||
<button onTouchTap={this.start} type="button">Start</button>
|
|
||||||
<button onTouchTap={this.stop} type="button">Stop</button>
|
|
||||||
<div>
|
|
||||||
<textarea ref="gcode" cols="80" rows="20" defaultValue={CIRCLE} />
|
|
||||||
<button onTouchTap={this.upload} type="button">Upload</button>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render((
|
|
||||||
<Print />
|
|
||||||
), document.getElementById('app'));
|
|
Loading…
Reference in New Issue
Block a user