v1.0.9 changes from 1.1.1
This commit is contained in:
@@ -1,150 +1,120 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
"use strict";
|
||||
|
||||
const api = require("./api");
|
||||
const utils = require("./utils");
|
||||
const merge = require("lodash.merge");
|
||||
|
||||
const config_defaults = require("../resources/onefinity_defaults.json");
|
||||
|
||||
const variant_defaults = {
|
||||
machinist_x35: require("../resources/onefinity_machinist_x35_defaults.json"),
|
||||
woodworker_x35: require("../resources/onefinity_woodworker_x35_defaults.json"),
|
||||
woodworker_x50: require("../resources/onefinity_woodworker_x50_defaults.json"),
|
||||
journeyman_x50: require("../resources/onefinity_journeyman_x50_defaults.json")
|
||||
machinist_x35: require("../resources/onefinity_machinist_x35_defaults.json"),
|
||||
woodworker_x35: require("../resources/onefinity_woodworker_x35_defaults.json"),
|
||||
woodworker_x50: require("../resources/onefinity_woodworker_x50_defaults.json"),
|
||||
journeyman_x50: require("../resources/onefinity_journeyman_x50_defaults.json")
|
||||
};
|
||||
|
||||
const api = require('./api');
|
||||
|
||||
module.exports = {
|
||||
template: '#admin-general-view-template',
|
||||
props: ['config', 'state'],
|
||||
template: "#admin-general-view-template",
|
||||
props: [ "config", "state" ],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
configRestored: false,
|
||||
confirmReset: false,
|
||||
configReset: false,
|
||||
latest: '',
|
||||
autoCheckUpgrade: true,
|
||||
reset_variant: ''
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
latest_version: function (version) {
|
||||
this.latest = version
|
||||
}
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.autoCheckUpgrade = this.config.admin['auto-check-upgrade']
|
||||
},
|
||||
|
||||
methods: {
|
||||
backup: function () {
|
||||
document.getElementById('download-target').src = '/api/config/download';
|
||||
data: function() {
|
||||
return {
|
||||
confirmReset: false,
|
||||
autoCheckUpgrade: true,
|
||||
reset_variant: ""
|
||||
};
|
||||
},
|
||||
|
||||
restore_config: function () {
|
||||
// If we don't reset the form the browser may cache file if name is same
|
||||
// even if contents have changed
|
||||
$('.restore-config')[0].reset();
|
||||
$('.restore-config input').click();
|
||||
ready: function() {
|
||||
this.autoCheckUpgrade = this.config.admin["auto-check-upgrade"];
|
||||
},
|
||||
|
||||
restore: function (e) {
|
||||
var files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) return;
|
||||
methods: {
|
||||
backup: function() {
|
||||
document.getElementById("download-target").src = "/api/config/download";
|
||||
},
|
||||
|
||||
var fr = new FileReader();
|
||||
fr.onload = function (e) {
|
||||
var config;
|
||||
try {
|
||||
config = JSON.parse(e.target.result);
|
||||
} catch (ex) {
|
||||
api.alert("Invalid config file");
|
||||
return;
|
||||
restore_config: function() {
|
||||
utils.clickFileInput("restore-config");
|
||||
},
|
||||
|
||||
restore: function(e) {
|
||||
const files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = async ({ target }) => {
|
||||
let config;
|
||||
try {
|
||||
config = JSON.parse(target.result);
|
||||
} catch (error) {
|
||||
console.error("Invalid config file:", error);
|
||||
alert("Invalid config file");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await api.put("config/save", config);
|
||||
this.$dispatch("update");
|
||||
SvelteComponents.showDialog("Message", {
|
||||
title: "Success",
|
||||
message: "Configuration restored"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Restore failed:", error);
|
||||
alert("Restore failed");
|
||||
}
|
||||
};
|
||||
|
||||
fileReader.readAsText(files[0]);
|
||||
},
|
||||
|
||||
reset: async function() {
|
||||
const config = merge(
|
||||
{},
|
||||
config_defaults,
|
||||
variant_defaults[this.reset_variant]
|
||||
);
|
||||
|
||||
try {
|
||||
await api.put("config/save", config);
|
||||
this.confirmReset = false;
|
||||
this.$dispatch("update");
|
||||
SvelteComponents.showDialog("Message", {
|
||||
title: "Success",
|
||||
message: "Configuration restored"
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Restore failed:", error);
|
||||
alert("Restore failed");
|
||||
}
|
||||
},
|
||||
|
||||
check: function() {
|
||||
this.$dispatch("check");
|
||||
},
|
||||
|
||||
upgrade: function() {
|
||||
this.$dispatch("upgrade");
|
||||
},
|
||||
|
||||
upload_firmware: function() {
|
||||
utils.clickFileInput("upload-firmware");
|
||||
},
|
||||
|
||||
upload: function(e) {
|
||||
const files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
this.$dispatch("upload", files[0]);
|
||||
},
|
||||
|
||||
change_auto_check_upgrade: function() {
|
||||
this.config.admin["auto-check-upgrade"] = this.autoCheckUpgrade;
|
||||
this.$dispatch("config-changed");
|
||||
}
|
||||
|
||||
api.put('config/save', config).done(function (data) {
|
||||
this.$dispatch('update');
|
||||
this.configRestored = true;
|
||||
|
||||
}.bind(this)).fail(function (error) {
|
||||
api.alert('Restore failed', error);
|
||||
})
|
||||
}.bind(this);
|
||||
|
||||
fr.readAsText(files[0]);
|
||||
},
|
||||
|
||||
reset: async function () {
|
||||
const config = merge(
|
||||
{},
|
||||
config_defaults,
|
||||
variant_defaults[this.reset_variant]
|
||||
);
|
||||
|
||||
try {
|
||||
await api.put('config/save', config)
|
||||
this.confirmReset = false;
|
||||
this.$dispatch('update');
|
||||
this.configRestored = true;
|
||||
} catch (err) {
|
||||
api.alert('Restore failed');
|
||||
console.error('Restore failed', err);
|
||||
}
|
||||
},
|
||||
|
||||
check: function () {
|
||||
this.$dispatch('check')
|
||||
},
|
||||
|
||||
upgrade: function () {
|
||||
this.$dispatch('upgrade')
|
||||
},
|
||||
|
||||
upload_firmware: function () {
|
||||
// If we don't reset the form the browser may cache file if name is same
|
||||
// even if contents have changed
|
||||
$('.upload-firmware')[0].reset();
|
||||
$('.upload-firmware input').click();
|
||||
},
|
||||
|
||||
upload: function (e) {
|
||||
var files = e.target.files || e.dataTransfer.files;
|
||||
if (!files.length) return;
|
||||
this.$dispatch('upload', files[0]);
|
||||
},
|
||||
|
||||
change_auto_check_upgrade: function () {
|
||||
this.config.admin['auto-check-upgrade'] = this.autoCheckUpgrade;
|
||||
this.$dispatch('config-changed');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,177 +1,14 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
var api = require('./api');
|
||||
|
||||
|
||||
module.exports = {
|
||||
template: '#admin-network-view-template',
|
||||
props: ['config', 'state'],
|
||||
template: "#admin-network-view-template",
|
||||
|
||||
attached: function() {
|
||||
this.svelteComponent = SvelteComponents.createComponent(
|
||||
"AdminNetworkView",
|
||||
document.getElementById("admin-network")
|
||||
);
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
hostnameSet: false,
|
||||
usernameSet: false,
|
||||
passwordSet: false,
|
||||
redirectTimeout: 0,
|
||||
hostname: '',
|
||||
username: '',
|
||||
current: '',
|
||||
password: '',
|
||||
password2: '',
|
||||
wifi_mode: 'client',
|
||||
wifi_ssid: '',
|
||||
wifi_ch: undefined,
|
||||
wifi_pass: '',
|
||||
wifiConfirm: false,
|
||||
rebooting: false
|
||||
detached: function() {
|
||||
this.svelteComponent.$destroy();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ready: function () {
|
||||
api.get('hostname').done(function (hostname) {
|
||||
this.hostname = hostname;
|
||||
}.bind(this));
|
||||
|
||||
api.get('remote/username').done(function (username) {
|
||||
this.username = username;
|
||||
}.bind(this));
|
||||
|
||||
api.get('wifi').done(function (config) {
|
||||
this.wifi_mode = config.mode;
|
||||
this.wifi_ssid = config.ssid;
|
||||
this.wifi_ch = config.channel;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
redirect: function (hostname) {
|
||||
if (0 < this.redirectTimeout) {
|
||||
this.redirectTimeout -= 1;
|
||||
setTimeout(function () {this.redirect(hostname)}.bind(this), 1000);
|
||||
|
||||
} else location.hostname = hostname;
|
||||
},
|
||||
|
||||
|
||||
set_hostname: function () {
|
||||
api.put('hostname', {hostname: this.hostname}).done(function () {
|
||||
this.redirectTimeout = 45;
|
||||
this.hostnameSet = true;
|
||||
|
||||
api.put('reboot').always(function () {
|
||||
if (String(location.hostname) == 'localhost') return;
|
||||
|
||||
var hostname = this.hostname;
|
||||
if (String(location.hostname).endsWith('.local'))
|
||||
hostname += '.local'
|
||||
this.$dispatch('hostname-changed', hostname);
|
||||
this.redirect(hostname);
|
||||
}.bind(this));
|
||||
|
||||
}.bind(this)).fail(function (error) {
|
||||
api.alert('Set hostname failed', error);
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
set_username: function () {
|
||||
api.put('remote/username', {username: this.username}).done(function () {
|
||||
this.usernameSet = true;
|
||||
}.bind(this)).fail(function (error) {
|
||||
api.alert('Set username failed', error);
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
set_password: function () {
|
||||
if (this.password != this.password2) {
|
||||
alert('Passwords to not match');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.password.length < 6) {
|
||||
alert('Password too short');
|
||||
return;
|
||||
}
|
||||
|
||||
api.put('remote/password', {
|
||||
current: this.current,
|
||||
password: this.password
|
||||
}).done(function () {
|
||||
this.passwordSet = true;
|
||||
}.bind(this)).fail(function (error) {
|
||||
api.alert('Set password failed', error);
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
config_wifi: function () {
|
||||
this.wifiConfirm = false;
|
||||
|
||||
if (!this.wifi_ssid.length) {
|
||||
alert('SSID not set');
|
||||
return;
|
||||
}
|
||||
|
||||
if (32 < this.wifi_ssid.length) {
|
||||
alert('SSID longer than 32 characters');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.wifi_pass.length && this.wifi_pass.length < 8) {
|
||||
alert('WiFi password shorter than 8 characters');
|
||||
return;
|
||||
}
|
||||
|
||||
if (128 < this.wifi_pass.length) {
|
||||
alert('WiFi password longer than 128 characters');
|
||||
return;
|
||||
}
|
||||
|
||||
this.rebooting = true;
|
||||
|
||||
var config = {
|
||||
mode: this.wifi_mode,
|
||||
channel: this.wifi_ch,
|
||||
ssid: this.wifi_ssid,
|
||||
pass: this.wifi_pass
|
||||
}
|
||||
|
||||
api.put('wifi', config).fail(function (error) {
|
||||
api.alert('Failed to configure WiFi', error);
|
||||
this.rebooting = false;
|
||||
}.bind(this))
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
128
src/js/api.js
128
src/js/api.js
@@ -1,104 +1,48 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
async function callApi(method, url, data) {
|
||||
try {
|
||||
const headers = {};
|
||||
let body = undefined;
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
if (data) {
|
||||
if (data instanceof FormData) {
|
||||
body = data;
|
||||
} else {
|
||||
headers["Content-Type"] = "application/json; charset=utf-8";
|
||||
body = JSON.stringify(data);
|
||||
}
|
||||
}
|
||||
|
||||
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/>.
|
||||
const response = await fetch(`/api/${url}`, {
|
||||
method,
|
||||
headers,
|
||||
body,
|
||||
cache: "no-cache",
|
||||
});
|
||||
|
||||
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.
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
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/>.
|
||||
throw new Error(await response.text());
|
||||
} catch (error) {
|
||||
console.debug(`API Error: ${url}: ${error}`);
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
function api_cb(method, url, data, config) {
|
||||
config = $.extend({
|
||||
type: method,
|
||||
url: '/api/' + url,
|
||||
dataType: 'json',
|
||||
cache: false
|
||||
}, config);
|
||||
|
||||
if (typeof data == 'object') {
|
||||
config.data = JSON.stringify(data);
|
||||
config.contentType = 'application/json; charset=utf-8';
|
||||
}
|
||||
|
||||
var d = $.Deferred();
|
||||
|
||||
$.ajax(config).success(function (data, status, xhr) {
|
||||
d.resolve(data, status, xhr);
|
||||
|
||||
}).error(function (xhr, status, error) {
|
||||
var text = xhr.responseText;
|
||||
try {text = $.parseJSON(xhr.responseText)} catch(e) {}
|
||||
if (!text) text = error;
|
||||
|
||||
d.reject(text, xhr, status, error);
|
||||
console.debug('API Error: ' + url + ': ' + text);
|
||||
});
|
||||
|
||||
return d.promise();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
get: function (url, config) {
|
||||
return api_cb('GET', url, undefined, config);
|
||||
},
|
||||
get: function(url) {
|
||||
return callApi("GET", url);
|
||||
},
|
||||
|
||||
put: function(url, body = undefined) {
|
||||
return callApi("PUT", url, body);
|
||||
},
|
||||
|
||||
put: function(url, data, config) {
|
||||
return api_cb('PUT', url, data, config);
|
||||
},
|
||||
|
||||
|
||||
post: function(url, data, config) {
|
||||
return api_cb('POST', url, data, config);
|
||||
},
|
||||
|
||||
|
||||
upload: function(url, data, config) {
|
||||
config = $.extend({
|
||||
processData: false,
|
||||
contentType: false,
|
||||
cache: false,
|
||||
data: data
|
||||
}, config);
|
||||
|
||||
return api_cb('PUT', url, undefined, config);
|
||||
},
|
||||
|
||||
|
||||
'delete': function (url, config) {
|
||||
return api_cb('DELETE', url, undefined, config);
|
||||
},
|
||||
|
||||
|
||||
alert: function (msg, error) {
|
||||
if (typeof error != 'undefined') {
|
||||
if (typeof error.message != 'undefined')
|
||||
msg += '\n' + error.message;
|
||||
else msg += '\n' + JSON.stringify(error);
|
||||
delete: function(url) {
|
||||
return callApi("DELETE", url);
|
||||
}
|
||||
|
||||
alert(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
850
src/js/app.js
850
src/js/app.js
@@ -1,506 +1,440 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
const api = require("./api");
|
||||
const cookie = require("./cookie")("bbctrl-");
|
||||
const Sock = require("./sock");
|
||||
const semverLt = require("semver/functions/lt");
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
SvelteComponents.createComponent("DialogHost",
|
||||
document.getElementById("svelte-dialog-host")
|
||||
);
|
||||
|
||||
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/>.
|
||||
function parse_version(v) {
|
||||
const pattern = /^(\d+)\.(\d+)\.(\d+)(?:[-.]?(.*))?$/;
|
||||
const [ version, major, minor, patch, pre ] = v.trim().match(pattern) || [];
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
const api = require('./api');
|
||||
const cookie = require('./cookie')('bbctrl-');
|
||||
const Sock = require('./sock');
|
||||
const omit = require('lodash.omit');
|
||||
|
||||
function is_newer_version(current, latest) {
|
||||
const pattern = /(\d+)\.(\d+)\.(\d+)(.*)/;
|
||||
const currentParts = current.match(pattern);
|
||||
const latestParts = latest.match(pattern);
|
||||
|
||||
if (!currentParts || !latestParts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Normal version comparisons
|
||||
const major = latestParts[1] - currentParts[1];
|
||||
const minor = latestParts[2] - currentParts[2];
|
||||
const patch = latestParts[3] - currentParts[3];
|
||||
|
||||
// If current is a pre-release, and latest is a release
|
||||
const betaToRelease = latestParts[4].length === 0 && currentParts[4].length > 0;
|
||||
|
||||
switch (true) {
|
||||
case major > 0:
|
||||
case major === 0 && minor > 0:
|
||||
case major === 0 && minor === 0 && patch > 0:
|
||||
case major === 0 && minor === 0 && patch === 0 && betaToRelease:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
version,
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
pre
|
||||
};
|
||||
}
|
||||
|
||||
function is_object(o) { return o !== null && typeof o == 'object' }
|
||||
function is_array(o) { return Array.isArray(o) }
|
||||
function fixup_version_number(version) {
|
||||
const v = parse_version(version);
|
||||
|
||||
version = `${v.major}.${v.minor}.${v.patch}`;
|
||||
if (v.pre) {
|
||||
const [ , prefix, num ] = v.pre.match(/([a-zA-Z])(\d+)/);
|
||||
|
||||
const suffix = prefix === "b"
|
||||
? `beta.${num}`
|
||||
: v.pre;
|
||||
|
||||
version = `${version}-${suffix}`;
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
function is_object(o) {
|
||||
return o !== null && typeof o == "object";
|
||||
}
|
||||
|
||||
function is_array(o) {
|
||||
return Array.isArray(o);
|
||||
}
|
||||
|
||||
function update_array(dst, src) {
|
||||
while (dst.length) dst.pop()
|
||||
for (var i = 0; i < src.length; i++)
|
||||
Vue.set(dst, i, src[i]);
|
||||
while (dst.length) {
|
||||
dst.pop();
|
||||
}
|
||||
|
||||
for (let i = 0; i < src.length; i++) {
|
||||
Vue.set(dst, i, src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function hasOwnProperty(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
|
||||
function update_object(dst, src, remove) {
|
||||
var props, index, key, value;
|
||||
let props, index, key, value;
|
||||
|
||||
if (remove) {
|
||||
props = Object.getOwnPropertyNames(dst);
|
||||
if (remove) {
|
||||
props = Object.getOwnPropertyNames(dst);
|
||||
|
||||
for (index in props) {
|
||||
key = props[index];
|
||||
if (!src.hasOwnProperty(key))
|
||||
Vue.delete(dst, key);
|
||||
for (index in props) {
|
||||
key = props[index];
|
||||
if (!hasOwnProperty(src, key)) {
|
||||
Vue.delete(dst, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
props = Object.getOwnPropertyNames(src);
|
||||
for (index in props) {
|
||||
key = props[index];
|
||||
value = src[key];
|
||||
props = Object.getOwnPropertyNames(src);
|
||||
for (index in props) {
|
||||
key = props[index];
|
||||
value = src[key];
|
||||
|
||||
if (is_array(value) && dst.hasOwnProperty(key) && is_array(dst[key]))
|
||||
update_array(dst[key], value);
|
||||
|
||||
else if (is_object(value) && dst.hasOwnProperty(key) && is_object(dst[key]))
|
||||
update_object(dst[key], value, remove);
|
||||
|
||||
else Vue.set(dst, key, value);
|
||||
}
|
||||
if (is_array(value) && hasOwnProperty(dst, key) && is_array(dst[key])) {
|
||||
update_array(dst[key], value);
|
||||
} else if (is_object(value) && hasOwnProperty(dst, key) && is_object(dst[key])) {
|
||||
update_object(dst[key], value, remove);
|
||||
} else {
|
||||
Vue.set(dst, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Vue({
|
||||
el: 'body',
|
||||
el: "body",
|
||||
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
status: 'connecting',
|
||||
currentView: 'loading',
|
||||
index: -1,
|
||||
modified: false,
|
||||
template: require('../resources/config-template.json'),
|
||||
config: {
|
||||
settings: { units: 'METRIC' },
|
||||
motors: [{}, {}, {}, {}],
|
||||
version: '<loading>',
|
||||
full_version: '<loading>'
|
||||
},
|
||||
state: {
|
||||
messages: [],
|
||||
probing_active: false,
|
||||
wait_for_probing_complete: false,
|
||||
show_probe_complete_modal: false,
|
||||
show_probe_failed_modal: false
|
||||
},
|
||||
video_size: cookie.get('video-size', 'small'),
|
||||
crosshair: cookie.get('crosshair', 'false') != 'false',
|
||||
errorTimeout: 30,
|
||||
errorTimeoutStart: 0,
|
||||
errorShow: false,
|
||||
errorMessage: '',
|
||||
confirmUpgrade: false,
|
||||
confirmUpload: false,
|
||||
firmwareUpgrading: false,
|
||||
checkedUpgrade: false,
|
||||
firmwareName: '',
|
||||
latestVersion: '',
|
||||
ipAddress: '0.0.0.0',
|
||||
wifiSSID: '',
|
||||
confirmShutdown: false,
|
||||
diskSpace: ''
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
'estop': { template: '#estop-template' },
|
||||
'loading-view': { template: '<h1>Loading...</h1>' },
|
||||
'control-view': require('./control-view'),
|
||||
'settings-view': require('./settings-view'),
|
||||
'motor-view': require('./motor-view'),
|
||||
'tool-view': require('./tool-view'),
|
||||
'io-view': require('./io-view'),
|
||||
'admin-general-view': require('./admin-general-view'),
|
||||
'admin-network-view': require('./admin-network-view'),
|
||||
'help-view': { template: '#help-view-template' },
|
||||
'cheat-sheet-view': {
|
||||
template: '#cheat-sheet-view-template',
|
||||
data: function () { return { showUnimplemented: false } }
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
'config-changed': function () {
|
||||
this.modified = true;
|
||||
data: function() {
|
||||
return {
|
||||
status: "connecting",
|
||||
currentView: "loading",
|
||||
display_units: localStorage.getItem("display_units") || "METRIC",
|
||||
index: -1,
|
||||
modified: false,
|
||||
template: require("../resources/config-template.json"),
|
||||
config: {
|
||||
settings: { units: "METRIC" },
|
||||
motors: [{}, {}, {}, {}],
|
||||
version: "<loading>",
|
||||
full_version: "<loading>",
|
||||
ip: "<>",
|
||||
wifiName: "not connected",
|
||||
},
|
||||
state: {
|
||||
messages: [],
|
||||
},
|
||||
video_size: cookie.get("video-size", "small"),
|
||||
crosshair: cookie.get("crosshair", "false") != "false",
|
||||
errorTimeout: 30,
|
||||
errorTimeoutStart: 0,
|
||||
errorShow: false,
|
||||
errorMessage: "",
|
||||
confirmUpgrade: false,
|
||||
confirmUpload: false,
|
||||
firmwareUpgrading: false,
|
||||
checkedUpgrade: false,
|
||||
firmwareName: "",
|
||||
latestVersion: "",
|
||||
};
|
||||
},
|
||||
|
||||
'hostname-changed': function (hostname) {
|
||||
this.hostname = hostname
|
||||
components: {
|
||||
estop: { template: "#estop-template" },
|
||||
"loading-view": { template: "<h1>Loading...</h1>" },
|
||||
"control-view": require("./control-view"),
|
||||
"settings-view": require("./settings-view"),
|
||||
"motor-view": require("./motor-view"),
|
||||
"tool-view": require("./tool-view"),
|
||||
"io-view": require("./io-view"),
|
||||
"admin-general-view": require("./admin-general-view"),
|
||||
"admin-network-view": require("./admin-network-view"),
|
||||
"help-view": require("./help-view"),
|
||||
"cheat-sheet-view": {
|
||||
template: "#cheat-sheet-view-template",
|
||||
data: function() {
|
||||
return {
|
||||
showUnimplemented: false
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
send: function (msg) {
|
||||
if (this.status == 'connected') {
|
||||
console.debug('>', msg);
|
||||
this.sock.send(msg);
|
||||
}
|
||||
watch: {
|
||||
display_units: function(value) {
|
||||
localStorage.setItem("display_units", value);
|
||||
SvelteComponents.setDisplayUnits(value);
|
||||
},
|
||||
},
|
||||
|
||||
connected: function () {
|
||||
this.update()
|
||||
},
|
||||
events: {
|
||||
"config-changed": function() {
|
||||
this.modified = true;
|
||||
},
|
||||
|
||||
update: function () {
|
||||
this.update()
|
||||
},
|
||||
send: function(msg) {
|
||||
if (this.status == "connected") {
|
||||
this.sock.send(msg);
|
||||
}
|
||||
},
|
||||
|
||||
check: function () {
|
||||
this.latestVersion = '';
|
||||
connected: function() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt',
|
||||
data: { hid: this.state.hid },
|
||||
cache: false
|
||||
update: function() {
|
||||
this.update();
|
||||
},
|
||||
|
||||
}).done(function (data) {
|
||||
this.latestVersion = data;
|
||||
this.$broadcast('latest_version', data);
|
||||
}.bind(this))
|
||||
},
|
||||
check: async function() {
|
||||
try {
|
||||
const response = await fetch("https://raw.githubusercontent.com/OneFinityCNC/onefinity-release/master/latest.txt", {
|
||||
cache: "no-cache"
|
||||
});
|
||||
|
||||
upgrade: function () {
|
||||
this.confirmUpgrade = true;
|
||||
},
|
||||
this.latestVersion = (await response.text()).trim();
|
||||
} catch (err) {
|
||||
this.latestVersion = "";
|
||||
}
|
||||
},
|
||||
|
||||
upload: function (firmware) {
|
||||
this.firmware = firmware;
|
||||
this.firmwareName = firmware.name;
|
||||
this.confirmUpload = true;
|
||||
},
|
||||
upgrade: function() {
|
||||
this.confirmUpgrade = true;
|
||||
},
|
||||
|
||||
error: function (msg) {
|
||||
// Honor user error blocking
|
||||
if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000)
|
||||
return;
|
||||
upload: function(firmware) {
|
||||
this.firmware = firmware;
|
||||
this.firmwareName = firmware.name;
|
||||
this.confirmUpload = true;
|
||||
},
|
||||
|
||||
// Wait at least 1 sec to pop up repeated errors
|
||||
if (1 < msg.repeat && Date.now() - msg.ts < 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Popup error dialog
|
||||
this.errorShow = true;
|
||||
this.errorMessage = msg.msg;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
popupMessages: function () {
|
||||
const msgs = [];
|
||||
|
||||
for (let i = 0; i < this.state.messages.length; i++) {
|
||||
const text = this.state.messages[i].text;
|
||||
if (!/^#/.test(text)) {
|
||||
msgs.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
return msgs;
|
||||
}
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
$(window).on('hashchange', this.parse_hash);
|
||||
this.connect();
|
||||
},
|
||||
|
||||
methods: {
|
||||
metric: function () {
|
||||
return this.config.settings.units != 'IMPERIAL'
|
||||
},
|
||||
|
||||
block_error_dialog: function () {
|
||||
this.errorTimeoutStart = Date.now();
|
||||
this.errorShow = false;
|
||||
},
|
||||
|
||||
toggle_video: function (e) {
|
||||
if (this.video_size == 'small') this.video_size = 'large';
|
||||
else if (this.video_size == 'large') this.video_size = 'small';
|
||||
cookie.set('video-size', this.video_size);
|
||||
},
|
||||
|
||||
toggle_crosshair: function (e) {
|
||||
e.preventDefault();
|
||||
this.crosshair = !this.crosshair;
|
||||
cookie.set('crosshair', this.crosshair);
|
||||
},
|
||||
|
||||
estop: function () {
|
||||
if (this.state.xx == 'ESTOPPED') api.put('clear');
|
||||
else api.put('estop');
|
||||
},
|
||||
|
||||
upgrade_confirmed: async function () {
|
||||
this.confirmUpgrade = false;
|
||||
|
||||
try {
|
||||
await api.put('upgrade');
|
||||
this.firmwareUpgrading = true;
|
||||
} catch (err) {
|
||||
api.alert('Error during upgrade.');
|
||||
console.error("Error during upgrade", err);
|
||||
}
|
||||
},
|
||||
|
||||
upload_confirmed: function () {
|
||||
this.confirmUpload = false;
|
||||
|
||||
const form = new FormData();
|
||||
form.append('firmware', this.firmware);
|
||||
|
||||
$.ajax({
|
||||
url: '/api/firmware/update',
|
||||
type: 'PUT',
|
||||
data: form,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false
|
||||
|
||||
}).success(function () {
|
||||
this.firmwareUpgrading = true;
|
||||
}.bind(this)).error(function (err) {
|
||||
api.alert('Firmware update failed');
|
||||
console.error('Firmware update failed', err);
|
||||
}.bind(this))
|
||||
},
|
||||
|
||||
show_upgrade: function () {
|
||||
if (!this.latestVersion) return false;
|
||||
return is_newer_version(this.config.version, this.latestVersion);
|
||||
},
|
||||
|
||||
update: function () {
|
||||
api.get('config/load').done(function (config) {
|
||||
update_object(this.config, config, true);
|
||||
this.parse_hash();
|
||||
|
||||
if (!this.checkedUpgrade) {
|
||||
this.checkedUpgrade = true;
|
||||
|
||||
var check = this.config.admin['auto-check-upgrade'];
|
||||
if (typeof check == 'undefined' || check)
|
||||
this.$emit('check');
|
||||
}
|
||||
|
||||
this.check_ip_address();
|
||||
this.check_ssid();
|
||||
}.bind(this))
|
||||
},
|
||||
|
||||
check_ip_address: function () {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'hostinfo.txt',
|
||||
data: { hid: this.state.hid },
|
||||
cache: false
|
||||
|
||||
}).done(function (data) {
|
||||
console.debug('>', data);
|
||||
this.ipAddress = 'IP:' + data;
|
||||
this.$broadcast('ipAddress', data);
|
||||
}.bind(this))
|
||||
},
|
||||
|
||||
check_ssid: function () {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'ssidinfo.txt',
|
||||
data: { hid: this.state.hid },
|
||||
cache: false
|
||||
|
||||
}).done(function (data) {
|
||||
console.debug('>', data);
|
||||
this.wifiSSID = 'SSID:' + data;
|
||||
this.$broadcast('wifiSSID', data);
|
||||
}.bind(this))
|
||||
},
|
||||
|
||||
get_ip_address: function () {
|
||||
console.debug('get_ip>', this.ipAddress);
|
||||
return this.ipAddress;
|
||||
},
|
||||
|
||||
get_ssid: function () {
|
||||
console.debug('get_ssid>', this.wifiSSID);
|
||||
return this.wifiSSID;
|
||||
},
|
||||
|
||||
shutdown: function () {
|
||||
this.confirmShutdown = false;
|
||||
api.put('shutdown');
|
||||
|
||||
},
|
||||
|
||||
reboot: function () {
|
||||
this.confirmShutdown = false;
|
||||
api.put('reboot');
|
||||
},
|
||||
|
||||
connect: function () {
|
||||
this.sock = new Sock(`//${location.host}/sockjs`);
|
||||
|
||||
this.sock.onmessage = (e) => {
|
||||
if (typeof e.data != 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('log' in e.data) {
|
||||
if (e.data.log.msg === "Switch not found") {
|
||||
this.$broadcast('probing_failed');
|
||||
} else {
|
||||
this.$broadcast('log', e.data.log);
|
||||
}
|
||||
|
||||
delete e.data.log;
|
||||
}
|
||||
|
||||
// Check for session ID change on controller
|
||||
if ('sid' in e.data) {
|
||||
if (typeof this.sid == 'undefined') {
|
||||
this.sid = e.data.sid;
|
||||
} else if (this.sid != e.data.sid) {
|
||||
if (typeof this.hostname !== 'undefined' && location.hostname !== 'localhost') {
|
||||
location.hostname = this.hostname;
|
||||
error: function(msg) {
|
||||
// Honor user error blocking
|
||||
if (Date.now() - this.errorTimeoutStart < this.errorTimeout * 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
// Wait at least 1 sec to pop up repeated errors
|
||||
if (1 < msg.repeat && Date.now() - msg.ts < 1000) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set this to true to get console output of changes to the state
|
||||
const debugStateChanges = false;
|
||||
if (debugStateChanges) {
|
||||
const data = omit(e.data, [
|
||||
'vdd',
|
||||
'vin',
|
||||
'vout',
|
||||
'motor',
|
||||
'temp',
|
||||
'heartbeat',
|
||||
'load1',
|
||||
'load2',
|
||||
'rpi_temp'
|
||||
]);
|
||||
if (Object.keys(data).length > 0) {
|
||||
console.log(JSON.stringify(data, null, 4));
|
||||
}
|
||||
}
|
||||
|
||||
update_object(this.state, e.data, false);
|
||||
|
||||
if (this.state.pw === 0) {
|
||||
Vue.set(this.state, "saw_probe_connected", true);
|
||||
}
|
||||
|
||||
if (this.state.cycle === 'idle') {
|
||||
if (this.state.wait_for_probing_complete) {
|
||||
Vue.set(this.state, "wait_for_probing_complete", false);
|
||||
this.$broadcast("probing_complete");
|
||||
}
|
||||
}
|
||||
|
||||
this.$broadcast('update');
|
||||
};
|
||||
|
||||
this.sock.onopen = () => {
|
||||
this.status = 'connected';
|
||||
this.$emit(this.status);
|
||||
this.$broadcast(this.status);
|
||||
};
|
||||
|
||||
this.sock.onclose = () => {
|
||||
this.status = 'disconnected';
|
||||
this.$emit(this.status);
|
||||
this.$broadcast(this.status);
|
||||
};
|
||||
// Popup error dialog
|
||||
this.errorShow = true;
|
||||
this.errorMessage = msg.msg;
|
||||
},
|
||||
},
|
||||
|
||||
parse_hash: function () {
|
||||
var hash = location.hash.substr(1);
|
||||
computed: {
|
||||
popupMessages: function() {
|
||||
const msgs = [];
|
||||
|
||||
if (!hash.trim().length) {
|
||||
location.hash = 'control';
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < this.state.messages.length; i++) {
|
||||
const text = this.state.messages[i].text;
|
||||
if (!/^#/.test(text)) {
|
||||
msgs.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
var parts = hash.split(':');
|
||||
|
||||
if (parts.length == 2) this.index = parts[1];
|
||||
|
||||
this.currentView = parts[0];
|
||||
return msgs;
|
||||
},
|
||||
},
|
||||
|
||||
save: function () {
|
||||
const selected_tool = this.config.tool['selected-tool'];
|
||||
const saveModbus = selected_tool !== "pwm" &&
|
||||
selected_tool !== "laser" &&
|
||||
selected_tool !== "router";
|
||||
const settings = {
|
||||
['tool']: { ...this.config.tool },
|
||||
['pwm-spindle']: { ...this.config['pwm-spindle'] },
|
||||
['modbus-spindle']: saveModbus ? { ...this.config['modbus-spindle'] } : undefined
|
||||
}
|
||||
delete settings.tool['tool-type'];
|
||||
ready: function() {
|
||||
window.onhashchange = () => this.parse_hash();
|
||||
this.connect();
|
||||
|
||||
this.config['selected-tool-settings'][selected_tool] = settings;
|
||||
|
||||
api.put('config/save', this.config).done(function (data) {
|
||||
this.modified = false;
|
||||
}.bind(this)).fail(function (error) {
|
||||
api.alert('Save failed', error);
|
||||
});
|
||||
SvelteComponents.registerControllerMethods({
|
||||
dispatch: (...args) => this.$dispatch(...args)
|
||||
});
|
||||
},
|
||||
|
||||
close_messages: function (action) {
|
||||
if (action == 'stop') api.put('stop');
|
||||
if (action == 'continue') api.put('unpause');
|
||||
methods: {
|
||||
block_error_dialog: function() {
|
||||
this.errorTimeoutStart = Date.now();
|
||||
this.errorShow = false;
|
||||
},
|
||||
|
||||
// Acknowledge messages
|
||||
if (this.state.messages.length) {
|
||||
var id = this.state.messages.slice(-1)[0].id
|
||||
api.put('message/' + id + '/ack');
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
toggle_video: function() {
|
||||
if (this.video_size == "small") {
|
||||
this.video_size = "large";
|
||||
} else if (this.video_size == "large") {
|
||||
this.video_size = "small";
|
||||
}
|
||||
cookie.set("video-size", this.video_size);
|
||||
},
|
||||
|
||||
toggle_crosshair: function(e) {
|
||||
e.preventDefault();
|
||||
this.crosshair = !this.crosshair;
|
||||
cookie.set("crosshair", this.crosshair);
|
||||
},
|
||||
|
||||
estop: function() {
|
||||
if (this.state.xx == "ESTOPPED") {
|
||||
api.put("clear");
|
||||
} else {
|
||||
api.put("estop");
|
||||
}
|
||||
},
|
||||
|
||||
upgrade_confirmed: async function() {
|
||||
this.confirmUpgrade = false;
|
||||
|
||||
try {
|
||||
await api.put("upgrade");
|
||||
this.firmwareUpgrading = true;
|
||||
} catch (error) {
|
||||
console.error("Error during upgrade:", error);
|
||||
alert("Error during upgrade");
|
||||
}
|
||||
},
|
||||
|
||||
upload_confirmed: async function() {
|
||||
this.confirmUpload = false;
|
||||
|
||||
const form = new FormData();
|
||||
form.append("firmware", this.firmware);
|
||||
|
||||
try {
|
||||
await api.put("firmware/update", form);
|
||||
this.firmwareUpgrading = true;
|
||||
} catch (error) {
|
||||
console.error("Firmware update failed:", error);
|
||||
alert("Firmware update failed");
|
||||
}
|
||||
},
|
||||
|
||||
show_upgrade: function() {
|
||||
if (!this.latestVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return semverLt(this.config.full_version, this.latestVersion);
|
||||
},
|
||||
|
||||
showShutdownDialog: function() {
|
||||
SvelteComponents.showDialog("Shutdown");
|
||||
},
|
||||
|
||||
update: async function() {
|
||||
const config = await api.get("config/load");
|
||||
const wifi = await api.get("wifi");
|
||||
update_object(this.config, config, true);
|
||||
this.config.full_version = fixup_version_number(this.config.full_version);
|
||||
this.config.ip = wifi.ipAddresses;
|
||||
this.config.wifiName = wifi.wifi;
|
||||
this.parse_hash();
|
||||
|
||||
if (!this.checkedUpgrade) {
|
||||
this.checkedUpgrade = true;
|
||||
|
||||
const check = this.config.admin["auto-check-upgrade"];
|
||||
if (typeof check == "undefined" || check) {
|
||||
this.$emit("check");
|
||||
}
|
||||
}
|
||||
|
||||
SvelteComponents.handleConfigUpdate(this.config);
|
||||
},
|
||||
|
||||
connect: function() {
|
||||
this.sock = new Sock(`//${location.host}/sockjs`);
|
||||
|
||||
this.sock.onmessage = (e) => {
|
||||
if (typeof e.data != "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.log && e.data.log.msg !== "Switch not found") {
|
||||
this.$broadcast("log", e.data.log);
|
||||
|
||||
if (Object.keys(e.data).length === 1) {
|
||||
// If there's only log data, we're done
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for session ID change on controller
|
||||
if ("sid" in e.data) {
|
||||
if (typeof this.sid == "undefined") {
|
||||
this.sid = e.data.sid;
|
||||
} else if (this.sid != e.data.sid) {
|
||||
if (this.hostname && location.hostname !== "localhost") {
|
||||
location.hostname = this.hostname;
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
update_object(this.state, e.data, false);
|
||||
|
||||
SvelteComponents.handleControllerStateUpdate(this.state);
|
||||
|
||||
delete this.state.log;
|
||||
|
||||
this.$broadcast("update");
|
||||
};
|
||||
|
||||
this.sock.onopen = () => {
|
||||
this.status = "connected";
|
||||
this.$emit(this.status);
|
||||
this.$broadcast(this.status);
|
||||
};
|
||||
|
||||
this.sock.onclose = () => {
|
||||
this.status = "disconnected";
|
||||
this.$emit(this.status);
|
||||
this.$broadcast(this.status);
|
||||
};
|
||||
},
|
||||
|
||||
parse_hash: function() {
|
||||
const hash = location.hash.substr(1);
|
||||
|
||||
if (!hash.trim().length) {
|
||||
location.hash = "control";
|
||||
return;
|
||||
}
|
||||
|
||||
const parts = hash.split(":");
|
||||
|
||||
if (parts.length == 2) {
|
||||
this.index = parts[1];
|
||||
}
|
||||
|
||||
this.currentView = parts[0];
|
||||
},
|
||||
|
||||
save: async function() {
|
||||
const selected_tool = this.config.tool["selected-tool"];
|
||||
const saveModbus =
|
||||
selected_tool !== "pwm" &&
|
||||
selected_tool !== "laser" &&
|
||||
selected_tool !== "router";
|
||||
const settings = {
|
||||
["tool"]: { ...this.config.tool },
|
||||
["pwm-spindle"]: { ...this.config["pwm-spindle"] },
|
||||
["modbus-spindle"]: saveModbus
|
||||
? { ...this.config["modbus-spindle"] }
|
||||
: undefined,
|
||||
};
|
||||
delete settings.tool["tool-type"];
|
||||
|
||||
this.config["selected-tool-settings"][selected_tool] = settings;
|
||||
|
||||
try {
|
||||
await api.put("config/save", this.config);
|
||||
this.modified = false;
|
||||
} catch (error) {
|
||||
console.error("Save failed:", error);
|
||||
alert("Save failed");
|
||||
}
|
||||
},
|
||||
|
||||
close_messages: function(action) {
|
||||
if (action == "stop") {
|
||||
api.put("stop");
|
||||
}
|
||||
|
||||
if (action == "continue") {
|
||||
api.put("unpause");
|
||||
}
|
||||
|
||||
// Acknowledge messages
|
||||
if (this.state.messages.length) {
|
||||
const id = this.state.messages.slice(-1)[0].id;
|
||||
api.put(`message/${id}/ack`);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,65 +1,37 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#axis-control-template',
|
||||
props: ['axes', 'colors', 'enabled', 'adjust', 'step'],
|
||||
template: "#axis-control-template",
|
||||
props: [ "axes", "colors", "enabled", "adjust", "step" ],
|
||||
|
||||
methods: {
|
||||
jog: function(axis, ring, direction) {
|
||||
const value = direction * this.value(ring);
|
||||
this.$dispatch(this.step ? "step" : "jog", this.axes[axis], value);
|
||||
},
|
||||
|
||||
methods: {
|
||||
jog: function (axis, ring, direction) {
|
||||
var value = direction * this.value(ring);
|
||||
this.$dispatch(this.step ? 'step' : 'jog', this.axes[axis], value);
|
||||
},
|
||||
back2zero: function(axis0,axis1) {
|
||||
this.$dispatch("back2zero",this.axes[axis0],this.axes[axis1]);
|
||||
},
|
||||
|
||||
back2zero: function(axis0,axis1) {
|
||||
this.$dispatch('back2zero',this.axes[axis0],this.axes[axis1])
|
||||
},
|
||||
release: function(axis) {
|
||||
if (!this.step) {
|
||||
this.$dispatch("jog", this.axes[axis], 0);
|
||||
}
|
||||
},
|
||||
|
||||
value: function(ring) {
|
||||
const adjust = [ 0.01, 0.1, 1 ][this.adjust];
|
||||
if (this.step) {
|
||||
return adjust * [ 0.1, 1, 10, 100 ][ring];
|
||||
}
|
||||
return adjust * [ 0.1, 0.25, 0.5, 1 ][ring];
|
||||
},
|
||||
|
||||
release: function (axis) {
|
||||
if (!this.step) this.$dispatch('jog', this.axes[axis], 0)
|
||||
},
|
||||
|
||||
|
||||
value: function (ring) {
|
||||
var adjust = [0.01, 0.1, 1][this.adjust];
|
||||
if (this.step) return adjust * [0.1, 1, 10, 100][ring];
|
||||
return adjust * [0.1, 0.25, 0.5, 1][ring];
|
||||
},
|
||||
|
||||
|
||||
text: function (ring) {
|
||||
var value = this.value(ring) * (this.step ? 1 : 100);
|
||||
value = parseFloat(value.toFixed(3));
|
||||
return value + (this.step ? '' : '%');
|
||||
text: function(ring) {
|
||||
let value = this.value(ring) * (this.step ? 1 : 100);
|
||||
value = parseFloat(value.toFixed(3));
|
||||
return value + (this.step ? "" : "%");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,232 +1,254 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
function is_defined(x) {return typeof x != 'undefined'}
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
props: ['state', 'config'],
|
||||
props: [ "state", "config" ],
|
||||
|
||||
computed: {
|
||||
metric: function() {
|
||||
return this.$root.display_units === "METRIC";
|
||||
},
|
||||
|
||||
computed: {
|
||||
x: function () {return this._compute_axis('x')},
|
||||
y: function () {return this._compute_axis('y')},
|
||||
z: function () {return this._compute_axis('z')},
|
||||
a: function () {return this._compute_axis('a')},
|
||||
b: function () {return this._compute_axis('b')},
|
||||
c: function () {return this._compute_axis('c')},
|
||||
axes: function () {return this._compute_axes()}
|
||||
},
|
||||
x: function() {
|
||||
return this._compute_axis("x");
|
||||
},
|
||||
|
||||
y: function() {
|
||||
return this._compute_axis("y");
|
||||
},
|
||||
|
||||
methods: {
|
||||
_convert_length: function (value) {
|
||||
return this.state.imperial ? value / 25.4 : value;
|
||||
},
|
||||
z: function() {
|
||||
return this._compute_axis("z");
|
||||
},
|
||||
|
||||
a: function() {
|
||||
return this._compute_axis("a");
|
||||
},
|
||||
|
||||
_length_str: function (value) {
|
||||
return this._convert_length(value).toLocaleString() +
|
||||
(this.state.imperial ? ' in' : ' mm');
|
||||
},
|
||||
b: function() {
|
||||
return this._compute_axis("b");
|
||||
},
|
||||
|
||||
c: function() {
|
||||
return this._compute_axis("c");
|
||||
},
|
||||
|
||||
_compute_axis: function (axis) {
|
||||
var abs = this.state[axis + 'p'] || 0;
|
||||
var off = this.state['offset_' + axis];
|
||||
var motor_id = this._get_motor_id(axis);
|
||||
var motor = motor_id == -1 ? {} : this.config.motors[motor_id];
|
||||
var enabled = typeof motor.enabled != 'undefined' && motor.enabled;
|
||||
var homingMode = motor['homing-mode']
|
||||
var homed = this.state[motor_id + 'homed'];
|
||||
var min = this.state[motor_id + 'tn'];
|
||||
var max = this.state[motor_id + 'tm'];
|
||||
var dim = max - min;
|
||||
var pathMin = this.state['path_min_' + axis];
|
||||
var pathMax = this.state['path_max_' + axis];
|
||||
var pathDim = pathMax - pathMin;
|
||||
var under = pathMin + off < min;
|
||||
var over = max < pathMax + off;
|
||||
var klass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis;
|
||||
var state = 'UNHOMED';
|
||||
var icon = 'question-circle';
|
||||
var fault = this.state[motor_id + 'df'] & 0x1f;
|
||||
var shutdown = this.state.power_shutdown;
|
||||
var title;
|
||||
var ticon = 'question-circle';
|
||||
var tstate = 'NO FILE';
|
||||
var toolmsg;
|
||||
var tklass = (homed ? 'homed' : 'unhomed') + ' axis-' + axis;
|
||||
|
||||
if (fault || shutdown) {
|
||||
state = shutdown ? 'SHUTDOWN' : 'FAULT';
|
||||
klass += ' error';
|
||||
icon = 'exclamation-circle';
|
||||
|
||||
} else if(homed) {
|
||||
state = 'HOMED';
|
||||
icon = 'check-circle';
|
||||
}
|
||||
|
||||
if (0 < dim && dim < pathDim) {
|
||||
tstate = 'NO FIT';
|
||||
tklass += ' error';
|
||||
ticon = 'ban';
|
||||
|
||||
} else {
|
||||
|
||||
if (over || under) {
|
||||
tstate = over ? 'OVER' : 'UNDER';
|
||||
tklass += ' warn';
|
||||
ticon = 'exclamation-circle';
|
||||
} else {
|
||||
tstate = 'OK';
|
||||
ticon = 'check-circle';
|
||||
axes: function() {
|
||||
return this._compute_axes();
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case 'UNHOMED': title = 'Click the home button to home axis.'; break;
|
||||
case 'HOMED': title = 'Axis successfuly homed.'; break;
|
||||
case 'FAULT':
|
||||
title = 'Motor driver fault. A potentially damaging electrical ' +
|
||||
'condition was detected and the motor driver was shutdown. ' +
|
||||
'Please power down the controller and check your motor cabling. ' +
|
||||
'See the "Motor Faults" table on the "Indicators" tab for more ' +
|
||||
'information.';
|
||||
break;
|
||||
case 'SHUTDOWN':
|
||||
title = 'Motor power fault. All motors in shutdown. ' +
|
||||
'See the "Power Faults" table on the "Indicators" tab for more ' +
|
||||
'information. Reboot controller to reset.';
|
||||
}
|
||||
|
||||
switch(tstate) {
|
||||
|
||||
case 'OVER':
|
||||
toolmsg = 'Caution: The current tool path file would move ' +
|
||||
this._length_str(pathMax + off - max) + ' above axis limit with the current offset.';
|
||||
break;
|
||||
|
||||
case 'UNDER':
|
||||
toolmsg = 'Caution: The current tool path file would move ' +
|
||||
this._length_str(min - pathMin - off) + ' below limit with the current offset.';
|
||||
break;
|
||||
|
||||
case 'NO FIT':
|
||||
toolmsg = 'Warning: The current tool path dimensions (' +
|
||||
this._length_str(pathDim) + ') exceed axis dimensions (' +
|
||||
this._length_str(dim) + ') by ' +
|
||||
this._length_str(pathDim - dim) + '.';
|
||||
break;
|
||||
|
||||
default:
|
||||
toolmsg = 'Tool path ' + axis + ' dimensions OK.';
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
pos: abs - off,
|
||||
abs: abs,
|
||||
off: off,
|
||||
min: min,
|
||||
max: max,
|
||||
dim: dim,
|
||||
pathMin: pathMin,
|
||||
pathMax: pathMax,
|
||||
pathDim: pathDim,
|
||||
motor: motor_id,
|
||||
enabled: enabled,
|
||||
homingMode: homingMode,
|
||||
homed: homed,
|
||||
klass: klass,
|
||||
state: state,
|
||||
icon: icon,
|
||||
title: title,
|
||||
ticon: ticon,
|
||||
tstate: tstate,
|
||||
toolmsg: toolmsg,
|
||||
tklass: tklass
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
_convert_length: function(value) {
|
||||
return this.metric
|
||||
? value
|
||||
: value / 25.4;
|
||||
},
|
||||
|
||||
_get_motor_id: function (axis) {
|
||||
for (var i = 0; i < this.config.motors.length; i++) {
|
||||
var motor = this.config.motors[i];
|
||||
if (motor.axis.toLowerCase() == axis) return i;
|
||||
}
|
||||
_length_str: function(value) {
|
||||
return this._convert_length(value).toLocaleString() + (this.metric ? " mm" : " in");
|
||||
},
|
||||
|
||||
return -1;
|
||||
},
|
||||
_compute_axis: function(axis) {
|
||||
const abs = this.state[`${axis}p`] || 0;
|
||||
const off = this.state[`offset_${axis}`];
|
||||
const motor_id = this._get_motor_id(axis);
|
||||
const motor = motor_id == -1 ? {} : this.config.motors[motor_id];
|
||||
const enabled = typeof motor.enabled != "undefined" && motor.enabled;
|
||||
const homingMode = motor["homing-mode"];
|
||||
const homed = this.state[`${motor_id}homed`];
|
||||
const min = this.state[`${motor_id}tn`];
|
||||
const max = this.state[`${motor_id}tm`];
|
||||
const dim = max - min;
|
||||
const pathMin = this.state[`path_min_${axis}`];
|
||||
const pathMax = this.state[`path_max_${axis}`];
|
||||
const pathDim = pathMax - pathMin;
|
||||
const under = pathMin + off < min;
|
||||
const over = max < pathMax + off;
|
||||
let klass = `${homed ? "homed" : "unhomed"} axis-${axis}`;
|
||||
let state = "UNHOMED";
|
||||
let icon = "question-circle";
|
||||
const fault = this.state[`${motor_id}df`] & 0x1f;
|
||||
const shutdown = this.state.power_shutdown;
|
||||
let title;
|
||||
let ticon = "question-circle";
|
||||
let tstate = "NO FILE";
|
||||
let toolmsg;
|
||||
let tklass = `${homed ? "homed" : "unhomed"} axis-${axis}`;
|
||||
|
||||
if (fault || shutdown) {
|
||||
state = shutdown ? "SHUTDOWN" : "FAULT";
|
||||
klass += " error";
|
||||
icon = "exclamation-circle";
|
||||
} else if (homed) {
|
||||
state = "HOMED";
|
||||
icon = "check-circle";
|
||||
}
|
||||
|
||||
_compute_axes: function () {
|
||||
var homed = false;
|
||||
if (0 < dim && dim < pathDim) {
|
||||
tstate = "NO FIT";
|
||||
tklass += " error";
|
||||
ticon = "ban";
|
||||
} else {
|
||||
if (over || under) {
|
||||
tstate = over ? "OVER" : "UNDER";
|
||||
tklass += " warn";
|
||||
ticon = "exclamation-circle";
|
||||
} else {
|
||||
tstate = "OK";
|
||||
ticon = "check-circle";
|
||||
}
|
||||
}
|
||||
|
||||
for (var name of 'xyzabc') {
|
||||
var axis = this[name];
|
||||
switch (state) {
|
||||
case "UNHOMED":
|
||||
title = "Click the home button to home axis.";
|
||||
break;
|
||||
|
||||
if (!axis.enabled) continue
|
||||
if (!axis.homed) {homed = false; break}
|
||||
homed = true;
|
||||
}
|
||||
case "HOMED":
|
||||
title = "Axis successfuly homed.";
|
||||
break;
|
||||
|
||||
var error = false;
|
||||
var warn = false;
|
||||
case "FAULT":
|
||||
title = [
|
||||
`Motor driver fault. A potentially damaging electrical`,
|
||||
`condition was detected and the motor driver was shutdown.`,
|
||||
`Please power down the controller and check your motor cabling.`,
|
||||
`See the "Motor Faults" table on the "Indicators" tab for more`,
|
||||
`information.`,
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
if (homed)
|
||||
for (name of 'xyzabc') {
|
||||
axis = this[name];
|
||||
case "SHUTDOWN":
|
||||
title = [
|
||||
`Motor power fault. All motors in shutdown.`,
|
||||
`See the "Power Faults" table on the "Indicators" tab for more`,
|
||||
`information. Reboot controller to reset.`
|
||||
].join(" ");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!axis.enabled) continue;
|
||||
if (axis.klass.indexOf('error') != -1) error = true;
|
||||
if (axis.klass.indexOf('warn') != -1) warn = true;
|
||||
switch (tstate) {
|
||||
case "OVER":
|
||||
toolmsg = [
|
||||
`Caution: The current tool path file would move`,
|
||||
`${this._length_str(pathMax + off - max)}`,
|
||||
`above axis limit with the current offset.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
case "UNDER":
|
||||
toolmsg = [
|
||||
`Caution: The current tool path file would move`,
|
||||
`${this._length_str(min - pathMin - off)}`,
|
||||
`below limit with the current offset.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
case "NO FIT":
|
||||
toolmsg = [
|
||||
`Warning: The current tool path dimensions`,
|
||||
`(${this._length_str(pathDim)}) exceed axis dimensions`,
|
||||
`(${this._length_str(dim)}) by ${this._length_str(pathDim - dim)}.`
|
||||
].join(" ");
|
||||
break;
|
||||
|
||||
default:
|
||||
toolmsg = `Tool path ${axis} dimensions OK.`;
|
||||
break;
|
||||
}
|
||||
|
||||
return {
|
||||
pos: abs - off,
|
||||
abs: abs,
|
||||
off: off,
|
||||
min: min,
|
||||
max: max,
|
||||
dim: dim,
|
||||
pathMin: pathMin,
|
||||
pathMax: pathMax,
|
||||
pathDim: pathDim,
|
||||
motor: motor_id,
|
||||
enabled: enabled,
|
||||
homingMode: homingMode,
|
||||
homed: homed,
|
||||
klass: klass,
|
||||
state: state,
|
||||
icon: icon,
|
||||
title: title,
|
||||
ticon: ticon,
|
||||
tstate: tstate,
|
||||
toolmsg: toolmsg,
|
||||
tklass: tklass
|
||||
};
|
||||
},
|
||||
|
||||
_get_motor_id: function(axis) {
|
||||
for (let i = 0; i < this.config.motors.length; i++) {
|
||||
const motor = this.config.motors[i];
|
||||
if (motor.axis.toLowerCase() == axis) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
},
|
||||
|
||||
_compute_axes: function() {
|
||||
let homed = false;
|
||||
|
||||
for (const name of "xyzabc") {
|
||||
const axis = this[name];
|
||||
|
||||
if (!axis.enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!axis.homed) {
|
||||
homed = false; break;
|
||||
}
|
||||
|
||||
homed = true;
|
||||
}
|
||||
|
||||
let error = false;
|
||||
let warn = false;
|
||||
|
||||
if (homed) {
|
||||
for (const name of "xyzabc") {
|
||||
const axis = this[name];
|
||||
|
||||
if (!axis.enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (axis.klass.indexOf("error") != -1) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (axis.klass.indexOf("warn") != -1) {
|
||||
warn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let klass = homed ? "homed" : "unhomed";
|
||||
if (error) {
|
||||
klass += " error";
|
||||
} else if (warn) {
|
||||
klass += " warn";
|
||||
}
|
||||
|
||||
if (!homed && this.ask_home) {
|
||||
this.ask_home = false;
|
||||
SvelteComponents.showDialog("HomeMachine", {
|
||||
home: () => this.home()
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
homed: homed,
|
||||
klass: klass
|
||||
};
|
||||
}
|
||||
|
||||
var klass = homed ? 'homed' : 'unhomed';
|
||||
if (error) klass += ' error';
|
||||
else if (warn) klass += ' warn';
|
||||
|
||||
if(!homed && this.ask_home)
|
||||
{
|
||||
this.ask_home_msg = true;
|
||||
this.ask_home = false;
|
||||
}
|
||||
|
||||
return {
|
||||
homed: homed,
|
||||
klass: klass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,87 +1,77 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
function _msg_equal(a, b) {
|
||||
return a.level == b.level && a.source == b.source && a.where == b.where &&
|
||||
a.msg == b.msg;
|
||||
return a.level == b.level
|
||||
&& a.source == b.source
|
||||
&& a.where == b.where
|
||||
&& a.msg == b.msg;
|
||||
}
|
||||
|
||||
|
||||
// Shared among all instances
|
||||
var messages = [];
|
||||
|
||||
const messages = [];
|
||||
|
||||
module.exports = {
|
||||
template: '#console-template',
|
||||
template: "#console-template",
|
||||
|
||||
data: function() {
|
||||
return {
|
||||
messages
|
||||
};
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {messages: messages}
|
||||
},
|
||||
events: {
|
||||
log: function(msg) {
|
||||
// There may be multiple instances of this module so ignore messages
|
||||
// that have already been processed.
|
||||
if (msg.logged) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg.logged = true;
|
||||
|
||||
events: {
|
||||
log: function (msg) {
|
||||
// There may be multiple instances of this module so ignore messages
|
||||
// that have already been processed.
|
||||
if (msg.logged) return;
|
||||
msg.logged = true;
|
||||
// Make sure we have a message level
|
||||
msg.level = msg.level || "info";
|
||||
|
||||
// Make sure we have a message level
|
||||
msg.level = msg.level || 'info';
|
||||
// Add to message log and count and collapse repeats
|
||||
const repeat = messages.length && _msg_equal(msg, messages[0]);
|
||||
if (repeat) {
|
||||
messages[0].repeat++;
|
||||
} else {
|
||||
msg.repeat = msg.repeat || 1;
|
||||
messages.unshift(msg);
|
||||
while (256 < messages.length) {
|
||||
messages.pop();
|
||||
}
|
||||
}
|
||||
|
||||
// Add to message log and count and collapse repeats
|
||||
var repeat = messages.length && _msg_equal(msg, messages[0]);
|
||||
if (repeat) messages[0].repeat++;
|
||||
else {
|
||||
msg.repeat = msg.repeat || 1;
|
||||
messages.unshift(msg);
|
||||
while (256 < messages.length) messages.pop();
|
||||
}
|
||||
msg.ts = Date.now();
|
||||
if (messages[0].repeat > 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write message to browser console for debugging
|
||||
var text = JSON.stringify(msg);
|
||||
if (msg.level == 'error' || msg.level == 'critical') console.error(text);
|
||||
else if (msg.level == 'warning') console.warn(text);
|
||||
else if (msg.level == 'debug' && console.debug) console.debug(text);
|
||||
else console.log(text);
|
||||
msg.ts = Date.now();
|
||||
|
||||
// Event on errors
|
||||
if (msg.level == 'error' || msg.level == 'critical')
|
||||
this.$dispatch('error', msg);
|
||||
// Write message to browser console for debugging
|
||||
const text = JSON.stringify(msg);
|
||||
if (msg.level == "error" || msg.level == "critical") {
|
||||
console.error(text);
|
||||
} else if (msg.level == "warning") {
|
||||
console.warn(text);
|
||||
} else if (msg.level == "debug" && console.debug) {
|
||||
console.debug(text);
|
||||
} else {
|
||||
console.log(text);
|
||||
}
|
||||
|
||||
// Event on errors
|
||||
if (msg.level == "error" || msg.level == "critical") {
|
||||
this.$dispatch("error", msg);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
clear: function() {
|
||||
messages.splice(0, messages.length);
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
clear: function () {messages.splice(0, messages.length);},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
112
src/js/cookie.js
112
src/js/cookie.js
@@ -1,69 +1,49 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
Copyright 2018. Buildbotics LLC
|
||||
All Rights Reserved.
|
||||
|
||||
For information regarding this software email:
|
||||
Joseph Coffland
|
||||
joseph@buildbotics.com
|
||||
|
||||
This software is free software: you clan 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 = function (prefix) {
|
||||
if (typeof prefix == 'undefined') prefix = '';
|
||||
|
||||
var cookie = {
|
||||
get: function (name, defaultValue) {
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
name = prefix + name + '=';
|
||||
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1);
|
||||
if (!c.indexOf(name)) return c.substring(name.length, c.length);
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
|
||||
set: function (name, value, days) {
|
||||
var offset = 2147483647; // Max value
|
||||
if (typeof days != 'undefined') offset = days * 24 * 60 * 60 * 1000;
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + offset);
|
||||
var expires = 'expires=' + d.toUTCString();
|
||||
document.cookie = prefix + name + '=' + value + ';' + expires + ';path=/';
|
||||
},
|
||||
|
||||
|
||||
set_bool: function (name, value) {
|
||||
cookie.set(name, value ? 'true' : 'false');
|
||||
},
|
||||
|
||||
|
||||
get_bool: function (name, defaultValue) {
|
||||
return cookie.get(name, defaultValue ? 'true' : 'false') == 'true';
|
||||
module.exports = function(prefix) {
|
||||
if (typeof prefix == "undefined") {
|
||||
prefix = "";
|
||||
}
|
||||
}
|
||||
|
||||
return cookie;
|
||||
}
|
||||
const cookie = {
|
||||
get: function(name, defaultValue) {
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const ca = decodedCookie.split(";");
|
||||
name = `${prefix + name}=`;
|
||||
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == " ") {
|
||||
c = c.substring(1);
|
||||
}
|
||||
if (!c.indexOf(name)) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
},
|
||||
|
||||
set: function(name, value, days) {
|
||||
let offset = 2147483647; // Max value
|
||||
if (typeof days != "undefined") {
|
||||
offset = days * 24 * 60 * 60 * 1000;
|
||||
}
|
||||
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + offset);
|
||||
const expires = `expires=${d.toUTCString()}`;
|
||||
document.cookie = `${prefix}${name}=${value};${expires};path=/`;
|
||||
},
|
||||
|
||||
set_bool: function(name, value) {
|
||||
cookie.set(name, value ? "true" : "false");
|
||||
},
|
||||
|
||||
get_bool: function(name, defaultValue) {
|
||||
return cookie.get(name, defaultValue ? "true" : "false") == "true";
|
||||
}
|
||||
};
|
||||
|
||||
return cookie;
|
||||
};
|
||||
|
||||
@@ -1,168 +1,154 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
var api = require('./api');
|
||||
|
||||
|
||||
var entityMap = {
|
||||
'&': '&', '<': '<', '>': '>', '"': '"', "'": ''',
|
||||
'/': '/', '`': '`', '=': '='}
|
||||
"use strict";
|
||||
|
||||
const entityMap = {
|
||||
"&": "&", "<": "<", ">": ">", '"': """, "'": "'",
|
||||
"/": "/", "`": "`", "=": "=" };
|
||||
|
||||
function escapeHTML(s) {
|
||||
return s.replace(/[&<>"'`=\/]/g, function (c) {return entityMap[c]})
|
||||
return s.replace(/[&<>"'`=\\/]/g, function(c) {
|
||||
return entityMap[c];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
template: '#gcode-viewer-template',
|
||||
template: "#gcode-viewer-template",
|
||||
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
empty: true,
|
||||
file: '',
|
||||
line: -1,
|
||||
scrolling: false
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
'gcode-load': function (file) {this.load(file)},
|
||||
'gcode-clear': function () {this.clear()},
|
||||
'gcode-reload': function (file) {this.reload(file)},
|
||||
'gcode-line': function (line) {this.update_line(line)}
|
||||
},
|
||||
|
||||
|
||||
ready: function () {
|
||||
this.clusterize = new Clusterize({
|
||||
rows: [],
|
||||
scrollElem: $(this.$el).find('.clusterize-scroll')[0],
|
||||
contentElem: $(this.$el).find('.clusterize-content')[0],
|
||||
no_data_text: 'GCode view...',
|
||||
callbacks: {clusterChanged: this.highlight}
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
attached: function () {
|
||||
if (typeof this.clusterize != 'undefined')
|
||||
this.clusterize.refresh(true);
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
load: async function(file) {
|
||||
if (file == this.file) return;
|
||||
this.clear();
|
||||
this.file = file;
|
||||
|
||||
if (!file) return;
|
||||
|
||||
const response = await fetch(`/api/file/${file}?${Math.random()}`);
|
||||
const text = await response.text();
|
||||
|
||||
if (text.length > 20e6) {
|
||||
this.clusterize.update(['File is large - gcode view disabled']);
|
||||
} else {
|
||||
const lines = escapeHTML(text.trimRight())
|
||||
.split(/[\r\n]/)
|
||||
.map((line, i) => `<li class="ln${i + 1}"><b>${i + 1}</b>${line}</li>`);
|
||||
|
||||
this.clusterize.update(lines);
|
||||
}
|
||||
|
||||
this.empty = false;
|
||||
|
||||
Vue.nextTick(this.update_line);
|
||||
data: function() {
|
||||
return {
|
||||
empty: true,
|
||||
file: "",
|
||||
line: -1
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
clear: function () {
|
||||
this.empty = true;
|
||||
this.file = '';
|
||||
this.line = -1;
|
||||
this.clusterize.clear();
|
||||
},
|
||||
|
||||
|
||||
reload: function (file) {
|
||||
if (file != this.file) return;
|
||||
this.clear();
|
||||
this.load(file);
|
||||
},
|
||||
|
||||
|
||||
highlight: function () {
|
||||
var e = $(this.$el).find('.highlight');
|
||||
if (e.length) e.removeClass('highlight');
|
||||
|
||||
e = $(this.$el).find('.ln' + this.line);
|
||||
if (e.length) e.addClass('highlight');
|
||||
},
|
||||
|
||||
|
||||
update_line: function(line) {
|
||||
if (typeof line != 'undefined') {
|
||||
if (this.line == line) return;
|
||||
this.line = line;
|
||||
|
||||
} else line = this.line;
|
||||
|
||||
var totalLines = this.clusterize.getRowsAmount();
|
||||
|
||||
if (line <= 0) line = 1;
|
||||
if (totalLines < line) line = totalLines;
|
||||
|
||||
var e = $(this.$el).find('.clusterize-scroll');
|
||||
|
||||
var lineHeight = e[0].scrollHeight / totalLines;
|
||||
var linesPerPage = Math.floor(e[0].clientHeight / lineHeight);
|
||||
var current = e[0].scrollTop / lineHeight;
|
||||
var target = line - 1 - Math.floor(linesPerPage / 2);
|
||||
|
||||
// Update scroll position
|
||||
if (!this.scrolling) {
|
||||
if (target < current - 20 || current + 20 < target)
|
||||
e[0].scrollTop = target * lineHeight;
|
||||
|
||||
else {
|
||||
this.scrolling = true;
|
||||
e.animate({scrollTop: target * lineHeight}, {
|
||||
complete: function () {this.scrolling = false}.bind(this)
|
||||
})
|
||||
events: {
|
||||
"gcode-load": function(file) {
|
||||
this.load(file);
|
||||
},
|
||||
"gcode-clear": function() {
|
||||
this.clear();
|
||||
},
|
||||
"gcode-reload": function(file) {
|
||||
this.reload(file);
|
||||
},
|
||||
"gcode-line": function(line) {
|
||||
this.update_line(line);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Vue.nextTick(this.highlight);
|
||||
ready: function() {
|
||||
this.clusterize = new Clusterize({
|
||||
rows: [],
|
||||
scrollElem: this.$el.querySelector(".clusterize-scroll"),
|
||||
contentElem: this.$el.querySelector(".clusterize-content"),
|
||||
no_data_text: "GCode view...",
|
||||
callbacks: { clusterChanged: this.highlight }
|
||||
});
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
if (typeof this.clusterize != "undefined") {
|
||||
this.clusterize.refresh(true);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
load: async function(file) {
|
||||
if (file == this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
this.file = file;
|
||||
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(`/api/file/${file}`, { cache: "no-cache" });
|
||||
const text = await response.text();
|
||||
|
||||
if (text.length > 20e6) {
|
||||
this.clusterize.update([ "File is large - gcode view disabled" ]);
|
||||
} else {
|
||||
const lines = escapeHTML(text.trimRight())
|
||||
.split(/[\r\n]/)
|
||||
.map((line, i) => `<li class="ln${i + 1}"><b>${i + 1}</b>${line}</li>`);
|
||||
|
||||
this.clusterize.update(lines);
|
||||
}
|
||||
|
||||
this.empty = false;
|
||||
|
||||
Vue.nextTick(this.update_line);
|
||||
},
|
||||
|
||||
clear: function() {
|
||||
this.empty = true;
|
||||
this.file = "";
|
||||
this.line = -1;
|
||||
this.clusterize.clear();
|
||||
},
|
||||
|
||||
reload: function(file) {
|
||||
if (file != this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clear();
|
||||
this.load(file);
|
||||
},
|
||||
|
||||
highlight: function() {
|
||||
const highlights = this.$el.querySelectorAll(".highlight");
|
||||
for (const highlight of highlights) {
|
||||
highlight.className = (highlight.className || "")
|
||||
.split(" ")
|
||||
.filter(c => c !== "highlight")
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
const lines = this.$el.querySelectorAll(`.ln${this.line}`);
|
||||
for (const line of lines) {
|
||||
line.className = (line.className || "")
|
||||
.split(" ")
|
||||
.filter(c => c !== "highlight")
|
||||
.concat([ "highlight" ])
|
||||
.join(" ");
|
||||
}
|
||||
},
|
||||
|
||||
update_line: function(line) {
|
||||
if (typeof line != "undefined") {
|
||||
if (this.line == line) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.line = line;
|
||||
} else {
|
||||
line = this.line;
|
||||
}
|
||||
|
||||
const totalLines = this.clusterize.getRowsAmount();
|
||||
|
||||
if (line <= 0) {
|
||||
line = 1;
|
||||
}
|
||||
|
||||
if (totalLines < line) {
|
||||
line = totalLines;
|
||||
}
|
||||
|
||||
const scroll = this.$el.querySelector(".clusterize-scroll");
|
||||
|
||||
const lineHeight = scroll.scrollHeight / totalLines;
|
||||
const linesPerPage = Math.floor(scroll.clientHeight / lineHeight);
|
||||
const target = line - 1 - Math.floor(linesPerPage / 2);
|
||||
|
||||
// Update scroll position
|
||||
scroll.scrollTop = target * lineHeight;
|
||||
|
||||
Vue.nextTick(this.highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
14
src/js/help-view.js
Normal file
14
src/js/help-view.js
Normal file
@@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
template: "#help-view-template",
|
||||
|
||||
attached: function() {
|
||||
this.svelteComponent = SvelteComponents.createComponent(
|
||||
"HelpView",
|
||||
document.getElementById("help")
|
||||
);
|
||||
},
|
||||
|
||||
detached: function() {
|
||||
this.svelteComponent.$destroy();
|
||||
}
|
||||
};
|
||||
@@ -1,107 +1,94 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
var modbus = require('./modbus.js');
|
||||
"use strict";
|
||||
|
||||
const modbus = require("./modbus.js");
|
||||
|
||||
module.exports = {
|
||||
template: '#indicators-template',
|
||||
props: ['state'],
|
||||
template: "#indicators-template",
|
||||
props: [ "state" ],
|
||||
|
||||
computed: {
|
||||
modbus_status: function() {
|
||||
return modbus.status_to_string(this.state.mx);
|
||||
},
|
||||
|
||||
computed: {
|
||||
modbus_status: function () {return modbus.status_to_string(this.state.mx)},
|
||||
sense_error: function() {
|
||||
let error = "";
|
||||
|
||||
if (this.state.motor_voltage_sense_error) {
|
||||
error += "Motor voltage\n";
|
||||
}
|
||||
if (this.state.motor_current_sense_error) {
|
||||
error += "Motor current\n";
|
||||
}
|
||||
if (this.state.load1_sense_error) {
|
||||
error += "Load 1\n";
|
||||
}
|
||||
if (this.state.load2_sense_error) {
|
||||
error += "Load 2\n";
|
||||
}
|
||||
if (this.state.vdd_current_sense_error) {
|
||||
error += "Vdd current\n";
|
||||
}
|
||||
|
||||
sense_error: function () {
|
||||
var error = '';
|
||||
return error;
|
||||
}
|
||||
},
|
||||
|
||||
if (this.state.motor_voltage_sense_error) error += 'Motor voltage\n';
|
||||
if (this.state.motor_current_sense_error) error += 'Motor current\n';
|
||||
if (this.state.load1_sense_error) error += 'Load 1\n';
|
||||
if (this.state.load2_sense_error) error += 'Load 2\n';
|
||||
if (this.state.vdd_current_sense_error) error += 'Vdd current\n';
|
||||
methods: {
|
||||
is_motor_enabled: function(motor) {
|
||||
return typeof this.state[`${motor}me`] != "undefined" && this.state[`${motor}me`];
|
||||
},
|
||||
|
||||
return error;
|
||||
get_min_pin: function(motor) {
|
||||
switch (motor) {
|
||||
case 0: return 3;
|
||||
case 1: return 5;
|
||||
case 2: return 9;
|
||||
case 3: return 11;
|
||||
}
|
||||
},
|
||||
|
||||
get_max_pin: function(motor) {
|
||||
switch (motor) {
|
||||
case 0: return 4;
|
||||
case 1: return 8;
|
||||
case 2: return 10;
|
||||
case 3: return 12;
|
||||
}
|
||||
},
|
||||
|
||||
motor_fault_class: function(motor, bit) {
|
||||
if (typeof motor == "undefined") {
|
||||
const status = this.state["fa"];
|
||||
|
||||
if (typeof status == "undefined") {
|
||||
return "fa-question";
|
||||
}
|
||||
|
||||
return `fa-thumbs-${status ? "down error" : "up success"}`;
|
||||
}
|
||||
|
||||
const flags = this.state[`${motor}df`];
|
||||
|
||||
if (typeof flags == "undefined") {
|
||||
return "fa-question";
|
||||
}
|
||||
|
||||
return (flags & (1 << bit)) ? "fa-thumbs-down error" :
|
||||
"fa-thumbs-up success";
|
||||
},
|
||||
|
||||
motor_reset: function(motor) {
|
||||
if (typeof motor == "undefined") {
|
||||
let cmd = "";
|
||||
for (let i = 0; i < 4; i++) {
|
||||
cmd += `\\$${i}df=0\n`;
|
||||
}
|
||||
|
||||
this.$dispatch("send", cmd);
|
||||
} else {
|
||||
this.$dispatch("send", `\\$${motor}df=0`);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
is_motor_enabled: function (motor) {
|
||||
return typeof this.state[motor + 'me'] != 'undefined' &&
|
||||
this.state[motor + 'me'];
|
||||
},
|
||||
|
||||
|
||||
get_min_pin: function (motor) {
|
||||
switch (motor) {
|
||||
case 0: return 3;
|
||||
case 1: return 5;
|
||||
case 2: return 9;
|
||||
case 3: return 11;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get_max_pin: function (motor) {
|
||||
switch (motor) {
|
||||
case 0: return 4;
|
||||
case 1: return 8;
|
||||
case 2: return 10;
|
||||
case 3: return 12;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
motor_fault_class: function (motor, bit) {
|
||||
if (typeof motor == 'undefined') {
|
||||
var status = this.state['fa'];
|
||||
if (typeof status == 'undefined') return 'fa-question';
|
||||
return 'fa-thumbs-' + (status ? 'down error' : 'up success')
|
||||
}
|
||||
|
||||
var flags = this.state[motor + 'df'];
|
||||
if (typeof flags == 'undefined') return 'fa-question';
|
||||
return (flags & (1 << bit)) ? 'fa-thumbs-down error' :
|
||||
'fa-thumbs-up success';
|
||||
},
|
||||
|
||||
|
||||
motor_reset: function (motor) {
|
||||
if (typeof motor == 'undefined') {
|
||||
var cmd = '';
|
||||
for (var i = 0; i < 4; i++)
|
||||
cmd += '\\$' + i + 'df=0\n';
|
||||
this.$dispatch('send', cmd);
|
||||
|
||||
} else this.$dispatch('send', '\\$' + motor + 'df=0');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,177 +1,155 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: "#io-indicator-template",
|
||||
props: ['name', 'state'],
|
||||
template: "#io-indicator-template",
|
||||
props: [ "name", "state" ],
|
||||
|
||||
computed: {
|
||||
klass: function() {
|
||||
switch (this.name) {
|
||||
case "min-switch-0": return this.get_motor_min_class(0);
|
||||
case "min-switch-1": return this.get_motor_min_class(1);
|
||||
case "min-switch-2": return this.get_motor_min_class(2);
|
||||
case "min-switch-3": return this.get_motor_min_class(3);
|
||||
case "max-switch-0": return this.get_motor_max_class(0);
|
||||
case "max-switch-1": return this.get_motor_max_class(1);
|
||||
case "max-switch-2": return this.get_motor_max_class(2);
|
||||
case "max-switch-3": return this.get_motor_max_class(3);
|
||||
case "estop": return this.get_input_class("ew", "et");
|
||||
case "probe": return this.get_input_class("pw", "pt");
|
||||
case "load-1": return this.get_output_class("1");
|
||||
case "load-2": return this.get_output_class("2");
|
||||
case "fault": return this.get_output_class("f");
|
||||
case "tool-enable-mode": return this.get_output_class("e");
|
||||
case "tool-direction-mode": return this.get_output_class("d");
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
klass: function () {
|
||||
if (this.name == 'min-switch-0') return this.get_motor_min_class(0);
|
||||
if (this.name == 'min-switch-1') return this.get_motor_min_class(1);
|
||||
if (this.name == 'min-switch-2') return this.get_motor_min_class(2);
|
||||
if (this.name == 'min-switch-3') return this.get_motor_min_class(3);
|
||||
if (this.name == 'max-switch-0') return this.get_motor_max_class(0);
|
||||
if (this.name == 'max-switch-1') return this.get_motor_max_class(1);
|
||||
if (this.name == 'max-switch-2') return this.get_motor_max_class(2);
|
||||
if (this.name == 'max-switch-3') return this.get_motor_max_class(3);
|
||||
if (this.name == 'estop') return this.get_input_class('ew', 'et');
|
||||
if (this.name == 'probe') return this.get_input_class('pw', 'pt');
|
||||
if (this.name == 'load-1') return this.get_output_class('1');
|
||||
if (this.name == 'load-2') return this.get_output_class('2');
|
||||
if (this.name == 'fault') return this.get_output_class('f');
|
||||
if (this.name == 'tool-enable-mode') return this.get_output_class('e');
|
||||
if (this.name == 'tool-direction-mode') return this.get_output_class('d');
|
||||
tooltip: function() {
|
||||
switch (this.name) {
|
||||
case "min-switch-0": return this.get_motor_min_tooltip(0);
|
||||
case "min-switch-1": return this.get_motor_min_tooltip(1);
|
||||
case "min-switch-2": return this.get_motor_min_tooltip(2);
|
||||
case "min-switch-3": return this.get_motor_min_tooltip(3);
|
||||
case "max-switch-0": return this.get_motor_max_tooltip(0);
|
||||
case "max-switch-1": return this.get_motor_max_tooltip(1);
|
||||
case "max-switch-2": return this.get_motor_max_tooltip(2);
|
||||
case "max-switch-3": return this.get_motor_max_tooltip(3);
|
||||
case "estop": return this.get_input_tooltip("ew", "et");
|
||||
case "probe": return this.get_input_tooltip("pw", "pt");
|
||||
case "load-1": return this.get_output_tooltip("1");
|
||||
case "load-2": return this.get_output_tooltip("2");
|
||||
case "fault": return this.get_output_tooltip("f");
|
||||
case "tool-direction-mode": return this.get_output_tooltip("d");
|
||||
case "tool-enable-mode": return this.get_output_tooltip("e");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
get_io_state_class: function(active, state) {
|
||||
if (typeof active == "undefined" || typeof state == "undefined") {
|
||||
return "fa-exclamation-triangle warn";
|
||||
}
|
||||
|
||||
tooltip: function () {
|
||||
if (this.name == 'min-switch-0') return this.get_motor_min_tooltip(0);
|
||||
if (this.name == 'min-switch-1') return this.get_motor_min_tooltip(1);
|
||||
if (this.name == 'min-switch-2') return this.get_motor_min_tooltip(2);
|
||||
if (this.name == 'min-switch-3') return this.get_motor_min_tooltip(3);
|
||||
if (this.name == 'max-switch-0') return this.get_motor_max_tooltip(0);
|
||||
if (this.name == 'max-switch-1') return this.get_motor_max_tooltip(1);
|
||||
if (this.name == 'max-switch-2') return this.get_motor_max_tooltip(2);
|
||||
if (this.name == 'max-switch-3') return this.get_motor_max_tooltip(3);
|
||||
if (this.name == 'estop') return this.get_input_tooltip('ew', 'et');
|
||||
if (this.name == 'probe') return this.get_input_tooltip('pw', 'pt');
|
||||
if (this.name == 'load-1') return this.get_output_tooltip('1');
|
||||
if (this.name == 'load-2') return this.get_output_tooltip('2');
|
||||
if (this.name == 'fault') return this.get_output_tooltip('f');
|
||||
if (this.name == 'tool-direction-mode')
|
||||
return this.get_output_tooltip('d');
|
||||
if (this.name == 'tool-enable-mode')
|
||||
return this.get_output_tooltip('e');
|
||||
if (state == 2) {
|
||||
return "fa-circle-o";
|
||||
}
|
||||
|
||||
const icon = state ? "fa-plus-circle" : "fa-minus-circle";
|
||||
return `${icon} ${active ? "active" : "inactive"}`;
|
||||
},
|
||||
|
||||
get_input_active: function(stateCode, typeCode) {
|
||||
const type = this.state[typeCode];
|
||||
const state = this.state[stateCode];
|
||||
|
||||
if (type == 1) {
|
||||
return !state; // Normally open
|
||||
} else if (type == 2) {
|
||||
return state; // Normally closed
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
get_input_class: function(stateCode, typeCode) {
|
||||
return this.get_io_state_class(this.get_input_active(stateCode, typeCode), this.state[stateCode]);
|
||||
},
|
||||
|
||||
get_output_class: function(output) {
|
||||
return this.get_io_state_class(this.state[`${output}oa`], this.state[`${output}os`]);
|
||||
},
|
||||
|
||||
get_motor_min_class: function(motor) {
|
||||
return this.get_input_class(`${motor}lw`, `${motor}ls`);
|
||||
},
|
||||
|
||||
get_motor_max_class: function(motor) {
|
||||
return this.get_input_class(`${motor}xw`, `${motor}xs`);
|
||||
},
|
||||
|
||||
get_tooltip: function(mode, active, state) {
|
||||
if (typeof mode == "undefined" || typeof active == "undefined" || typeof state == "undefined") {
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
if (state == 0) {
|
||||
state = "Lo/Gnd";
|
||||
} else if (state == 1) {
|
||||
state = "Hi/+3.3v";
|
||||
} else if (state == 2) {
|
||||
state = "Tristated";
|
||||
} else {
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
return `Mode: ${mode}\nActive: ${active ? "True" : "False"}\nLevel: ${state}`;
|
||||
},
|
||||
|
||||
get_input_tooltip: function(stateCode, typeCode) {
|
||||
let type = this.state[typeCode];
|
||||
if (type == 0) {
|
||||
return "Disabled";
|
||||
} else if (type == 1) {
|
||||
type = "Normally open";
|
||||
} else if (type == 2) {
|
||||
type = "Normally closed";
|
||||
}
|
||||
|
||||
const active = this.get_input_active(stateCode, typeCode);
|
||||
const state = this.state[stateCode];
|
||||
|
||||
return this.get_tooltip(type, active, state);
|
||||
},
|
||||
|
||||
get_output_tooltip: function(output) {
|
||||
let mode = this.state[`${output}om`];
|
||||
|
||||
switch (mode) {
|
||||
case 0: return "Disabled";
|
||||
case 1: mode = "Lo/Hi"; break;
|
||||
case 2: mode = "Hi/Lo"; break;
|
||||
case 3: mode = "Tri/Lo"; break;
|
||||
case 4: mode = "Tri/Hi"; break;
|
||||
case 5: mode = "Lo/Tri"; break;
|
||||
case 6: mode = "Hi/Tri"; break;
|
||||
default:
|
||||
mode = undefined;
|
||||
}
|
||||
|
||||
const active = this.state[`${output}oa`];
|
||||
const state = this.state[`${output}os`];
|
||||
|
||||
return this.get_tooltip(mode, active, state);
|
||||
},
|
||||
|
||||
get_motor_min_tooltip: function(motor) {
|
||||
return this.get_input_tooltip(`${motor}lw`, `${motor}ls`);
|
||||
},
|
||||
|
||||
get_motor_max_tooltip: function(motor) {
|
||||
return this.get_input_tooltip(`${motor}xw`, `${motor}xs`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
get_io_state_class: function (active, state) {
|
||||
if (typeof active == 'undefined' || typeof state == 'undefined')
|
||||
return 'fa-exclamation-triangle warn';
|
||||
|
||||
if (state == 2) return 'fa-circle-o';
|
||||
|
||||
return (state ? 'fa-plus-circle' : 'fa-minus-circle') + ' ' +
|
||||
(active ? 'active' : 'inactive');
|
||||
},
|
||||
|
||||
|
||||
get_input_active: function (stateCode, typeCode) {
|
||||
var type = this.state[typeCode];
|
||||
var state = this.state[stateCode];
|
||||
|
||||
if (type == 1) return !state; // Normally open
|
||||
else if (type == 2) return state; // Normally closed
|
||||
|
||||
return false
|
||||
},
|
||||
|
||||
|
||||
get_input_class: function (stateCode, typeCode) {
|
||||
return this.get_io_state_class(this.get_input_active(stateCode, typeCode),
|
||||
this.state[stateCode]);
|
||||
},
|
||||
|
||||
|
||||
get_output_class: function (output) {
|
||||
return this.get_io_state_class(this.state[output + 'oa'],
|
||||
this.state[output + 'os']);
|
||||
},
|
||||
|
||||
|
||||
get_motor_min_class: function (motor) {
|
||||
return this.get_input_class(motor + 'lw', motor + 'ls');
|
||||
},
|
||||
|
||||
|
||||
get_motor_max_class: function (motor) {
|
||||
return this.get_input_class(motor + 'xw', motor + 'xs');
|
||||
},
|
||||
|
||||
|
||||
get_tooltip: function (mode, active, state) {
|
||||
if (typeof mode == 'undefined' || typeof active == 'undefined' ||
|
||||
typeof state == 'undefined') return 'Invalid';
|
||||
|
||||
if (state == 0) state = 'Lo/Gnd';
|
||||
else if (state == 1) state = 'Hi/+3.3v';
|
||||
else if (state == 2) state = 'Tristated';
|
||||
else return 'Invalid';
|
||||
|
||||
return 'Mode: ' + mode + '\nActive: ' + (active ? 'True' : 'False') +
|
||||
'\nLevel: ' + state;
|
||||
},
|
||||
|
||||
|
||||
get_input_tooltip: function (stateCode, typeCode) {
|
||||
var type = this.state[typeCode];
|
||||
if (type == 0) return 'Disabled';
|
||||
else if (type == 1) type = 'Normally open';
|
||||
else if (type == 2) type = 'Normally closed';
|
||||
|
||||
var active = this.get_input_active(stateCode, typeCode);
|
||||
var state = this.state[stateCode];
|
||||
|
||||
return this.get_tooltip(type, active, state);
|
||||
},
|
||||
|
||||
|
||||
get_output_tooltip: function (output) {
|
||||
var mode = this.state[output + 'om'];
|
||||
if (mode == 0) return 'Disabled';
|
||||
else if (mode == 1) mode = 'Lo/Hi';
|
||||
else if (mode == 2) mode = 'Hi/Lo';
|
||||
else if (mode == 3) mode = 'Tri/Lo';
|
||||
else if (mode == 4) mode = 'Tri/Hi';
|
||||
else if (mode == 5) mode = 'Lo/Tri';
|
||||
else if (mode == 6) mode = 'Hi/Tri';
|
||||
else mode = undefined;
|
||||
|
||||
var active = this.state[output + 'oa'];
|
||||
var state = this.state[output + 'os'];
|
||||
|
||||
return this.get_tooltip(mode, active, state);
|
||||
},
|
||||
|
||||
|
||||
get_motor_min_tooltip: function (motor) {
|
||||
return this.get_input_tooltip(motor + 'lw', motor + 'ls');
|
||||
},
|
||||
|
||||
|
||||
get_motor_max_tooltip: function (motor) {
|
||||
return this.get_input_tooltip(motor + 'xw', motor + 'xs');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,42 +1,13 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#io-view-template',
|
||||
props: ['config', 'template', 'state'],
|
||||
template: "#io-view-template",
|
||||
props: [ "config", "template", "state" ],
|
||||
|
||||
|
||||
events: {
|
||||
'input-changed': function() {
|
||||
this.$dispatch('config-changed');
|
||||
return false;
|
||||
events: {
|
||||
"input-changed": function() {
|
||||
this.$dispatch("config-changed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
251
src/js/main.js
251
src/js/main.js
@@ -1,147 +1,148 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict';
|
||||
|
||||
"use strict";
|
||||
|
||||
function cookie_get(name) {
|
||||
var decodedCookie = decodeURIComponent(document.cookie);
|
||||
var ca = decodedCookie.split(';');
|
||||
name = name + '=';
|
||||
const decodedCookie = decodeURIComponent(document.cookie);
|
||||
const ca = decodedCookie.split(";");
|
||||
name = `${name}=`;
|
||||
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) == ' ') c = c.substring(1);
|
||||
if (!c.indexOf(name)) return c.substring(name.length, c.length);
|
||||
}
|
||||
for (let i = 0; i < ca.length; i++) {
|
||||
let c = ca[i];
|
||||
while (c.charAt(0) == " ") {
|
||||
c = c.substring(1);
|
||||
}
|
||||
|
||||
if (!c.indexOf(name)) {
|
||||
return c.substring(name.length, c.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function cookie_set(name, value, days) {
|
||||
var d = new Date();
|
||||
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
var expires = 'expires=' + d.toUTCString();
|
||||
document.cookie = name + '=' + value + ';' + expires + ';path=/';
|
||||
const d = new Date();
|
||||
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1000);
|
||||
const expires = `expires=${d.toUTCString()}`;
|
||||
document.cookie = `${name}=${value};${expires};path=/`;
|
||||
}
|
||||
|
||||
|
||||
var uuid_chars =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+';
|
||||
|
||||
const uuid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+";
|
||||
|
||||
function uuid(length) {
|
||||
if (typeof length == 'undefined') length = 52;
|
||||
if (typeof length == "undefined") {
|
||||
length = 52;
|
||||
}
|
||||
|
||||
var s = '';
|
||||
for (var i = 0; i < length; i++)
|
||||
s += uuid_chars[Math.floor(Math.random() * uuid_chars.length)];
|
||||
let s = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
s += uuid_chars[Math.floor(Math.random() * uuid_chars.length)];
|
||||
}
|
||||
|
||||
return s
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
$(function() {
|
||||
if (typeof cookie_get('client-id') == 'undefined')
|
||||
cookie_set('client-id', uuid(), 10000);
|
||||
|
||||
// Vue debugging
|
||||
Vue.config.debug = true;
|
||||
//Vue.util.warn = function (msg) {console.debug('[Vue warn]: ' + msg)}
|
||||
|
||||
// Register global components
|
||||
Vue.component('templated-input', require('./templated-input'));
|
||||
Vue.component('message', require('./message'));
|
||||
Vue.component('indicators', require('./indicators'));
|
||||
Vue.component('io-indicator', require('./io-indicator'));
|
||||
Vue.component('console', require('./console'));
|
||||
Vue.component('unit-value', require('./unit-value'));
|
||||
|
||||
Vue.filter('number', function (value) {
|
||||
if (isNaN(value)) return 'NaN';
|
||||
return value.toLocaleString();
|
||||
});
|
||||
|
||||
Vue.filter('percent', function (value, precision) {
|
||||
if (typeof value == 'undefined') return '';
|
||||
if (typeof precision == 'undefined') precision = 2;
|
||||
return (value * 100.0).toFixed(precision) + '%';
|
||||
});
|
||||
|
||||
Vue.filter('non_zero_percent', function (value, precision) {
|
||||
if (!value) return '';
|
||||
if (typeof precision == 'undefined') precision = 2;
|
||||
return (value * 100.0).toFixed(precision) + '%';
|
||||
});
|
||||
|
||||
Vue.filter('fixed', function (value, precision) {
|
||||
if (typeof value == 'undefined') return '0';
|
||||
return parseFloat(value).toFixed(precision)
|
||||
});
|
||||
|
||||
Vue.filter('upper', function (value) {
|
||||
if (typeof value == 'undefined') return '';
|
||||
return value.toUpperCase()
|
||||
});
|
||||
|
||||
Vue.filter('time', function (value, precision) {
|
||||
if (isNaN(value)) return '';
|
||||
if (isNaN(precision)) precision = 0;
|
||||
|
||||
var MIN = 60;
|
||||
var HR = MIN * 60;
|
||||
var DAY = HR * 24;
|
||||
var parts = [];
|
||||
|
||||
if (DAY <= value) {
|
||||
parts.push(Math.floor(value / DAY));
|
||||
value %= DAY;
|
||||
window.onload = function() {
|
||||
if (typeof cookie_get("client-id") == "undefined") {
|
||||
cookie_set("client-id", uuid(), 10000);
|
||||
}
|
||||
|
||||
if (HR <= value) {
|
||||
parts.push(Math.floor(value / HR));
|
||||
value %= HR;
|
||||
}
|
||||
// Register global components
|
||||
Vue.component("templated-input", require("./templated-input"));
|
||||
Vue.component("message", require("./message"));
|
||||
Vue.component("indicators", require("./indicators"));
|
||||
Vue.component("io-indicator", require("./io-indicator"));
|
||||
Vue.component("console", require("./console"));
|
||||
Vue.component("unit-value", require("./unit-value"));
|
||||
|
||||
if (MIN <= value) {
|
||||
parts.push(Math.floor(value / MIN));
|
||||
value %= MIN;
|
||||
Vue.filter("number", function(value) {
|
||||
if (isNaN(value)) {
|
||||
return "NaN";
|
||||
}
|
||||
|
||||
} else parts.push(0);
|
||||
return value.toLocaleString();
|
||||
});
|
||||
|
||||
parts.push(value);
|
||||
Vue.filter("percent", function(value, precision) {
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
if (typeof precision == "undefined") {
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
return parts.join(':');
|
||||
});
|
||||
return `${(value * 100.0).toFixed(precision)}%`;
|
||||
});
|
||||
|
||||
// Vue app
|
||||
require('./app');
|
||||
});
|
||||
Vue.filter("non_zero_percent", function(value, precision) {
|
||||
if (!value) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (typeof precision == "undefined") {
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
return `${(value * 100.0).toFixed(precision)}%`;
|
||||
});
|
||||
|
||||
Vue.filter("fixed", function(value, precision) {
|
||||
if (typeof value == "undefined") {
|
||||
return "0";
|
||||
}
|
||||
|
||||
return parseFloat(value).toFixed(precision);
|
||||
});
|
||||
|
||||
Vue.filter("upper", function(value) {
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return value.toUpperCase();
|
||||
});
|
||||
|
||||
Vue.filter("time", function(value, precision) {
|
||||
if (isNaN(value)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (isNaN(precision)) {
|
||||
precision = 0;
|
||||
}
|
||||
|
||||
const MIN = 60;
|
||||
const HR = MIN * 60;
|
||||
const DAY = HR * 24;
|
||||
const parts = [];
|
||||
|
||||
if (DAY <= value) {
|
||||
parts.push(Math.floor(value / DAY));
|
||||
value %= DAY;
|
||||
}
|
||||
|
||||
if (HR <= value) {
|
||||
parts.push(Math.floor(value / HR));
|
||||
value %= HR;
|
||||
}
|
||||
|
||||
if (MIN <= value) {
|
||||
parts.push(Math.floor(value / MIN));
|
||||
value %= MIN;
|
||||
} else {
|
||||
parts.push(0);
|
||||
}
|
||||
|
||||
parts.push(value);
|
||||
|
||||
for (let 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]}`;
|
||||
}
|
||||
}
|
||||
|
||||
return parts.join(":");
|
||||
});
|
||||
|
||||
// Vue app
|
||||
require("./app");
|
||||
};
|
||||
|
||||
@@ -1,47 +1,19 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#message-template',
|
||||
template: "#message-template",
|
||||
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
twoWay: true
|
||||
},
|
||||
props: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
twoWay: true
|
||||
},
|
||||
|
||||
class: {
|
||||
type: String,
|
||||
required: false,
|
||||
twoWay: false
|
||||
class: {
|
||||
type: String,
|
||||
required: false,
|
||||
twoWay: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,48 +1,20 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '#modbus-reg-view-template',
|
||||
props: ['index', 'model', 'template', 'enable'],
|
||||
replace: true,
|
||||
template: "#modbus-reg-view-template",
|
||||
props: [ "index", "model", "template", "enable" ],
|
||||
|
||||
computed: {
|
||||
has_user_value: function() {
|
||||
const type = this.model["reg-type"];
|
||||
return type.indexOf("write") != -1 || type.indexOf("fixed") != -1;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
has_user_value: function () {
|
||||
var type = this.model['reg-type'];
|
||||
return type.indexOf('write') != -1 || type.indexOf('fixed') != -1;
|
||||
methods: {
|
||||
change: function() {
|
||||
this.$dispatch("input-changed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
change: function () {this.$dispatch('input-changed')}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,51 +1,23 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
// Must match modbus.c
|
||||
var exports = {
|
||||
DISCONNECTED: 0,
|
||||
OK: 1,
|
||||
CRC: 2,
|
||||
INVALID: 3,
|
||||
TIMEDOUT: 4
|
||||
const constants = {
|
||||
DISCONNECTED: 0,
|
||||
OK: 1,
|
||||
CRC: 2,
|
||||
INVALID: 3,
|
||||
TIMEDOUT: 4
|
||||
};
|
||||
|
||||
|
||||
exports.status_to_string =
|
||||
function (status) {
|
||||
if (status == exports.OK) return 'Ok';
|
||||
if (status == exports.CRC) return 'CRC error';
|
||||
if (status == exports.INVALID) return 'Invalid response';
|
||||
if (status == exports.TIMEDOUT) return 'Timedout';
|
||||
return 'Disconnected';
|
||||
}
|
||||
|
||||
|
||||
module.exports = exports;
|
||||
module.exports = {
|
||||
...constants,
|
||||
status_to_string: function(status) {
|
||||
switch (status) {
|
||||
case constants.OK: return "Ok";
|
||||
case constants.CRC: return "CRC error";
|
||||
case constants.INVALID: return "Invalid response";
|
||||
case constants.TIMEDOUT: return "Timedout";
|
||||
default: return "Disconnected";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,136 +1,120 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
template: '#motor-view-template',
|
||||
props: ['index', 'config', 'template', 'state'],
|
||||
template: "#motor-view-template",
|
||||
props: [ "index", "config", "template", "state" ],
|
||||
|
||||
computed: {
|
||||
metric: function() {
|
||||
return this.$root.display_units === "METRIC";
|
||||
},
|
||||
|
||||
computed: {
|
||||
metric: function () {return this.$root.metric()},
|
||||
is_slave: function() {
|
||||
for (let i = 0; i < this.index; i++) {
|
||||
if (this.motor.axis == this.config.motors[i].axis) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
is_slave: function () {
|
||||
for (var i = 0; i < this.index; i++)
|
||||
if (this.motor.axis == this.config.motors[i].axis)
|
||||
return true;
|
||||
motor: function() {
|
||||
return this.config.motors[this.index];
|
||||
},
|
||||
|
||||
return false;
|
||||
invalidMaxVelocity: function() {
|
||||
return this.maxMaxVelocity < this.motor["max-velocity"];
|
||||
},
|
||||
|
||||
maxMaxVelocity: function() {
|
||||
return 1 * (15 * this.umPerStep / this.motor["microsteps"]).toFixed(3);
|
||||
},
|
||||
|
||||
ustepPerSec: function() {
|
||||
return this.rpm * this.stepsPerRev * this.motor["microsteps"] / 60;
|
||||
},
|
||||
|
||||
rpm: function() {
|
||||
return 1000 * this.motor["max-velocity"] / this.motor["travel-per-rev"];
|
||||
},
|
||||
|
||||
gForce: function() {
|
||||
return this.motor["max-accel"] * 0.0283254504;
|
||||
},
|
||||
|
||||
gForcePerMin: function() {
|
||||
return this.motor["max-jerk"] * 0.0283254504;
|
||||
},
|
||||
|
||||
stepsPerRev: function() {
|
||||
return 360 / this.motor["step-angle"];
|
||||
},
|
||||
|
||||
umPerStep: function() {
|
||||
return this.motor["travel-per-rev"] * this.motor["step-angle"] / 0.36;
|
||||
},
|
||||
|
||||
milPerStep: function() {
|
||||
return this.umPerStep / 25.4;
|
||||
},
|
||||
|
||||
invalidStallVelocity: function() {
|
||||
if (!this.motor["homing-mode"].startsWith("stall-")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.maxStallVelocity < this.motor["search-velocity"];
|
||||
},
|
||||
|
||||
stallRPM: function() {
|
||||
const v = this.motor["search-velocity"];
|
||||
return 1000 * v / this.motor["travel-per-rev"];
|
||||
},
|
||||
|
||||
maxStallVelocity: function() {
|
||||
const maxRate = 900000 / this.motor["stall-sample-time"];
|
||||
const ustep = this.motor["stall-microstep"];
|
||||
const angle = this.motor["step-angle"];
|
||||
const travel = this.motor["travel-per-rev"];
|
||||
const maxStall = maxRate * 60 / 360 / 1000 * angle / ustep * travel;
|
||||
|
||||
return 1 * maxStall.toFixed(3);
|
||||
},
|
||||
|
||||
stallUStepPerSec: function() {
|
||||
const ustep = this.motor["stall-microstep"];
|
||||
return this.stallRPM * this.stepsPerRev * ustep / 60;
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
"input-changed": function() {
|
||||
Vue.nextTick(function() {
|
||||
// Limit max-velocity
|
||||
if (this.invalidMaxVelocity) {
|
||||
this.$set('motor["max-velocity"]', this.maxMaxVelocity);
|
||||
}
|
||||
|
||||
motor: function () {return this.config.motors[this.index]},
|
||||
//Limit stall-velocity
|
||||
if (this.invalidStallVelocity) {
|
||||
this.$set('motor["search-velocity"]', this.maxStallVelocity);
|
||||
}
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
}.bind(this));
|
||||
|
||||
invalidMaxVelocity: function () {
|
||||
return this.maxMaxVelocity < this.motor['max-velocity'];
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
show: function(name, templ) {
|
||||
if (templ.hmodes == undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
maxMaxVelocity: function () {
|
||||
return 1 * (15 * this.umPerStep / this.motor['microsteps']).toFixed(3);
|
||||
},
|
||||
|
||||
|
||||
ustepPerSec: function () {
|
||||
return this.rpm * this.stepsPerRev * this.motor['microsteps'] / 60;
|
||||
},
|
||||
|
||||
|
||||
rpm: function () {
|
||||
return 1000 * this.motor['max-velocity'] / this.motor['travel-per-rev'];
|
||||
},
|
||||
|
||||
|
||||
gForce: function () {return this.motor['max-accel'] * 0.0283254504},
|
||||
gForcePerMin: function () {return this.motor['max-jerk'] * 0.0283254504},
|
||||
stepsPerRev: function () {return 360 / this.motor['step-angle']},
|
||||
|
||||
|
||||
umPerStep: function () {
|
||||
return this.motor['travel-per-rev'] * this.motor['step-angle'] / 0.36
|
||||
},
|
||||
|
||||
|
||||
milPerStep: function () {return this.umPerStep / 25.4},
|
||||
|
||||
invalidStallVelocity: function() {
|
||||
if(!this.motor['homing-mode'].startsWith('stall-')) return false;
|
||||
return this.maxStallVelocity < this.motor['search-velocity'];
|
||||
},
|
||||
|
||||
stallRPM: function() {
|
||||
var v = this.motor['search-velocity'];
|
||||
return 1000 * v / this.motor['travel-per-rev'];
|
||||
},
|
||||
|
||||
maxStallVelocity: function() {
|
||||
var maxRate = 900000/this.motor['stall-sample-time'];
|
||||
var ustep = this.motor['stall-microstep'];
|
||||
var angle = this.motor['step-angle'];
|
||||
var travel = this.motor['travel-per-rev'];
|
||||
var maxStall = maxRate * 60/ 360 /1000 * angle/ ustep * travel;
|
||||
|
||||
return 1 * maxStall.toFixed(3);
|
||||
},
|
||||
|
||||
stallUStepPerSec: function() {
|
||||
var ustep = this.motor['stall-microstep'];
|
||||
return this.stallRPM * this.stepsPerRev * ustep / 60;
|
||||
return templ.hmodes.indexOf(this.motor["homing-mode"]) != -1;
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
'input-changed': function() {
|
||||
Vue.nextTick(function () {
|
||||
// Limit max-velocity
|
||||
if (this.invalidMaxVelocity)
|
||||
this.$set('motor["max-velocity"]', this.maxMaxVelocity);
|
||||
|
||||
//Limit stall-velocity
|
||||
if(this.invalidStallVelocity)
|
||||
this.$set('motor["search-velocity"]', this.maxStallVelocity);
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
}.bind(this))
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
show: function(name, templ) {
|
||||
if(templ.hmodes == undefined) return true;
|
||||
return templ.hmodes.indexOf(this.motor['homing-mode']) != -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
1191
src/js/orbit.js
1191
src/js/orbit.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,42 +1,14 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
|
||||
module.exports = {
|
||||
template: '#settings-view-template',
|
||||
props: ['config', 'template'],
|
||||
template: "#settings-view-template",
|
||||
|
||||
attached: function() {
|
||||
this.svelteComponent = SvelteComponents.createComponent(
|
||||
"SettingsView",
|
||||
document.getElementById("settings")
|
||||
);
|
||||
},
|
||||
|
||||
events: {
|
||||
'input-changed': function() {
|
||||
this.$dispatch('config-changed');
|
||||
return false;
|
||||
detached: function() {
|
||||
this.svelteComponent.$destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
189
src/js/sock.js
189
src/js/sock.js
@@ -1,127 +1,106 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
This file is part of the Buildbotics firmware.
|
||||
const Sock = function(url, retry, timeout) {
|
||||
if (!(this instanceof Sock)) {
|
||||
return new Sock(url, retry);
|
||||
}
|
||||
|
||||
Copyright (c) 2015 - 2018, Buildbotics LLC
|
||||
All rights reserved.
|
||||
if (typeof retry == "undefined") {
|
||||
retry = 2000;
|
||||
}
|
||||
if (typeof timeout == "undefined") {
|
||||
timeout = 16000;
|
||||
}
|
||||
|
||||
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/>.
|
||||
this.url = url;
|
||||
this.retry = retry;
|
||||
this.timeout = timeout;
|
||||
this.divisions = 4;
|
||||
this.count = 0;
|
||||
|
||||
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.
|
||||
this.connect();
|
||||
};
|
||||
|
||||
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/>.
|
||||
Sock.prototype.onmessage = function() {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
For information regarding this software email:
|
||||
"Joseph Coffland" <joseph@buildbotics.com>
|
||||
Sock.prototype.onopen = function() {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
\******************************************************************************/
|
||||
Sock.prototype.onclose = function() {
|
||||
// Ignore
|
||||
};
|
||||
|
||||
'use strict'
|
||||
Sock.prototype.connect = function() {
|
||||
console.debug("connecting to", this.url);
|
||||
this.close();
|
||||
|
||||
this._sock = new SockJS(this.url);
|
||||
|
||||
var Sock = function (url, retry, timeout) {
|
||||
if (!(this instanceof Sock)) return new Sock(url, retry);
|
||||
this._sock.onmessage = function(e) {
|
||||
console.debug("msg:", e.data);
|
||||
this.heartbeat("msg");
|
||||
this.onmessage(e);
|
||||
}.bind(this);
|
||||
|
||||
if (typeof retry == 'undefined') retry = 2000;
|
||||
if (typeof timeout == 'undefined') timeout = 16000;
|
||||
this._sock.onopen = function() {
|
||||
console.debug("connected");
|
||||
this.heartbeat("open");
|
||||
this.onopen();
|
||||
}.bind(this);
|
||||
|
||||
this.url = url;
|
||||
this.retry = retry;
|
||||
this.timeout = timeout;
|
||||
this.divisions = 4;
|
||||
this.count = 0;
|
||||
this._sock.onclose = function() {
|
||||
console.debug("disconnected");
|
||||
this._cancel_timeout();
|
||||
|
||||
this.connect();
|
||||
}
|
||||
this.onclose();
|
||||
if (typeof this._sock != "undefined") {
|
||||
setTimeout(this.connect.bind(this), this.retry);
|
||||
}
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
Sock.prototype._timedout = function() {
|
||||
// Divide timeout so slow browser doesn't trigger timeouts when the
|
||||
// connection is good.
|
||||
if (this.divisions <= ++this.count) {
|
||||
console.debug("connection timedout");
|
||||
this._timeout = undefined;
|
||||
this._sock.close();
|
||||
|
||||
Sock.prototype.onmessage = function () {}
|
||||
Sock.prototype.onopen = function () {}
|
||||
Sock.prototype.onclose = function () {}
|
||||
} else {
|
||||
this._set_timeout();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Sock.prototype.connect = function () {
|
||||
console.debug('connecting to', this.url);
|
||||
this.close();
|
||||
|
||||
this._sock = new SockJS(this.url);
|
||||
|
||||
this._sock.onmessage = function (e) {
|
||||
console.debug('msg:', e.data);
|
||||
this.heartbeat('msg');
|
||||
this.onmessage(e);
|
||||
}.bind(this);
|
||||
|
||||
|
||||
this._sock.onopen = function () {
|
||||
console.debug('connected');
|
||||
this.heartbeat('open');
|
||||
this.onopen();
|
||||
}.bind(this);
|
||||
|
||||
|
||||
this._sock.onclose = function () {
|
||||
console.debug('disconnected');
|
||||
this._cancel_timeout();
|
||||
|
||||
this.onclose();
|
||||
if (typeof this._sock != 'undefined')
|
||||
setTimeout(this.connect.bind(this), this.retry);
|
||||
}.bind(this);
|
||||
}
|
||||
|
||||
|
||||
Sock.prototype._timedout = function () {
|
||||
// Divide timeout so slow browser doesn't trigger timeouts when the
|
||||
// connection is good.
|
||||
if (this.divisions <= ++this.count) {
|
||||
console.debug('connection timedout');
|
||||
Sock.prototype._cancel_timeout = function() {
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = undefined;
|
||||
this._sock.close();
|
||||
this.count = 0;
|
||||
};
|
||||
|
||||
} else this._set_timeout();
|
||||
}
|
||||
Sock.prototype._set_timeout = function() {
|
||||
this._timeout = setTimeout(this._timedout.bind(this),
|
||||
this.timeout / this.divisions);
|
||||
};
|
||||
|
||||
Sock.prototype.heartbeat = function() {
|
||||
this._cancel_timeout();
|
||||
this._set_timeout();
|
||||
};
|
||||
|
||||
Sock.prototype._cancel_timeout = function () {
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = undefined;
|
||||
this.count = 0;
|
||||
}
|
||||
Sock.prototype.close = function() {
|
||||
if (typeof this._sock != "undefined") {
|
||||
const sock = this._sock;
|
||||
this._sock = undefined;
|
||||
sock.close();
|
||||
}
|
||||
};
|
||||
|
||||
Sock.prototype.send = function(msg) {
|
||||
this._sock.send(msg);
|
||||
};
|
||||
|
||||
Sock.prototype._set_timeout = function () {
|
||||
this._timeout = setTimeout(this._timedout.bind(this),
|
||||
this.timeout / this.divisions);
|
||||
}
|
||||
|
||||
|
||||
Sock.prototype.heartbeat = function (msg) {
|
||||
//console.debug('heartbeat ' + new Date().toLocaleTimeString() + ' ' + msg);
|
||||
this._cancel_timeout();
|
||||
this._set_timeout();
|
||||
}
|
||||
|
||||
|
||||
Sock.prototype.close = function () {
|
||||
if (typeof this._sock != 'undefined') {
|
||||
var sock = this._sock;
|
||||
this._sock = undefined;
|
||||
sock.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sock.prototype.send = function (msg) {this._sock.send(msg)}
|
||||
|
||||
|
||||
module.exports = Sock
|
||||
module.exports = Sock;
|
||||
|
||||
@@ -1,89 +1,69 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '#templated-input-template',
|
||||
props: ['name', 'model', 'template'],
|
||||
replace: true,
|
||||
template: "#templated-input-template",
|
||||
props: [ "name", "model", "template" ],
|
||||
|
||||
|
||||
data: function () {return {view: ''}},
|
||||
|
||||
|
||||
computed: {
|
||||
metric: function () {return this.$root.metric()},
|
||||
|
||||
|
||||
_view: function () {
|
||||
if (this.template.scale) {
|
||||
if (this.metric) return 1 * this.model.toFixed(3);
|
||||
|
||||
return 1 * (this.model / this.template.scale).toFixed(4);
|
||||
}
|
||||
|
||||
return this.model;
|
||||
data: function() {
|
||||
return { view: "" };
|
||||
},
|
||||
|
||||
computed: {
|
||||
metric: function() {
|
||||
return this.$root.display_units === "METRIC";
|
||||
},
|
||||
|
||||
units: function () {
|
||||
return (this.metric || !this.template.iunit) ?
|
||||
this.template.unit : this.template.iunit;
|
||||
_view: function() {
|
||||
if (this.template.scale) {
|
||||
if (this.metric) {
|
||||
return 1 * this.model.toFixed(3);
|
||||
}
|
||||
|
||||
return 1 * (this.model / this.template.scale).toFixed(4);
|
||||
}
|
||||
|
||||
return this.model;
|
||||
},
|
||||
|
||||
units: function() {
|
||||
return (this.metric || !this.template.iunit)
|
||||
? this.template.unit
|
||||
: this.template.iunit;
|
||||
},
|
||||
|
||||
title: function() {
|
||||
let s = `Default :${this.template.default} ${(this.template.unit || "")}`;
|
||||
|
||||
if (typeof this.template.help != "undefined") {
|
||||
s = `${this.template.help}\n${s}`;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
_view: function() {
|
||||
this.view = this._view;
|
||||
},
|
||||
|
||||
title: function () {
|
||||
var s = 'Default ' + this.template.default + ' ' +
|
||||
(this.template.unit || '');
|
||||
if (typeof this.template.help != 'undefined')
|
||||
s = this.template.help + '\n' + s;
|
||||
return s;
|
||||
view: function() {
|
||||
if (this.template.scale && !this.metric) {
|
||||
this.model = this.view * this.template.scale;
|
||||
} else {
|
||||
this.model = this.view;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ready: function() {
|
||||
this.view = this._view;
|
||||
},
|
||||
|
||||
methods: {
|
||||
change: function() {
|
||||
this.$dispatch("input-changed");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
watch: {
|
||||
_view: function () {this.view = this._view},
|
||||
|
||||
|
||||
view: function () {
|
||||
if (this.template.scale && !this.metric)
|
||||
this.model = this.view * this.template.scale;
|
||||
else this.model = this.view;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ready: function () {this.view = this._view},
|
||||
|
||||
|
||||
methods: {
|
||||
change: function () {this.$dispatch('input-changed')}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,277 +1,252 @@
|
||||
/******************************************************************************\
|
||||
"use strict";
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict';
|
||||
|
||||
const api = require('./api');
|
||||
const modbus = require('./modbus.js');
|
||||
const api = require("./api");
|
||||
const modbus = require("./modbus.js");
|
||||
const merge = require("lodash.merge");
|
||||
|
||||
module.exports = {
|
||||
template: '#tool-view-template',
|
||||
props: ['config', 'template', 'state'],
|
||||
template: "#tool-view-template",
|
||||
props: [ "config", "template", "state" ],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
address: 0,
|
||||
value: 0,
|
||||
toolList: [
|
||||
{
|
||||
id: "disabled",
|
||||
name: "Disabled"
|
||||
},
|
||||
{
|
||||
id: "router",
|
||||
type: "PWM Spindle",
|
||||
name: "Router (Makita, etc)"
|
||||
},
|
||||
{
|
||||
id: "laser",
|
||||
type: "PWM Spindle",
|
||||
name: "Laser (J Tech, etc)"
|
||||
},
|
||||
{
|
||||
id: "pwm",
|
||||
name: "PWM Spindle"
|
||||
},
|
||||
{
|
||||
id: "unsupported-separator",
|
||||
name: "Unsupported Tools",
|
||||
disabled: true,
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "huanyang-vfd",
|
||||
name: "Huanyang VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "custom-modbus-vfd",
|
||||
name: "Custom Modbus VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "ac-tech-vfd",
|
||||
name: "AC-Tech VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "nowforever-vfd",
|
||||
name: "Nowforever VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "delta-vfd",
|
||||
name: "Delta VFD015M21A (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "yl600-vfd",
|
||||
name: "YL600, YL620, YL620-A VFD (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "fr-d700-vfd",
|
||||
name: "FR-D700 (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "sunfar-e300-vfd",
|
||||
name: "Sunfar E300 (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "omron-mx2-vfd",
|
||||
name: "OMRON MX2",
|
||||
unsupported: true
|
||||
data: function() {
|
||||
return {
|
||||
address: 0,
|
||||
value: 0,
|
||||
toolList: [
|
||||
{
|
||||
id: "disabled",
|
||||
name: "Disabled"
|
||||
},
|
||||
{
|
||||
id: "router",
|
||||
type: "PWM Spindle",
|
||||
name: "Router (Makita, etc)"
|
||||
},
|
||||
{
|
||||
id: "laser",
|
||||
type: "PWM Spindle",
|
||||
name: "Laser (J Tech, etc)"
|
||||
},
|
||||
{
|
||||
id: "pwm",
|
||||
name: "PWM Spindle"
|
||||
},
|
||||
{
|
||||
id: "unsupported-separator",
|
||||
name: "Unsupported Tools",
|
||||
disabled: true,
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "huanyang-vfd",
|
||||
name: "Huanyang VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "custom-modbus-vfd",
|
||||
name: "Custom Modbus VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "ac-tech-vfd",
|
||||
name: "AC-Tech VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "nowforever-vfd",
|
||||
name: "Nowforever VFD",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "delta-vfd",
|
||||
name: "Delta VFD015M21A (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "yl600-vfd",
|
||||
name: "YL600, YL620, YL620-A VFD (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "fr-d700-vfd",
|
||||
name: "FR-D700 (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "sunfar-e300-vfd",
|
||||
name: "Sunfar E300 (Beta)",
|
||||
unsupported: true
|
||||
},
|
||||
{
|
||||
id: "omron-mx2-vfd",
|
||||
name: "OMRON MX2",
|
||||
unsupported: true
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
components: {
|
||||
"modbus-reg": require("./modbus-reg.js")
|
||||
},
|
||||
|
||||
watch: {
|
||||
"state.mr": function() {
|
||||
this.value = this.state.mr;
|
||||
}
|
||||
},
|
||||
|
||||
events: {
|
||||
"input-changed": function() {
|
||||
this.$dispatch("config-changed");
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
ready: function() {
|
||||
this.value = this.state.mr;
|
||||
},
|
||||
|
||||
computed: {
|
||||
regs_tmpl: function() {
|
||||
return this.template["modbus-spindle"].regs;
|
||||
},
|
||||
|
||||
tool_type: function() {
|
||||
return this.config.tool["tool-type"].toUpperCase();
|
||||
},
|
||||
|
||||
selected_tool: function() {
|
||||
return this.config.tool["selected-tool"];
|
||||
},
|
||||
|
||||
is_pwm_spindle: function() {
|
||||
return this.selected_tool == "pwm";
|
||||
},
|
||||
|
||||
is_modbus: function() {
|
||||
switch (this.selected_tool) {
|
||||
case "disabled":
|
||||
case "laser":
|
||||
case "router":
|
||||
case "pwm":
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
modbus_status: function() {
|
||||
return modbus.status_to_string(this.state.mx);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
change_selected_tool: function() {
|
||||
const selectedToolSettings = this.config["selected-tool-settings"] || {};
|
||||
const settings = selectedToolSettings[this.selected_tool] || {};
|
||||
this.config.tool = merge({}, this.config.tool, settings["tool"]);
|
||||
this.config["pwm-spindle"] = merge({}, this.config["pwm-spindle"], settings["pwm-spindle"]);
|
||||
this.config["modbus-spindle"] = merge({}, this.config["modbus-spindle"], settings["modbus-spindle"]);
|
||||
|
||||
const tool = this.toolList.find(tool => tool.id == this.config.tool["selected-tool"]);
|
||||
this.config.tool["tool-type"] = tool.type || tool.name;
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
show_tool_settings: function(key) {
|
||||
switch (true) {
|
||||
case key === "tool-type":
|
||||
case key === "selected-tool":
|
||||
return false;
|
||||
|
||||
case this.selected_tool === "disabled":
|
||||
return false;
|
||||
|
||||
case this.selected_tool === "laser":
|
||||
case this.selected_tool === "router":
|
||||
switch (key) {
|
||||
case "tool-enable-mode":
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
get_reg_type: function(reg) {
|
||||
return this.regs_tmpl.template["reg-type"].values[this.state[`${reg}vt`]];
|
||||
},
|
||||
|
||||
get_reg_addr: function(reg) {
|
||||
return this.state[`${reg}va`];
|
||||
},
|
||||
|
||||
get_reg_value: function(reg) {
|
||||
return this.state[`${reg}vv`];
|
||||
},
|
||||
|
||||
get_reg_fails: function(reg) {
|
||||
const fails = this.state[`${reg}vr`];
|
||||
return fails == 255 ? "Max" : fails;
|
||||
},
|
||||
|
||||
show_modbus_field: function(key) {
|
||||
return key != "regs" && (key != "multi-write" || this.tool_type == "CUSTOM MODBUS VFD");
|
||||
},
|
||||
|
||||
read: function(e) {
|
||||
e.preventDefault();
|
||||
api.put("modbus/read", { address: this.address });
|
||||
},
|
||||
|
||||
write: function(e) {
|
||||
e.preventDefault();
|
||||
api.put("modbus/write", { address: this.address, value: this.value });
|
||||
},
|
||||
|
||||
customize: function(e) {
|
||||
e.preventDefault();
|
||||
this.config.tool["tool-type"] = "Custom Modbus VFD";
|
||||
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
const reg = this.regs_tmpl.index[i];
|
||||
regs[i]["reg-type"] = this.get_reg_type(reg);
|
||||
regs[i]["reg-addr"] = this.get_reg_addr(reg);
|
||||
regs[i]["reg-value"] = this.get_reg_value(reg);
|
||||
}
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
clear: function(e) {
|
||||
e.preventDefault();
|
||||
this.config.tool["tool-type"] = "Custom Modbus VFD";
|
||||
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
regs[i]["reg-type"] = "disabled";
|
||||
regs[i]["reg-addr"] = 0;
|
||||
regs[i]["reg-value"] = 0;
|
||||
}
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
reset_failures: function(e) {
|
||||
e.preventDefault();
|
||||
const regs = this.config["modbus-spindle"].regs;
|
||||
for (let reg = 0; reg < regs.length; reg++) {
|
||||
this.$dispatch("send", `$${reg}vr=0`);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
'modbus-reg': require('./modbus-reg.js')
|
||||
},
|
||||
|
||||
watch: {
|
||||
'state.mr': function () { this.value = this.state.mr }
|
||||
},
|
||||
|
||||
events: {
|
||||
'input-changed': function () {
|
||||
this.$dispatch('config-changed');
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
this.value = this.state.mr;
|
||||
},
|
||||
|
||||
computed: {
|
||||
regs_tmpl: function () {
|
||||
return this.template['modbus-spindle'].regs;
|
||||
},
|
||||
|
||||
tool_type: function () {
|
||||
return this.config.tool['tool-type'].toUpperCase();
|
||||
},
|
||||
|
||||
selected_tool: function () {
|
||||
return this.config.tool['selected-tool'];
|
||||
},
|
||||
|
||||
is_pwm_spindle: function () {
|
||||
return this.selected_tool == 'pwm';
|
||||
},
|
||||
|
||||
is_modbus: function () {
|
||||
switch (this.selected_tool) {
|
||||
case "disabled":
|
||||
case "laser":
|
||||
case "router":
|
||||
case "pwm":
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
modbus_status: function () {
|
||||
return modbus.status_to_string(this.state.mx);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
change_selected_tool: function () {
|
||||
const selectedToolSettings = this.config['selected-tool-settings'] || {};
|
||||
const settings = selectedToolSettings[this.selected_tool] || {};
|
||||
this.config.tool = merge({}, this.config.tool, settings['tool']);
|
||||
this.config['pwm-spindle'] = merge({}, this.config['pwm-spindle'], settings['pwm-spindle']);
|
||||
this.config['modbus-spindle'] = merge({}, this.config['modbus-spindle'], settings['modbus-spindle']);
|
||||
|
||||
const tool = this.toolList.find(tool => tool.id == this.config.tool['selected-tool']);
|
||||
this.config.tool["tool-type"] = tool.type || tool.name;
|
||||
|
||||
this.$dispatch("config-changed");
|
||||
},
|
||||
|
||||
show_tool_settings: function (key) {
|
||||
switch (true) {
|
||||
case key === "tool-type":
|
||||
case key === "selected-tool":
|
||||
return false;
|
||||
|
||||
case this.selected_tool === "disabled":
|
||||
return false;
|
||||
|
||||
case this.selected_tool === "laser":
|
||||
case this.selected_tool === "router":
|
||||
switch (key) {
|
||||
case "tool-enable-mode":
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
get_reg_type: function (reg) {
|
||||
return this.regs_tmpl.template['reg-type'].values[this.state[reg + 'vt']];
|
||||
},
|
||||
|
||||
get_reg_addr: function (reg) {
|
||||
return this.state[reg + 'va'];
|
||||
},
|
||||
|
||||
get_reg_value: function (reg) {
|
||||
return this.state[reg + 'vv'];
|
||||
},
|
||||
|
||||
get_reg_fails: function (reg) {
|
||||
const fails = this.state[reg + 'vr']
|
||||
return fails == 255 ? 'Max' : fails;
|
||||
},
|
||||
|
||||
show_modbus_field: function (key) {
|
||||
return key != 'regs' &&
|
||||
(key != 'multi-write' || this.tool_type == 'CUSTOM MODBUS VFD');
|
||||
},
|
||||
|
||||
read: function (e) {
|
||||
e.preventDefault();
|
||||
api.put('modbus/read', { address: this.address });
|
||||
},
|
||||
|
||||
write: function (e) {
|
||||
e.preventDefault();
|
||||
api.put('modbus/write', { address: this.address, value: this.value });
|
||||
},
|
||||
|
||||
customize: function (e) {
|
||||
e.preventDefault();
|
||||
this.config.tool['tool-type'] = 'Custom Modbus VFD';
|
||||
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
const reg = this.regs_tmpl.index[i];
|
||||
regs[i]['reg-type'] = this.get_reg_type(reg);
|
||||
regs[i]['reg-addr'] = this.get_reg_addr(reg);
|
||||
regs[i]['reg-value'] = this.get_reg_value(reg);
|
||||
}
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
},
|
||||
|
||||
clear: function (e) {
|
||||
e.preventDefault();
|
||||
this.config.tool['tool-type'] = 'Custom Modbus VFD';
|
||||
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
for (let i = 0; i < regs.length; i++) {
|
||||
regs[i]['reg-type'] = 'disabled';
|
||||
regs[i]['reg-addr'] = 0;
|
||||
regs[i]['reg-value'] = 0;
|
||||
}
|
||||
|
||||
this.$dispatch('config-changed');
|
||||
},
|
||||
|
||||
reset_failures: function (e) {
|
||||
e.preventDefault();
|
||||
const regs = this.config['modbus-spindle'].regs;
|
||||
for (let reg = 0; reg < regs.length; reg++)
|
||||
this.$dispatch('send', '\$' + reg + 'vr=0');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,58 +1,47 @@
|
||||
/******************************************************************************\
|
||||
|
||||
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>
|
||||
|
||||
\******************************************************************************/
|
||||
|
||||
'use strict'
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
replace: true,
|
||||
template: '{{text}}<span class="unit">{{metric ? unit : iunit}}</span>',
|
||||
props: ['value', 'precision', 'unit', 'iunit', 'scale'],
|
||||
replace: true,
|
||||
template: '{{text}}<span class="unit">{{metric ? unit : iunit}}</span>',
|
||||
props: [ "value", "precision", "unit", "iunit", "scale" ],
|
||||
|
||||
computed: {
|
||||
metric: {
|
||||
cache: false,
|
||||
get: function() {
|
||||
return this.$root.display_units === "METRIC";
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
metric: function () {return !this.$root.state.imperial},
|
||||
text: function() {
|
||||
let value = this.value;
|
||||
if (typeof value == "undefined") {
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!this.metric) {
|
||||
value /= this.scale;
|
||||
}
|
||||
|
||||
text: function () {
|
||||
var value = this.value;
|
||||
if (typeof value == 'undefined') return '';
|
||||
return (1 * value.toFixed(this.precision)).toLocaleString();
|
||||
}
|
||||
},
|
||||
|
||||
if (!this.metric) value /= this.scale;
|
||||
ready: function() {
|
||||
if (typeof this.precision == "undefined") {
|
||||
this.precision = 0;
|
||||
}
|
||||
|
||||
return (1 * value.toFixed(this.precision)).toLocaleString();
|
||||
if (typeof this.unit == "undefined") {
|
||||
this.unit = "mm";
|
||||
}
|
||||
|
||||
if (typeof this.iunit == "undefined") {
|
||||
this.iunit = "in";
|
||||
}
|
||||
|
||||
if (typeof this.scale == "undefined") {
|
||||
this.scale = 25.4;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
ready: function () {
|
||||
if (typeof this.precision == 'undefined') this.precision = 0;
|
||||
if (typeof this.unit == 'undefined') this.unit = 'mm';
|
||||
if (typeof this.iunit == 'undefined') this.iunit = 'in';
|
||||
if (typeof this.scale == 'undefined') this.scale = 25.4;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
9
src/js/utils.js
Normal file
9
src/js/utils.js
Normal file
@@ -0,0 +1,9 @@
|
||||
function clickFileInput(formClass) {
|
||||
const form = document.querySelector(`.${formClass}`);
|
||||
form.reset();
|
||||
form.querySelector("input").click();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
clickFileInput
|
||||
};
|
||||
Reference in New Issue
Block a user