added es7 async functionality to increase code simplicity

This commit is contained in:
casperlamboo 2015-10-12 12:33:33 +02:00
parent 0d4d864211
commit c831a7cc02
14 changed files with 347 additions and 260 deletions

View File

@ -5,7 +5,8 @@ System.config({
"babelOptions": { "babelOptions": {
"optional": [ "optional": [
"runtime" "runtime"
] ],
"stage": 0
}, },
"paths": { "paths": {
"github:*": "jspm_packages/github/*", "github:*": "jspm_packages/github/*",

View File

@ -1,21 +1,88 @@
import Doodle3DManager from 'src/doodle3dmanager.js'; import Doodle3DManager from 'src/doodle3dmanager.js';
var list = document.getElementById('list'); let list = document.getElementById('list');
var doodle3DManager = new Doodle3DManager(); let doodle3DManager = new Doodle3DManager();
doodle3DManager.addEventListener('boxappeared', (event) => { doodle3DManager.addEventListener('boxappeared', async (event) => {
var box = event.box; let box = event.box;
var node = document.createElement('li'); var row = document.createElement('tr');
node.innerHTML = box.boxData.wifiboxid; row.style.color = 'black';
list.appendChild(node);
var id = document.createElement('td');
var state = document.createElement('td');
var localIP = document.createElement('td');
var bed = document.createElement('td');
var bedTarget = document.createElement('td');
var bufferedLines = document.createElement('td');
var currentLine = document.createElement('td');
var hasControl = document.createElement('td');
var hotend = document.createElement('td');
var hotendTarget = document.createElement('td');
var totalLines = document.createElement('td');
row.appendChild(id);
row.appendChild(localIP);
row.appendChild(state);
row.appendChild(currentLine);
row.appendChild(bufferedLines);
row.appendChild(totalLines);
row.appendChild(hotend);
row.appendChild(hotendTarget);
row.appendChild(bed);
row.appendChild(bedTarget);
row.appendChild(hasControl);
id.innerHTML = box.boxData.wifiboxid;
localIP.innerHTML = box.boxData.localip;
document.getElementById('table').appendChild(row);
function update (event) {
let data = event.state;
state.innerHTML = data.state;
if (data.state !== 'disconnected' && data.state !== 'connecting' && data.state !== 'unknown') {
bed.innerHTML = data.bed;
bedTarget.innerHTML = data.bed_target;
bufferedLines.innerHTML = data.buffered_lines;
currentLine.innerHTML = data.current_line;
hasControl.innerHTML = data.has_control;
hotend.innerHTML = data.hotend;
hotendTarget.innerHTML = data.hotend_target;
state.innerHTML = data.state;
totalLines.innerHTML = data.total_lines;
}
else {
bed.innerHTML = '';
bedTarget.innerHTML = '';
bufferedLines.innerHTML = '';
currentLine.innerHTML = '';
hasControl.innerHTML = '';
hotend.innerHTML = '';
hotendTarget.innerHTML = '';
totalLines.innerHTML = '';
}
};
box.setAutoUpdate(true, 1000);
function update (event) {
console.log(event);
}
box.addEventListener('update', update);
box.addEventListener('disconnect', (event) => {
box.removeEventListener('update', update);
});
}); });
doodle3DManager.addEventListener('boxdisappeared', (event) => { doodle3DManager.addEventListener('boxdisappeared', (event) => {
var box = event.box; let box = event.box;
for (var node of list.children) { for (let node of list.children) {
if (node.innerHTML === box.boxData.wifiboxid) { if (node.innerHTML === box.boxData.wifiboxid) {
list.removeChild(node); list.removeChild(node);
break; break;
@ -23,4 +90,4 @@ doodle3DManager.addEventListener('boxdisappeared', (event) => {
} }
}); });
doodle3DManager.setAutoUpdate(true); doodle3DManager.setAutoUpdate(true, 1000);

View File

@ -1,22 +1,45 @@
<!DOCTYPE> <!DOCTYPE>
<html> <html>
<head> <head>
<title>Doodle3D Box</title> <title>Doodle3D Box</title>
<script type="text/javascript" src="../jspm_packages/system.js"></script> <style>
<script type="text/javascript" src="../config.js"></script> table, th, td {
border: 1px solid #dddddd;
font-size: 15px;
font-family: Verdana, Geneva, Tahoma, Arial, Helvetica, sans-serif;
line-height: 20px;
}
</style>
<script type="text/javascript"> <script type="text/javascript" src="../jspm_packages/system.js"></script>
System.import('example/app.js'); <script type="text/javascript" src="../config.js"></script>
</script>
</head> <script type="text/javascript">
<body> System.import('./app.js');
</script>
<p>Doodle3D WiFi-Boxes</p> </head>
<ul id='list'></ul> <table style="width:100%">
<tbody id="table">
<tr>
<th>ID</th>
<th>Local IP</th>
<th>State</th>
<th>Current Line</th>
<th>Buffered Lines</th>
<th>Total Lines</th>
<th>Hotend</th>
<th>Hotend Target</th>
<th>Bed</th>
<th>Bed Target</th>
<th>Has Control</th>
</tr>
</tbody>
</table>
</body> <body>
</body>
</html> </html>

View File

@ -5,17 +5,17 @@ export default class {
this.api = api; this.api = api;
} }
get (keys) { get (...keys) {
return rest.get(this.api + 'config/?' + keys.join('=&') + '='); return rest.get(`${this.api}config/?${keys.join('=&')}=`);
} }
getAll () { getAll () {
return rest.get(this.api + 'config/all'); return rest.get(`${this.api}config/all`);
} }
set (data) { set (data) {
var scope = this; var scope = this;
return rest.post(this.api + 'config', data); return rest.post(`${this.api}config`, data);
} }
} }

View File

@ -7,6 +7,7 @@ import PrinterAPI from './printerapi.js';
import SketchAPI from './sketchapi.js'; import SketchAPI from './sketchapi.js';
import SystemAPI from './systemapi.js'; import SystemAPI from './systemapi.js';
import UpdateAPI from './updateapi.js'; import UpdateAPI from './updateapi.js';
import {sleep} from './utils.js';
export default class extends EventDispatcher { export default class extends EventDispatcher {
constructor (boxData) { constructor (boxData) {
@ -26,12 +27,14 @@ export default class extends EventDispatcher {
this.alive = false; this.alive = false;
this.autoUpdate = false; this.autoUpdate = false;
this.state = {}; this.state = {};
this.maxBatchSize = 10*1024;
this.maxBufferSize = 1024*1024;
this.fullBufferTimeout = 10000;
} }
setAutoUpdate (autoUpdate = true, updateInterval = 1000) { setAutoUpdate (autoUpdate = true, updateInterval = 1000) {
this.updateInterval = updateInterval; this.updateInterval = updateInterval;
if (this.autoUpdate === autoUpdate) { if (this.autoUpdate === autoUpdate) {
@ -41,67 +44,115 @@ export default class extends EventDispatcher {
this.autoUpdate = autoUpdate; this.autoUpdate = autoUpdate;
if (autoUpdate) { if (autoUpdate) {
this._initLoop(); this._update();
} }
return this; return this;
} }
_initLoop () { checkAlive () {
return new Promise(async (resolve, reject) => {
var request = this.network.alive(); let alive;
try {
request.then(() => { await this.network.alive();
alive = true;
this.alive = true; }
catch (error) {
this.dispatchEvent({ alive = false;
type: 'connect' }
});
this._updateStateLoop();
});
request.catch((error) => {
if (this.alive) {
this.alive = false;
if (alive !== this.alive) {
this.dispatchEvent({ this.dispatchEvent({
type: 'disconnect' type: alive ? 'connect' : 'disconnect'
}); });
} }
setTimeout(() => { this.alive = alive;
this._initLoop(); resolve(alive);
}, this.updateInterval);
}); });
} }
_updateStateLoop () { sendGCode (gcode) {
return new Promise(async (resolve, reject) => {
this.info.status().then((state) => { let printerState = await this.printer.state();
this.state = state; if (printerState.state !== 'idle') {
reject(`Cannot print, print state is ${printerState.state}`);
this.dispatchEvent({ return;
type: 'update',
state
});
if (this.autoUpdate) {
setTimeout(() => {
this._updateStateLoop();
}, this.updateInterval);
} }
}).catch((error) => { if (!gcode.endsWith('\n')) {
if (this.autoUpdate) { gcode += '\n';
setTimeout(() => {
this._initLoop();
}, this.updateInterval);
} }
this._currentBatch = 0;
let lastIndex = 0;
let start = true;
while (lastIndex !== gcode.length) {
let index = gcode.lastIndexOf('\n', lastIndex + this.maxBatchSize);
let batch = gcode.substring(lastIndex, index);
let progress = await this.printer.progress();
if (progress['buffered_lines'] + batch.length < this.maxBufferSize) {
lastIndex = index + 1; //skip next \n
await this._sendBatch(batch, start);
start = false;
}
else {
await sleep(this.fullBufferTimeout);
}
}
resolve();
}); });
} }
}
async _update () {
let alive = await this.checkAlive();
if (alive) {
while (this.autoUpdate) {
try {
this.state = await this.info.status();
this.dispatchEvent({
type: 'update',
state: this.state
});
await sleep(this.updateInterval);
}
catch (error) {
this._update();
break;
}
}
}
else {
await sleep(this.updateInterval);
this._update();
}
}
_sendBatch (gcode, index) {
return new Promise (async (resolve, reject) => {
try {
let start = index === 0;
let first = start;
let printRequest = await this.printer.print(gcode, first, start);
console.log(`batch sent: ${index}`, printRequest);
}
catch (error) {
await sleep(1000);
await this._sendBatch(gcode, index);
}
resolve();
});
}
}

View File

@ -1,43 +1,97 @@
import * as rest from './restapi.js'; import * as rest from './restapi.js';
import Doodle3DAPI from './doodle3dapi.js'; import Doodle3DAPI from './doodle3dapi.js';
import EventDispatcher from 'casperlamboo/EventDispatcher'; import EventDispatcher from 'casperlamboo/EventDispatcher';
import {sleep} from './utils.js';
export default class extends EventDispatcher { export default class extends EventDispatcher {
constructor () { constructor () {
super(); super();
this.api = 'http://connect.doodle3d.com/api/';
this.boxes = []; this.boxes = [];
this.nonServerBoxes = [{ this.nonServerBoxes = [{
wifiboxid: 'Wired Printer', wifiboxid: 'Wired Printer',
localip: '192.168.5.1' localip: '192.168.5.1'
}, { }/*, {
wifiboxid: 'Node JS Server', wifiboxid: 'Node JS Server',
localip: '127.0.0.1:2000' localip: '127.0.0.1:3000'
}]; }*/];
this.checkNonServerBoxes = true; this.checkNonServerBoxes = true;
this.api = 'http://connect.doodle3d.com/api/';
this.autoUpdate = false;
} }
setAutoUpdate (autoUpdate = true, rate = 5000) { setAutoUpdate (autoUpdate = true, updateInterval = 1000) {
this.updateInterval = updateInterval;
if (this.autoUpdate === autoUpdate) {
return;
}
this.autoUpdate = autoUpdate;
if (autoUpdate) { if (autoUpdate) {
this._update(); this._update();
if (this.interval !== undefined) {
clearInterval(this.interval);
}
this.interval = setInterval(() => {
this._update();
}, rate);
}
else if (this.interval !== undefined) {
clearInterval(this.interval);
delete this.interval;
} }
return this; return this;
} }
async _update () {
while (this.autoUpdate) {
await this._checkAlive();
await this._checkNew();
await sleep(this.updateInterval);
}
}
_checkAlive () {
return new Promise(async (resolve, reject) => {
for (let box of this.boxes) {
let alive = await box.checkAlive();
if (!alive) {
this._removeBox(box);
}
}
resolve();
});
}
_checkNew () {
return new Promise(async (resolve, reject) => {
try {
let boxes = await rest.get(`${this.api}list.php`);
if (this.checkNonServerBoxes) {
boxes = boxes.concat(this.nonServerBoxes);
}
let knownIPs = this.boxes.map((box) => box.boxData.localip);
for (let boxData of boxes) {
if (knownIPs.indexOf(boxData.localip) === -1) {
let box = new Doodle3DAPI(boxData);
let alive = await box.checkAlive();
if (alive) {
this._addBox(box);
}
}
}
resolve();
}
catch (error) {
console.warn('fail connecting to Doodle3D server');
}
});
}
_addBox (box) { _addBox (box) {
this.boxes.push(box); this.boxes.push(box);
@ -48,7 +102,7 @@ export default class extends EventDispatcher {
} }
_removeBox (box) { _removeBox (box) {
var index = this.boxes.indexOf(box); let index = this.boxes.indexOf(box);
if (index !== -1) { if (index !== -1) {
this.boxes.splice(index, 1); this.boxes.splice(index, 1);
this.dispatchEvent({ this.dispatchEvent({
@ -57,52 +111,4 @@ export default class extends EventDispatcher {
}); });
} }
} }
}
_update () {
this._checkAlive();
this._checkNew();
}
_checkAlive () {
for (var box of this.boxes) {
((box) => {
var request = box.network.alive();
request.catch(() => {
this._removeBox(box);
});
})(box);
}
}
_checkNew () {
var request = rest.get(this.api + 'list.php');
request.then((boxes) => {
if (this.checkNonServerBoxes) {
boxes = boxes.concat(this.nonServerBoxes);
}
var knownIPs = this.boxes.map((box) => box.boxData.localip);
for (var boxData of boxes) {
if (knownIPs.indexOf(boxData.localip) === -1) {
var box = new Doodle3DAPI(boxData);
((box) => {
var request = box.network.alive();
request.then((data, msg) => {
this._addBox(box);
});
request.catch(() => {
console.log(`failed to connect with ${box.boxData.wifiboxid}`);
});
})(box);
}
}
});
request.catch(() => {
console.warn('fail connecting to Doodle3D server');
});
}
}

View File

@ -6,18 +6,18 @@ export default class {
} }
get () { get () {
return rest.get(this.api + 'info'); return rest.get(`${this.api}info`);
} }
status () { status () {
return rest.get(this.api + 'info/status'); return rest.get(`${this.api}info/status`);
} }
downloadLogFiles () { downloadLogFiles () {
window.location = this.api + 'info/logfiles'; window.location = `${this.api}info/logfiles`;
} }
acces () { acces () {
return rest.get(this.api + 'info/access'); return rest.get(`${this.api}info/access`);
} }
} }

View File

@ -6,47 +6,50 @@ export default class {
} }
scan () { scan () {
return rest.get(this.api + 'network/scan'); return rest.get(`${this.api}network/scan`);
} }
known () { known () {
return rest.get(this.api + 'network/known'); return rest.get(`${this.api}network/known`);
} }
status () { status () {
return rest.get(this.api + 'network/status'); return rest.get(`${this.api}network/status`);
} }
assosiate (ssid, phrase = null, recreate = false) { assosiate (ssid, phrase, recreate = false) {
var data = {ssid, recreate}; var data = {
if (phrase) data.phrase = phrase; ssid,
recreate,
phrase
};
return rest.post(this.api + 'network/associate', data); return rest.post(`${this.api}network/associate`, data);
} }
disassosiate () { disassosiate () {
//not tested //not tested
return rest.post(this.api + 'network/disassociate', {}); return rest.post(`${this.api}network/disassociate`, {});
} }
openAccesPoint () { openAccesPoint () {
//not tested //not tested
return rest.post(this.api + 'network/openap', {}); return rest.post(`${this.api}network/openap`, {});
} }
remove (ssid) { remove (ssid) {
return rest.post(this.api + 'network/remove', { return rest.post(`${this.api}network/remove`, {
'ssid': ssid 'ssid': ssid
}); });
} }
signin () { signin () {
return rest.get(this.api + 'network/signin'); return rest.get(`${this.api}network/signin`);
} }
alive () { alive () {
return rest.get(this.api + 'network/alive'); return rest.get(`${this.api}network/alive`);
} }
} }

View File

@ -3,106 +3,43 @@ import * as rest from './restapi.js';
export default class { export default class {
constructor (api) { constructor (api) {
this.api = api; this.api = api;
this._printBatches = [];
this._currentBatch = 0;
this.maxBatchSize = 10*1024;
this.maxBufferedLines = 1024*1024;
this.fullBufferTimeout = 10000;
} }
temperature () { temperature () {
return rest.get(this.api + 'printer/temperature'); return rest.get(`${this.api}printer/temperature`);
} }
progress () { progress () {
return rest.get(this.api + 'printer/progress'); return rest.get(`${this.api}printer/progress`);
} }
state () { state () {
return rest.get(this.api + 'printer/state'); return rest.get(`${this.api}printer/state`);
} }
listAll () { listAll () {
return rest.get(this.api + 'printer/listall'); return rest.get(`${this.api}printer/listall`);
} }
heatup () { heatup () {
return rest.post(this.api + 'printer/heatup', {}); return rest.post(`${this.api}printer/heatup`, {});
} }
sendGCode (gcode) { print (gcode = '', first = false, start = false, last) {
if (!gcode.endsWith('\n')) { let data = {
gcode += '\n'; gcode,
} first,
start,
last
};
this._currentBatch = 0; return rest.post(`${this.api}printer/print`, data);
var lastIndex = 0;
while (lastIndex !== gcode.length) {
var index = gcode.lastIndexOf('\n', lastIndex + this.maxBatchSize);
var batch = gcode.substring(lastIndex, index);
lastIndex = index + 1; //skip next return
this._printBatches.push(batch);
}
this._sendBatch();
}
_sendBatch () {
var gcode = this._printBatches.shift();
var start = (this._currentBatch === 0) ? true : false;
var first = (this._currentBatch === 0) ? true : false;
var last = (this._printBatches.length === 0) ? true : false; //only for the node js server
var printRequest = this.print(gcode, start, first, last);
printRequest.then((data) => {
console.log('batch sent: ' + this._currentBatch, data);
var progressRequest = this.progress()
progressRequest.then((progress) => {
if (this._printBatches.length > 0) {
if (progress['buffered_lines'] + this.maxBatchSize < this.maxBufferedLines) {
this._currentBatch ++;
this._sendBatch();
}
else {
setTimeout(() => {
this._sendBatch();
}, this.fullBufferTimeout);
}
}
else {
console.log('Finish sending gcode to printer');
}
});
});
printRequest.catch((error) => {
this._printBatches.unshift(gcode);
setTimeout(() => {
this._sendBatch();
}, 1000);
});
}
print (gcode = '', first = false, start = false, last = false) {
var data = {gcode, first, start}
if (last) data.last = last;
return rest.post(this.api + 'printer/print', data);
} }
stop (gcode = '') { stop (gcode = '') {
this._currentBatch = 0; this._currentBatch = 0;
this._printBatches = []; this._printBatches = [];
return rest.post(this.api + 'printer/stop', {gcode}); return rest.post(`${this.api}printer/stop`, {gcode});
} }
} }

View File

@ -1,15 +1,12 @@
import $ from 'jquery'; import $ from 'jquery';
export function get (url) { export function get (url) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
$.ajax({ $.ajax({
url: url, url: url,
dataType: 'json', dataType: 'json',
timeout: 5000, timeout: 5000,
success: (response) => { success: (response) => {
if (response.status === 'success') { if (response.status === 'success') {
resolve(response.data, response.msg); resolve(response.data, response.msg);
} }
@ -17,15 +14,12 @@ export function get (url) {
reject(response.msg); reject(response.msg);
} }
} }
}).fail(reject); }).fail(reject);
}); });
} }
export function post (url, data) { export function post (url, data) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
$.ajax({ $.ajax({
url: url, url: url,
type: 'POST', type: 'POST',
@ -33,14 +27,12 @@ export function post (url, data) {
dataType: 'json', dataType: 'json',
timeout: 10000, timeout: 10000,
success: (response) => { success: (response) => {
if (response.status === 'success') { if (response.status === 'success') {
resolve(response.data); resolve(response.data);
} }
else { else {
reject(response.msg); reject(response.msg);
} }
} }
}).fail(reject); }).fail(reject);
}); });

