"through2": "^2.0.3"
}
},
+ "gulp-inline-images": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/gulp-inline-images/-/gulp-inline-images-1.2.6.tgz",
+ "integrity": "sha1-vNNBcHfF3Zvkq42XFO2mZNLVufo=",
+ "requires": {
+ "cheerio": "^0.22.0",
+ "gulp": "^3.9.1",
+ "gulp-util": "^3.0.8",
+ "through2": "^2.0.3"
+ }
+ },
"gulp-pug": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/gulp-pug/-/gulp-pug-4.0.1.tgz",
"vinyl-sourcemaps-apply": "^0.2.0"
}
},
+ "gulp-uglify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.1.tgz",
+ "integrity": "sha512-KVffbGY9d4Wv90bW/B1KZJyunLMyfHTBbilpDvmcrj5Go0/a1G3uVpt+1gRBWSw/11dqR3coJ1oWNTt1AiXuWQ==",
+ "requires": {
+ "gulplog": "^1.0.0",
+ "has-gulplog": "^0.1.0",
+ "lodash": "^4.13.1",
+ "make-error-cause": "^1.1.1",
+ "safe-buffer": "^5.1.2",
+ "through2": "^2.0.0",
+ "uglify-js": "^3.0.5",
+ "vinyl-sourcemaps-apply": "^0.2.0"
+ },
+ "dependencies": {
+ "lodash": {
+ "version": "4.17.11",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
+ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ }
+ }
+ },
"gulp-util": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
"es5-ext": "~0.10.2"
}
},
+ "make-error": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
+ "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g=="
+ },
+ "make-error-cause": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz",
+ "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=",
+ "requires": {
+ "make-error": "^1.2.0"
+ }
+ },
"make-iterator": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
"gulp-concat": "^2.6.1",
"gulp-csso": "^3.0.1",
"gulp-inline": "^0.1.3",
+ "gulp-inline-images": "^1.2.6",
"gulp-pug": "^4.0.1",
"gulp-sourcemaps": "^2.6.4",
"gulp-stylus": "^2.7.0",
+ "gulp-uglify": "^3.0.1",
"jshint": "",
"pug-cli": "^1.0.0-alpha6",
"stylus": ">=0.42.3",
},
- highlight_reason: function () {return this.reason != ''}
+ highlight_reason: function () {return this.reason != ''},
+ plan_time: function () {return this.state.plan_time},
+
+
+ eta: function () {
+ if (this.mach_state != 'RUNNING') return '';
+ var remaining = this.toolpath.time - this.plan_time;
+ var d = new Date();
+ d.setSeconds(d.getSeconds() + remaining);
+ return d.toLocaleString();
+ },
+
+
+ progress: function () {
+ if (!this.toolpath.time) return 0;
+ var p = this.plan_time / this.toolpath.time;
+ return p < 1 ? p : 1;
+ }
},
if (MIN <= value) {
parts.push(value / MIN);
value %= MIN;
- }
- parts.push(value.toFixed(precision));
+ } else parts.push(0);
+
+ parts.push(value);
- for (var i = 0; i < parts.length - 1; i++) {
- parts[i] = parts[i].toFixed(0);
+ for (var i = 0; i < parts.length; i++) {
+ parts[i] = parts[i].toFixed(i == parts.length - 1 ? precision : 0);
if (i && parts[i] < 10) parts[i] = '0' + parts[i];
}
},
- components: {
- 'tool-button': require('./tool-button')
- },
-
-
computed: {
hasPath: function () {return typeof this.toolpath.path != 'undefined'}
},
var step = this.toolpath.path[i];
var newColor = step.rapid ? rapid : cutting;
- if (!i) {
+ // Handle color change
+ if (!i || newColor != color) {
color = newColor;
positions.push(x, y, z);
colors.push.apply(colors, color);
positions.push(x, y, z);
colors.push.apply(colors, color);
-
- // Handle type change
- if (newColor != color) {
- color = newColor;
- positions.push(x, y, z);
- colors.push.apply(colors, color);
- }
}
var geometry = new THREE.BufferGeometry();
+++ /dev/null
-/******************************************************************************\
-
- Copyright 2018. Buildbotics LLC
- All Rights Reserved.
-
- For information regarding this software email:
- Joseph Coffland
- joseph@buildbotics.com
-
- This software is free software: you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation, either version 2.1 of
- the License, or (at your option) any later version.
-
- This software is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the C! library. If not, see
- <http://www.gnu.org/licenses/>.
-
-\******************************************************************************/
-
-'use strict'
-
-
-module.exports = {
- template: '#tool-button-template',
- props: ['name', 'active']
-}
message(:show.sync="confirmUpload")
h3(slot="header") Upload Firmware?
div(slot="body")
- p Are you sure you want to upload firmware <em>{{firmwareName}}</em>?
+ p Are you sure you want to upload firmware #[em {{firmwareName}}]?
p.pure-control-group
label(for="pass") Password
message(:show.sync="hostnameSet")
h3(slot="header") Hostname Set
div(slot="body")
- p Hostname was successfuly set to <strong>{{hostname}}</strong>.
+ p Hostname was successfuly set to #[strong {{hostname}}].
p Rebooting to apply changes.
p Redirecting to new hostname in {{redirectTimeout}} seconds.
div(slot="footer")
label(for="wifi_ch") Channel
select(name="wifi_ch", v-model="wifi_ch")
each ch in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
- option(value="#{ch}")= ch
+ option(value=ch)= ch
.pure-control-group(v-if="wifi_mode != 'disabled'")
label(for="ssid") Network (SSID)
input(name="ssid", v-model="wifi_ssid")
each color in 'red green blue orange cyan purple'.split(' ')
- lineargradient(xlink:href="##{color}", id="#{color}-1",
+ lineargradient(xlink:href="#" + color, id=color + "-1",
gradientunits="userSpaceOnUse", gradienttransform="rotate(180 7 5)",
x1="0", y1="0", x2="15", y2="10")
- lineargradient(xlink:href="##{color}", id="#{color}-2",
+ lineargradient(xlink:href="#" + color, id=color + "-2",
gradientunits="userSpaceOnUse", x1="10", y1="10", x2="40", y2="40")
th(colspan='3') Motion
tr
td
- a(href="#{base}/g-code.html#gcode:g0") G0
+ a(href=`${base}/g-code.html#gcode:g0`) G0
td
td Rapid Move
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g1") G1
+ a(target="_blank", href=`${base}/g-code.html#gcode:g1`) G1
td
td Linear Move
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g2-g3") G2, G3
+ a(target="_blank", href=`${base}/g-code.html#gcode:g2-g3`) G2, G3
td I J K or R, P
td Arc Move
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g4") G4
+ a(target="_blank", href=`${base}/g-code.html#gcode:g4`) G4
td P
td Dwell
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g5") G5
+ a(target="_blank", href=`${base}/g-code.html#gcode:g5`) G5
td I J P Q
td Cubic Spline
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g5.1") G5.1
+ a(target="_blank", href=`${base}/g-code.html#gcode:g5.1`) G5.1
td I J
td Quadratic Spline
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g5.2-g5.3") G5.2
+ a(target="_blank", href=`${base}/g-code.html#gcode:g5.2-g5.3`) G5.2
td P L
td NURBS
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g38") G38.2 - G38.5
+ a(target="_blank", href=`${base}/g-code.html#gcode:g38`) G38.2 - G38.5
td
td Straight Probe
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g33.1") G33.1
+ a(target="_blank", href=`${base}/g-code.html#gcode:g33.1`) G33.1
td K
td Rigid Tapping
th(colspan='3') Tool Control
tr
td
- a(href="#{base}/other-code.html#sec:select-tool") T
+ a(href=`${base}/other-code.html#sec:select-tool`) T
td
td Select Tool
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m6") M6
+ a(target="_blank", href=`${base}/m-code.html#mcode:m6`) M6
td T
td Tool Change
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m61") M61
+ a(target="_blank", href=`${base}/m-code.html#mcode:m61`) M61
td Q
td Set Current Tool
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g10-l1") G10 L1
+ a(target="_blank", href=`${base}/g-code.html#gcode:g10-l1`) G10 L1
td P Q R
td Set Tool Table
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g10-l10") G10 L10
+ a(target="_blank", href=`${base}/g-code.html#gcode:g10-l10`) G10 L10
td P
td Set Tool Table
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g10-l11") G10 L11
+ a(target="_blank", href=`${base}/g-code.html#gcode:g10-l11`) G10 L11
td P
td Set Tool Table
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g43") G43
+ a(target="_blank", href=`${base}/g-code.html#gcode:g43`) G43
td H
td Tool Length Offset
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g43.1") G43.1
+ a(target="_blank", href=`${base}/g-code.html#gcode:g43.1`) G43.1
td
td Dynamic Tool Length Offset
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g43.2") G43.2
+ a(target="_blank", href=`${base}/g-code.html#gcode:g43.2`) G43.2
td H
td Apply additional Tool Length Offset
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g49") G49
+ a(target="_blank", href=`${base}/g-code.html#gcode:g49`) G49
td
td Cancel Tool Length Compensation
th(colspan='3') Feed Control
tr
td
- a(href="#{base}/other-code.html#sec:set-feed-rate") F
+ a(href=`${base}/other-code.html#sec:set-feed-rate`) F
td
td Set Feed Rate
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g93-g94-g95")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g93-g94-g95`)
| G93, G94, G95
td
td Feed Rate Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m52") M52
+ a(target="_blank", href=`${base}/m-code.html#mcode:m52`) M52
td P0 (off) or P1 (on)
td Adaptive Feed Control
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m53") M53
+ a(target="_blank", href=`${base}/m-code.html#mcode:m53`) M53
td P0 (off) or P1 (on)
td Feed Stop Control
th(colspan='3') Spindle Control
tr
td
- a(href="#{base}/other-code.html#sec:set-spindle-speed") S
+ a(href=`${base}/other-code.html#sec:set-spindle-speed`) S
td
td Set Spindle Speed
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m3-m4-m5")
+ a(target="_blank", href=`${base}/m-code.html#mcode:m3-m4-m5`)
| M3, M4, M5
td S
td Spindle Control
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m19") M19
+ a(target="_blank", href=`${base}/m-code.html#mcode:m19`) M19
td
td Orient Spindle
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g96-g97") G96, G97
+ a(target="_blank", href=`${base}/g-code.html#gcode:g96-g97`) G96, G97
td S D
td Spindle Control Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g33") G33
+ a(target="_blank", href=`${base}/g-code.html#gcode:g33`) G33
td K
td Spindle Synchronized Motion
th(colspan='3') Coolant
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m7-m8-m9")
+ a(target="_blank", href=`${base}/m-code.html#mcode:m7-m8-m9`)
| M7, M8, M9
td
td Coolant Control
th(colspan='3') Stopping
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m0-m1") M0, M1
+ a(target="_blank", href=`${base}/m-code.html#mcode:m0-m1`) M0, M1
td
td Program Pause
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m2-m30") M2, M30
+ a(target="_blank", href=`${base}/m-code.html#mcode:m2-m30`) M2, M30
td
td Program End
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m60") M60
+ a(target="_blank", href=`${base}/m-code.html#mcode:m60`) M60
td
td Pallet Change Pause
th(colspan='3') Units
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g20-g21") G20, G21
+ a(target="_blank", href=`${base}/g-code.html#gcode:g20-g21`) G20, G21
td
td Units (inch, mm)
th(colspan='3') Distance Mode
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g90-g91") G90, G91
+ a(target="_blank", href=`${base}/g-code.html#gcode:g90-g91`) G90, G91
td
td Distance Mode
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g90.1-g91.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g90.1-g91.1`)
| G90.1, G91.1
td
td Arc Distance Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g7") G7
+ a(target="_blank", href=`${base}/g-code.html#gcode:g7`) G7
td
td Lathe Diameter Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g8") G8
+ a(target="_blank", href=`${base}/g-code.html#gcode:g8`) G8
td
td Lathe Radius Mode
th(colspan='3') Cutter Radius Compensation
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g40") G40
+ a(target="_blank", href=`${base}/g-code.html#gcode:g40`) G40
td
td Compensation Off
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g41-g42") G41,G42
+ a(target="_blank", href=`${base}/g-code.html#gcode:g41-g42`) G41,G42
td D
td Cutter Compensation
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g41.1-g42.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g41.1-g42.1`)
| G41.1, G42.1
td D L
td Dynamic Cutter Compensation
th(colspan='3') Path Control Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g61-g61.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g61-g61.1`)
| G61 G61.1
td
td Exact Path Mode
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g64") G64
+ a(target="_blank", href=`${base}/g-code.html#gcode:g64`) G64
td P Q
td Path Blending
th(colspan='3') Overrides
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m48-m49") M48, M49
+ a(target="_blank", href=`${base}/m-code.html#mcode:m48-m49`) M48, M49
td
td Speed and Feed Override Control
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m50") M50
+ a(target="_blank", href=`${base}/m-code.html#mcode:m50`) M50
td P0 (off) or P1 (on)
td Feed Override Control
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m51") M51
+ a(target="_blank", href=`${base}/m-code.html#mcode:m51`) M51
td P0 (off) or P1 (on)
td Spindle Speed Override Control
th(colspan='3') Coordinate Systems, Offsets & Planes
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g54-g59.3")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g54-g59.3`)
| G54-G59.3
td
td Select Coordinate System
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g10-l2") G10 L2
+ a(target="_blank", href=`${base}/g-code.html#gcode:g10-l2`) G10 L2
td P R
td Set Coordinate System
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g10-l20") G10 L20
+ a(target="_blank", href=`${base}/g-code.html#gcode:g10-l20`) G10 L20
td P
td Set Coordinate System
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g53") G53
+ a(target="_blank", href=`${base}/g-code.html#gcode:g53`) G53
td
td Move in Machine Coordinates
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g92") G92
+ a(target="_blank", href=`${base}/g-code.html#gcode:g92`) G92
td
td Coordinate System Offset
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g92.1-g92.2")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g92.1-g92.2`)
| G92.1, G92.2
td
td Reset G92 Offsets
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g92.3") G92.3
+ a(target="_blank", href=`${base}/g-code.html#gcode:g92.3`) G92.3
td
td Restore G92 Offsets
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g28-g28.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g28-g28.1`)
| G28, G28.1
td
td Go/Set Predefined Position
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g30-g30.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g30-g30.1`)
| G30, G30.1
td
td Go/Set Predefined Position
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g17-g19.1")
+ a(target="_blank", href=`${base}/g-code.html#gcode:g17-g19.1`)
| G17 - G19.1
td (affects G2, G3, G81…G89, G40…G42)
td Plane Select
th(colspan='3') Flow-control Codes
tr
td
- a(target="_blank", href="#{base}/o-code.html#ocode:subroutines")
+ a(target="_blank", href=`${base}/o-code.html#ocode:subroutines`)
| o sub/endsub/call
td
td Subroutines, sub/endsub call
tr
td
- a(target="_blank", href="#{base}/o-code.html#ocode:looping") o while
+ a(target="_blank", href=`${base}/o-code.html#ocode:looping`) o while
td
td Looping, while/endwhile do/while
tr
td
- a(target="_blank", href="#{base}/o-code.html#ocode:conditional") o if
+ a(target="_blank", href=`${base}/o-code.html#ocode:conditional`) o if
td
td Conditional, if/else/endif
tr
td
- a(target="_blank", href="#{base}/o-code.html#ocode:repeat") o repeat
+ a(target="_blank", href=`${base}/o-code.html#ocode:repeat`) o repeat
td
td Repeat a loop of code
tr
td
- a(target="_blank", href="#{base}/o-code.html#ocode:indirection") []
+ a(target="_blank", href=`${base}/o-code.html#ocode:indirection`) []
td
td Indirection
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/o-code.html#ocode:calling-files")
+ a(target="_blank", href=`${base}/o-code.html#ocode:calling-files`)
| o call
td
td Call named or numbered file
th(colspan='3') Modal State
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m70") M70
+ a(target="_blank", href=`${base}/m-code.html#mcode:m70`) M70
td
td Save modal state
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m71") M71
+ a(target="_blank", href=`${base}/m-code.html#mcode:m71`) M71
td
td Invalidate stored state
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m72") M72
+ a(target="_blank", href=`${base}/m-code.html#mcode:m72`) M72
td
td Restore modal state
tr
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m73") M73
+ a(target="_blank", href=`${base}/m-code.html#mcode:m73`) M73
td
td Save and Auto-restore modal state
th(colspan='3') Input/Output
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m62-m65") M62 - M65
+ a(target="_blank", href=`${base}/m-code.html#mcode:m62-m65`) M62 - M65
td P
td Digital Output Control
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m66") M66
+ a(target="_blank", href=`${base}/m-code.html#mcode:m66`) M66
td P E L Q
td Wait on Input
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m67") M67
+ a(target="_blank", href=`${base}/m-code.html#mcode:m67`) M67
td T
td Analog Output,Synchronized
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m68") M68
+ a(target="_blank", href=`${base}/m-code.html#mcode:m68`) M68
td T
td Analog Output, Immediate
th(colspan='3') User Defined Commands
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/m-code.html#mcode:m100-m199")
+ a(target="_blank", href=`${base}/m-code.html#mcode:m100-m199`)
| M101 - M199
td P Q
td User Defined Commands
th(colspan='3') Canned cycles
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g80") G80
+ a(target="_blank", href=`${base}/g-code.html#gcode:g80`) G80
td
td Cancel Canned Cycle
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g81") G81
+ a(target="_blank", href=`${base}/g-code.html#gcode:g81`) G81
td R L (P)
td Drilling Cycle
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g82") G82
+ a(target="_blank", href=`${base}/g-code.html#gcode:g82`) G82
td R L (P)
td Drilling Cycle, Dwell
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g83") G83
+ a(target="_blank", href=`${base}/g-code.html#gcode:g83`) G83
td R L Q
td Drilling Cycle, Peck
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g73") G73
+ a(target="_blank", href=`${base}/g-code.html#gcode:g73`) G73
td R L Q
td Drilling Cycle, Chip Breaking
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g85") G85
+ a(target="_blank", href=`${base}/g-code.html#gcode:g85`) G85
td R L (P)
td Boring Cycle, Feed Out
tr
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g89") G89
+ a(target="_blank", href=`${base}/g-code.html#gcode:g89`) G89
td R L (P)
td Boring Cycle, Dwell, Feed Out
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g76") G76
+ a(target="_blank", href=`${base}/g-code.html#gcode:g76`) G76
td P Z I J R K Q H L E
td Threading Cycle
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/g-code.html#gcode:g98-g99") G98, G99
+ a(target="_blank", href=`${base}/g-code.html#gcode:g98-g99`) G98, G99
td
td Canned Cycle Return Level
th(colspan='3') Comments & Messages
tr
td
- a(target="_blank", href="#{base}/overview.html#gcode:comments") ; (…)
+ a(target="_blank", href=`${base}/overview.html#gcode:comments`) ; (…)
td
td Comments
tr
td
- a(target="_blank", href="#{base}/overview.html#gcode:messages")
+ a(target="_blank", href=`${base}/overview.html#gcode:messages`)
| (MSG,…)
td
td Messages
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/overview.html#gcode:debug") (DEBUG,…)
+ a(target="_blank", href=`${base}/overview.html#gcode:debug`) (DEBUG,…)
td
td Debug Messages
tr.unimplemented(v-if="showUnimplemented")
td
- a(target="_blank", href="#{base}/overview.html#gcode:print") (PRINT,…)
+ a(target="_blank", href=`${base}/overview.html#gcode:print`) (PRINT,…)
td
td Print Messages
p
| The Buildbotics controller implements a subset of LinuxCNC GCode.
| Supported commands are listed above. You can find further help with
- | <a href="http://wikipedia.com/wiki/G-code" target="_blank">GCode</a>
+ | #[a(href="http://wikipedia.com/wiki/G-code", target="_blank") GCode]
| programming on the LinuxCNC website:
ul
.fa.fa-home
each axis in 'xyzabc'
- tr.axis(:class="{'homed': is_homed('#{axis}'), 'axis-#{axis}': true}",
- v-if="enabled('#{axis}')")
- th.name #{axis}
+ tr.axis(:class=`{'homed': is_homed('${axis}'), 'axis-${axis}': true}`,
+ v-if=`enabled('${axis}')`)
+ th.name= axis
td.position
- unit-value(:value="get_position('#{axis}')", precision="4")
- td.absolute: unit-value(:value="state.#{axis}p", precision="3")
- td.offset: unit-value(:value="get_offset('#{axis}')", precision="3")
+ unit-value(:value=`get_position('${axis}')`, precision="4")
+ td.absolute: unit-value(:value="state." + axis + "p", precision="3")
+ td.offset: unit-value(:value=`get_offset('${axis}')`, precision="3")
th.actions
button.pure-button(:disabled="!is_ready",
- title="Set {{'#{axis}' | upper}} axis position.",
- @click="show_set_position('#{axis}')")
+ title=`Set {{'${axis}' | upper}} axis position.`,
+ @click=`show_set_position('${axis}')`)
.fa.fa-cog
button.pure-button(:disabled="!is_ready",
- title="Zero {{'#{axis}' | upper}} axis offset.",
- @click="zero('#{axis}')") ∅
+ title=`Zero {{'${axis}' | upper}} axis offset.`,
+ @click=`zero('${axis}')`) ∅
button.pure-button(:disabled="!is_ready",
- title="Home {{'#{axis}' | upper}} axis.",
- @click="home('#{axis}')")
+ title=`Home {{'${axis}' | upper}} axis.`,
+ @click=`home('${axis}')`)
.fa.fa-home
- message(:show.sync="position_msg['#{axis}']")
+ message(:show.sync=`position_msg['${axis}']`)
h3(slot="header") Set {{'#{axis}' | upper}} axis position
div(slot="body")
.pure-control-group
label Position
input(v-model="axis_position",
- @keyup.enter="set_position('#{axis}', axis_position)")
+ @keyup.enter=`set_position('${axis}', axis_position)`)
p
div(slot="footer")
- button.pure-button(@click="position_msg['#{axis}'] = false")
+ button.pure-button(@click=`position_msg['${axis}'] = false`)
| Cancel
- button.pure-button(v-if="is_homed('#{axis}')",
- @click="unhome('#{axis}')") Unhome
+ button.pure-button(v-if="is_homed('" + axis + "')",
+ @click=`unhome('${axis}')`) Unhome
button.pure-button.button-success(
- @click="set_position('#{axis}', axis_position)") Set
+ @click=`set_position('${axis}', axis_position)`) Set
- message(:show.sync="manual_home['#{axis}']")
+ message(:show.sync=`manual_home['${axis}']`)
h3(slot="header") Manually home {{'#{axis}' | upper}} axis
div(slot="body")
.pure-control-group
label Absolute
input(v-model="axis_position",
- @keyup.enter="set_home('#{axis}', axis_position)")
+ @keyup.enter=`set_home('${axis}', axis_position)`)
p
div(slot="footer")
- button.pure-button(@click="manual_home['#{axis}'] = false")
+ button.pure-button(@click=`manual_home['${axis}'] = false`)
| Cancel
button.pure-button.button-success(
- title="Home {{'#{axis}' | upper}} axis.",
- @click="set_home('#{axis}', axis_position)") Set
+ title=`Home {{'${axis}' | upper}} axis.`,
+ @click=`set_home('${axis}', axis_position)`) Set
table.info
tr
tr
th Time
td(title="Total run time (days:hours:mins:secs)")
- | {{toolpath.time / 1000 | time}}
+ span(v-if="plan_time") {{plan_time | time}} of
+ | {{toolpath.time | time}}
tr
th ETA
- td
+ td {{eta}}
tr
th Line
td
- | {{0 <= state.line ? state.line : '0'}}
+ | {{0 <= state.line ? state.line : 0 | number}}
span(v-if="toolpath.lines")
| of {{toolpath.lines | number}}
tr
th Progress
td.progress
- label {{(state.progress || 0) | percent}}
- .bar(:style="'width:' + (state.progress || 0.01) * 100 + '%'")
+ label {{(progress || 0) | percent}}
+ .bar(:style="'width:' + (progress || 0) * 100 + '%'")
.override(title="Feed rate override.")
label Feed
.fa.fa-step-forward
button.pure-button(title="Upload a new GCode program.", @click="open",
- :disabled="is_running || is_stopping")
+ :disabled="!is_ready")
.fa.fa-folder-open
input.gcode-file-input(type="file", @change="upload",
- style="display:none", accept=".nc,.gcode,.gc,.ngc")
+ style="display:none", accept=".nc,.gcode,.gc,.ngc",
+ :disabled="!is_ready")
button.pure-button(title="Delete current GCode program.",
@click="deleteGCode = true",
- :disabled="!state.selected || is_running || is_stopping")
+ :disabled="!state.selected || !is_ready")
.fa.fa-trash
message(:show.sync="deleteGCode")
| selected
select(title="Select previously uploaded GCode programs.",
- v-model="state.selected", @change="load",
- :disabled="is_running || is_stopping")
+ v-model="state.selected", @change="load", :disabled="!is_ready")
option(v-for="file in files", :value="file") {{file}}
path-viewer(:toolpath="toolpath", :progress="progress",
#help
h2 User Manual
p
- | You can find a detailed user manual at <a
- | href="http://docs.buildbotics.com" target="_blank"
- | >docs.buildbotics.com</a>.
+ | You can find a detailed user manual at
+ |
+ a(href="http://docs.buildbotics.com", target="_blank")
+ | docs.buildbotics.com
+ |.
h2 Discussion Forum
p
| If you're having trouble or just want to chat with other Buildbotics
| CNC controller owners, head over to the Buildbotics forum at
- | <a href="http://forum.buildbotics.com" target="_blank"
- | >forum.buildbotics.com</a>. Register on the site and post a message.
- | We'll be happy to help.
+ |
+ a(href="http://forum.buildbotics.com", target="_blank")
+ | forum.buildbotics.com
+ |. Register on the site and post a message. We'll be happy to help.
h2 CAD/CAM Software
p
- | <a href="http://wikipedia.com/wiki/Computer-aided_manufacturing"
- | target="_blank">CAM</a> software can be used to create GCode
+ a(href="http://wikipedia.com/wiki/Computer-aided_manufacturing",
+ target="_blank") CAM
+ |
+ | software can be used to create GCode
| automatically from
- | <a href="http://wikipedia.com/wiki/Computer-aided_design"
- | target="_blank">CAD</a> models. Here are a few CAD/CAM resources:
+ |
+ a(href="http://wikipedia.com/wiki/Computer-aided_design",
+ target="_blank") CAD
+ |
+ | models. Here are a few CAD/CAM resources:
ul
li: a(href="http://camotics.org/", target="_blank")
| CAMotics - Open-Source CNC Simulator
each motor in '0123'
tr
td
- .fa.io(:class="get_input_class('#{motor}lw', '#{motor}ls')",
- :title="get_input_tooltip('#{motor}lw', '#{motor}ls')")
+ .fa.io(:class=`get_input_class('${motor}lw', '${motor}ls')`,
+ :title=`get_input_tooltip('${motor}lw', '${motor}ls')`)
td {{get_min_pin(#{motor})}}
th Motor #{motor} Min
th.separator
td
- .fa.io(:class="get_input_class('#{motor}xw', '#{motor}xs')",
- :title="get_input_tooltip('#{motor}xw', '#{motor}xs')")
+ .fa.io(:class=`get_input_class('${motor}xw', '${motor}xs')`,
+ :title=`get_input_tooltip('${motor}xw', '${motor}xs')`)
td {{get_max_pin(#{motor})}}
th Motor #{motor} Max
th Current
h2 DB25 breakout box
- img(width=700, src="/images/DB25_breakout_box.png")
+ img(width=700, src="images/DB25_breakout_box.png")
h2 DB25-M2 breakout
- img(width=400, src="/images/DB25-M2_breakout.png")
+ img(width=400, src="images/DB25-M2_breakout.png")
@click="small = !small", :class="{active: !small}")
.fa.fa-arrows-alt
- tool-button(name="tool", :active="showTool",
- @click="showTool = !showTool", title="Show/hide tool.")
- tool-button(name="bbox", :active="showBBox",
- @click="showBBox = !showBBox", title="Show/hide bounding box.")
- tool-button(name="axes", :active="showAxes",
- @click="showAxes = !showAxes", title="Show/hide axes.")
+ .tool-button(@click="showTool = !showTool", :active="showTool",
+ title="Show/hide tool.")
+ img(src="images/tool.png")
- tool-button(name="isometric", @click="snap('isometric')",
- title="Snap to isometric view.")
- tool-button(name="top", @click="snap('top')",
- title="Snap to top view.")
- tool-button(name="front", @click="snap('front')",
- title="Snap to front view.")
+ .tool-button(@click="showBBox = !showBBox", :active="showBBox",
+ title="Show/hide bounding box.")
+ img(src="images/bbox.png")
+
+ .tool-button(@click="showAxes = !showAxes", :active="showAxes",
+ title="Show/hide axes.")
+ img(src="images/axes.png")
+
+ each view in "isometric top front".split(" ")
+ .tool-button(@click=`snap('${view}')`, title=`Snap to ${view} view.`)
+ img(src=`images/${view}.png`)
.path-viewer-content(:class="{small: small}")
.path-viewer-message(:class="{error: error}")
th Message
tr(v-for="msg in toolpath.messages", :class="'log-' + msg.level")
- td {{msg.level}}
- td
+ td.level {{msg.level}}
+ td.location
| {{msg.line}}
span(v-if="msg.column") :{{msg.column}}
- td {{msg.msg}}
+ td.message {{msg.msg}}
:template="template.settings.units")
p
- | Note, <tt>units</tt> sets both the machine default units and the
- | units used in motor configuration. GCode <tt>program-start</tt>,
+ | Note, #[tt units] sets both the machine default units and the
+ | units used in motor configuration. GCode #[tt program-start],
| set below, may also change the default machine units.
fieldset
+++ /dev/null
-//-/////////////////////////////////////////////////////////////////////////////
-//- //
-//- Copyright (c) 2018, Cauldron Development LLC //
-//- All rights reserved. //
-//- //
-//- This file ("the software") is free software: you can redistribute it //
-//- and/or modify it under the terms of the GNU General Public License, //
-//- version 2 as published by the Free Software Foundation. You should //
-//- have received a copy of the GNU General Public License, version 2 //
-//- along with the software. If not, see <http://www.gnu.org/licenses/>. //
-//- //
-//- The software is distributed in the hope that it will be useful, but //
-//- WITHOUT ANY WARRANTY; without even the implied warranty of //
-//- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //
-//- Lesser General Public License for more details. //
-//- //
-//- You should have received a copy of the GNU Lesser General Public //
-//- License along with the software. If not, see //
-//- <http://www.gnu.org/licenses/>. //
-//- //
-//- For information regarding this software email: //
-//- "Joseph Coffland" <joseph@cauldrondevelopment.com> //
-//- //
-//-/////////////////////////////////////////////////////////////////////////////
-
-script#tool-button-template(type="text/x-template")
- .tool-button(:class="{'active': active}")
- img(:src="'images/' + name + '.png'")
v-if="is_modbus && this.tool_type != 'HUANYANG VFD'")
h2 Active Modbus Program
p
- | (Click <tt class="save">Save</tt> to activate the selected
- | <b>tool-type</b>.)
+ | (Click #[tt(class="save") Save] to activate the selected
+ | #[b tool-type].)
table.modbus-regs.fixed-regs
tr
th Index
td.reg-addr PD163
td.reg-value 1
td Modbus ID
- td Must match <tt>bus-id</tt> above.
+ td Must match #[tt bus-id] above.
tr
td.reg-addr PD164
td.reg-value 1
td 9600 baud
- td Must match <tt>baud</tt> above.
+ td Must match #[tt baud] above.
tr
td.reg-addr PD166
td.reg-value 3
td 8 bit, no parity, RTU mode
- td Must match <tt>parity</tt> above.
+ td Must match #[tt parity] above.
p
- | Other settings according to the <a
- | href="https://buildbotics.com/upload/vfd/Huanyang-VFD-manual.pdf"
- | target="_blank">Huanyang VFD manual</a> and spindle type.
+ | Other settings according to the
+ |
+ a(href="https://buildbotics.com/upload/vfd/Huanyang-VFD-manual.pdf",
+ target="_blank") Huanyang VFD manual
+ |
+ | and spindle type.
.notes(v-if="tool_type.startsWith('DELTA VFD015M21A')")
h2 Notes
td.reg-addr Pr.88
td.reg-value 1
td Modbus ID
- td Must match <tt>bus-id</tt> above
+ td Must match #[tt bus-id] above
tr
td.reg-addr Pr.89
td.reg-value 1
td 9600 baud
- td Must match <tt>baud</tt> above
+ td Must match #[tt baud] above
tr
td.reg-addr Pr.92
td.reg-value 3
td 8 bit, no parity, RTU mode
- td Must match <tt>parity</tt> above
+ td Must match #[tt parity] above
tr
td.reg-addr Pr.157
td.reg-value 1
td Communication mode
p
- | Other settings according to the <a
- | href="https://buildbotics.com/upload/vfd/Delta_VFD015M21A.pdf"
- | target="_blank">Delta VFD015M21A VFD manual</a> and spindle type.
+ | Other settings according to the
+ |
+ a(href="https://buildbotics.com/upload/vfd/Delta_VFD015M21A.pdf",
+ target="_blank") Delta VFD015M21A VFD manual
+ |
+ | and spindle type.
self.lcd = bbctrl.LCD(self)
self.mach = bbctrl.Mach(self)
self.preplanner = bbctrl.Preplanner(self)
+ self.planTimer = bbctrl.PlanTimer(self)
self.jog = bbctrl.Jog(self)
self.pwr = bbctrl.Pwr(self)
--- /dev/null
+################################################################################
+# #
+# This file is part of the Buildbotics firmware. #
+# #
+# Copyright (c) 2015 - 2018, Buildbotics LLC #
+# All rights reserved. #
+# #
+# This file ("the software") is free software: you can redistribute it #
+# and/or modify it under the terms of the GNU General Public License, #
+# version 2 as published by the Free Software Foundation. You should #
+# have received a copy of the GNU General Public License, version 2 #
+# along with the software. If not, see <http://www.gnu.org/licenses/>. #
+# #
+# The software is distributed in the hope that it will be useful, but #
+# WITHOUT ANY WARRANTY; without even the implied warranty of #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
+# Lesser General Public License for more details. #
+# #
+# You should have received a copy of the GNU Lesser General Public #
+# License along with the software. If not, see #
+# <http://www.gnu.org/licenses/>. #
+# #
+# For information regarding this software email: #
+# "Joseph Coffland" <joseph@buildbotics.com> #
+# #
+################################################################################
+
+import logging
+import time
+import bbctrl
+
+log = logging.getLogger('PlanTimer')
+
+
+class PlanTimer(object):
+ def __init__(self, ctrl):
+ self.ctrl = ctrl
+
+ self.reset()
+ self._report()
+
+ self.ctrl.state.set('plan_time', 0)
+ ctrl.state.add_listener(self._update)
+
+
+ def reset(self):
+ self.plan_time = 0
+ self.move_start = None
+ self.hold_start = None
+ self.plan_times = None
+ self.plan_index = 0
+
+
+ def _report(self):
+ if (self.plan_times is not None and
+ self.plan_index < len(self.plan_times) and
+ self.move_start is not None):
+ state = self.ctrl.state.get('xx', '')
+
+ if state in ['STOPPING', 'RUNNING']:
+ t = self.plan_time
+ delta = time.time() - self.move_start
+ nextT = self.plan_times[self.plan_index][1]
+ if t + delta < nextT: t += delta
+ else: t = nextT
+
+ self.ctrl.state.set('plan_time', round(t))
+
+ self.timer = self.ctrl.ioloop.call_later(1, self._report)
+
+
+ def _update(self, update):
+ # Check state
+ if 'xx' in update:
+ state = update['xx']
+
+ if state in ['READY', 'ESTOPPED']:
+ self.ctrl.state.set('plan_time', 0)
+ self.reset()
+
+ elif state == 'HOLDING': self.hold_start = time.time()
+ elif state == 'RUNNING' and self.hold_start is not None:
+ self.move_start += time.time() - self.hold_start
+ self.hold_start = None
+
+ # Get plan times
+ if self.plan_times is None or 'selected' in update:
+ active_plan = self.ctrl.state.get('selected', '')
+
+ if active_plan:
+ plan = self.ctrl.preplanner.get_plan(active_plan)
+
+ if plan is not None and plan.done():
+ self.reset()
+ self.plan_times = plan.result()[1]
+
+ # Get plan time for current id
+ if self.plan_times is not None and 'id' in update:
+ currentID = update['id']
+
+ while self.plan_index < len(self.plan_times):
+ id, t = self.plan_times[self.plan_index]
+ if id <= currentID: self.move_start = time.time()
+ if currentID <= id: break
+ self.plan_time = t
+ self.plan_index += 1
log = logging.getLogger('Planner')
reLogLine = re.compile(
- r'^(?P<level>[A-Z])[0-9 ]:((?P<where>[^:]+:\d+:\d+):)?(?P<msg>.*)$')
+ r'^(?P<level>[A-Z])[0-9 ]:'
+ r'((?P<file>[^:]+):)?'
+ r'((?P<line>\d+):)?'
+ r'((?P<column>\d+):)?'
+ r'(?P<msg>.*)$')
class Planner():
self.cmdq = CommandQueue()
self.logLock = threading.Lock()
self.logIntercept = {}
- self.time = 0
ctrl.state.add_listener(self._update)
level = m.group('level')
msg = m.group('msg')
- where = m.group('where')
+ filename = m.group('file')
+ line = m.group('line')
+ column = m.group('column')
- if where is not None: filename, line, column = where.split(':')
- else: filename, line, column = None, None, None
+ where = ':'.join(filter(None.__ne__, [filename, line, column]))
+
+ if line is not None: line = int(line)
+ if column is not None: column = int(column)
# Per thread log intercept
with self.logLock:
self.logIntercept[tid](level, msg, filename, line, column)
return
- if where is not None: extra = dict(where = where)
+ if where: extra = dict(where = where)
else: extra = None
if level == 'I': log.info (msg, extra = extra)
def __encode(self, block):
- log.info('Cmd:' + json.dumps(block))
-
type, id = block['type'], block['id']
+ if type != 'set': log.info('Cmd:' + json.dumps(block))
+
if type == 'line':
return Cmd.line(block['target'], block['exit-vel'],
block['max-accel'], block['max-jerk'],
self.max_plan_time = max_plan_time
self.max_loop_time = max_loop_time
- if not os.path.exists('plans'): os.mkdir('plans')
+ for dir in ['plans', 'times']:
+ if not os.path.exists(dir): os.mkdir(dir)
self.started = Future()
# Copy state for thread
state = self.ctrl.state.snapshot()
- config = self.ctrl.mach.planner.get_config(False, True)
+ config = self.ctrl.mach.planner.get_config(False, False)
+ del config['default-units']
# Start planner thread
plan = yield self.pool.submit(self._exec_plan, filename, state, config)
# Check if this plan was already run
hid = plan_hash(filename, config)
plan_path = 'plans/' + filename + '.' + hid + '.gz'
- if os.path.exists(plan_path):
- with open(plan_path, 'rb') as f: return f.read()
+ times_path = 'times/' + filename + '.' + hid + '.gz'
+
+ try:
+ if os.path.exists(plan_path) and os.path.exists(times_path):
+ with open(plan_path, 'rb') as f: data = f.read()
+ with open(times_path, 'rb') as f: times = f.read()
+ return (data, json.loads(gzip.decompress(times).decode('utf8')))
+
+ except Exception as e: log.error(e)
+
# Clean up old plans
self._clean_plans(filename)
position = dict(x = 0, y = 0, z = 0)
rapid = False
moves = []
+ times = []
messages = []
count = 0
try:
while planner.has_more():
cmd = planner.next()
- planner.set_active(cmd['id'])
+ planner.set_active(cmd['id']) # Release plan
+
# Cannot synchronize with actual machine so fake it
if planner.is_synchronizing(): planner.synchronize(0)
if cmd['type'] == 'line':
- totalTime += sum(cmd['times'])
+ if not 'first' in cmd:
+ totalTime += sum(cmd['times']) / 1000
+ times.append((cmd['id'], totalTime))
target = cmd['target']
move = {}
maxLine = line
maxLineTime = time.time()
- elif cmd['type'] == 'dwell': totalTime += cmd['seconds']
+ elif cmd['type'] == 'dwell':
+ totalTime += cmd['seconds']
+ times.append((cmd['id'], totalTime))
if not self._progress(filename, maxLine / totalLines):
raise Exception('Plan canceled.')
messages = messages)
data = gzip.compress(dump_json(data).encode('utf8'))
- # Save plan
+ # Save plan & times
with open(plan_path, 'wb') as f: f.write(data)
+ with open(times_path, 'wb') as f:
+ f.write(gzip.compress(dump_json(times).encode('utf8')))
- return data
+ return (data, times)
return
if data is not None:
+ data = data[0]
self.set_header('Content-Encoding', 'gzip')
# Respond with chunks to avoid long delays
from bbctrl.MainLCDPage import MainLCDPage
from bbctrl.IPLCDPage import IPLCDPage
from bbctrl.Camera import Camera, VideoHandler
+from bbctrl.PlanTimer import PlanTimer
import bbctrl.Cmd as Cmd
import bbctrl.v4l2 as v4l2
background-color inherit
color #ff3a3a
+ .path-viewer-messages
+ margin 0.125em 0
+
+ th, td
+ padding 0.125em
+
+ &.level
+ text-transform capitalize
+
.path-viewer-content
background-color #333
background linear-gradient(to bottom, #666 0%, #222 100%);