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 { Tabs, Tab } from 'material-ui/Tabs';
|
||||
import Settings from './Settings.js';
|
||||
import MalyanControl from './MalyanControl.js';
|
||||
import ReactResizeDetector from 'react-resize-detector';
|
||||
import JSONToSketchData from 'doodle3d-core/shape/JSONToSketchData';
|
||||
import createSceneData from 'doodle3d-core/d3/createSceneData.js';
|
||||
@ -334,6 +335,7 @@ class Interface extends React.Component {
|
||||
{isSlicing && <p>{progress.action}</p>}
|
||||
{isSlicing && <LinearProgress mode="determinate" value={progress.percentage * 100.0} />}
|
||||
</div>
|
||||
{settings && settings.printer === 'doodle3d_printer' && <MalyanControl ip={settings.ip} />}
|
||||
<div className={classes.sliceButtons}>
|
||||
{onCancel && <RaisedButton
|
||||
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 CONNECT_URL = 'http://connect.doodle3d.com/';
|
||||
|
||||
@ -127,6 +153,10 @@ export async function slice(target, name, mesh, settings, updateProgress) {
|
||||
break;
|
||||
case 'WIFI':
|
||||
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;
|
||||
break;
|
||||
default:
|
||||
@ -161,7 +191,7 @@ export async function slice(target, name, mesh, settings, updateProgress) {
|
||||
const file = new File([gcode], 'doodle.gcode', { type: 'plain/text' });
|
||||
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) => {
|
||||
updateProgress({
|
||||
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