View File

@ -6,20 +6,20 @@ export default class {
} }
getSketch (id) { getSketch (id) {
return rest.get(this.api + 'sketch/?id=' + id); return rest.get(`${this.api}sketch/?id=${id}`);
} }
set (data = '') { set (data = '') {
return rest.post(this.api + 'sketch', { return rest.post(`${this.api}sketch`, {
data data
}); });
} }
status () { status () {
return rest.get(this.api + 'sketch/status'); return rest.get(`${this.api}sketch/status`);
} }
clear () { clear () {
return rest.post(this.api + 'sketch/clear'); return rest.post(`${this.api}sketch/clear`);
} }
} }

View File

@ -6,6 +6,6 @@ export default class {
} }
versions () { versions () {
return rest.get(this.api + 'system/fwversions'); return rest.get(`${this.api}system/fwversions`);
} }
} }

View File

@ -6,24 +6,24 @@ export default class {
} }
status () { status () {
return rest.get(this.api + 'update/status'); return rest.get(`${this.api}update/status`);
} }
download () { download () {
//not tested //not tested
return rest.post(this.api + 'update/download', {}); return rest.post(`${this.api}update/download`, {});
} }
install () { install () {
//not tested //not tested
return rest.post(this.api + 'update/install', {}); return rest.post(`${this.api}update/install`, {});
} }
clear () { clear () {
//not tested //not tested
return rest.post(this.api + 'update/clear', {}); return rest.post(`${this.api}update/clear`, {});
} }
} }

7
src/utils.js Normal file
View File

@ -0,0 +1,7 @@
export function sleep (time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}