tesla-charge-controller/webapp/script.js

441 lines
12 KiB
JavaScript
Raw Permalink Normal View History

2024-01-23 10:40:56 +11:00
const api_url = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port;
Object.prototype.disable = function () {
var that = this;
for (var i = 0, len = that.length; i < len; i++) {
that[i].disabled = true;
}
return that;
};
Object.prototype.enable = function () {
var that = this;
for (var i = 0, len = that.length; i < len; i++) {
that[i].disabled = false;
}
return that;
};
function init_main() {
refresh_interval = register(refresh);
refresh();
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
clearInterval(refresh_interval);
} else {
refresh();
refresh_interval = register(refresh);
}
});
}
function init_pid() {
refresh_gains();
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
refresh_gains();
}
});
}
function init_shutoff() {
refresh_shutoff();
document.addEventListener("visibilitychange", () => {
if (!document.hidden) {
refresh_shutoff();
}
});
}
2024-01-23 10:40:56 +11:00
function init_info() {
refresh_interval = register(refresh_info);
refresh_info();
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
clearInterval(refresh_interval);
} else {
refresh_info();
refresh_interval = register(refresh_info);
}
});
}
2024-02-13 09:32:35 +11:00
function init_regulator() {
refresh_interval = register(refresh_regulator_state);
refresh_regulator_state();
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
clearInterval(refresh_interval);
} else {
refresh_regulator_state();
refresh_interval = register(refresh_regulator_state);
}
});
}
2024-01-23 10:40:56 +11:00
function register(func) {
return setInterval(func, 5000);
}
function flash() {
fetch(api_url + "/flash", { method: "POST" });
}
var is_automatic_control;
var current_min_rate;
var current_max_rate;
const delay = (time) => {
return new Promise(resolve => setTimeout(resolve, time));
};
function set_minimum() {
var set_button = document.getElementById("set-minimum");
var number_input = document.getElementById("min-rate");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/set-min/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_buttons();
});
}
}
function change_min() {
var set_button = document.getElementById("set-minimum");
var number_input = document.getElementById("min-rate");
set_button.disabled = (number_input.value == current_min_rate);
}
function set_maximum() {
var set_button = document.getElementById("set-maximum");
var number_input = document.getElementById("max-rate");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/set-max/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_buttons();
});
}
}
function change_max() {
var set_button = document.getElementById("set-maximum");
var number_input = document.getElementById("max-rate");
set_button.disabled = (number_input.value == current_max_rate);
}
function set_proportional() {
var set_button = document.getElementById("set-proportional");
var number_input = document.getElementById("proportional-gain");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/pid-settings/proportional/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_gains();
});
}
}
function set_derivative() {
var set_button = document.getElementById("set-derivative");
var number_input = document.getElementById("derivative-gain");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/pid-settings/derivative/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_gains();
});
}
}
function set_shutoff_voltage() {
var set_button = document.getElementById("set-shutoff-voltage");
var number_input = document.getElementById("shutoff-voltage");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/shutoff/voltage/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_shutoff();
});
}
}
function set_shutoff_time() {
var set_button = document.getElementById("set-shutoff-time");
var number_input = document.getElementById("shutoff-time");
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
fetch(api_url + "/shutoff/time/" + number_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
refresh_shutoff();
});
}
}
2024-02-13 09:32:35 +11:00
function set_regulator_state() {
var set_button = document.getElementById("set-regulator-state");
var state_input = document.getElementById("regstate");
set_button.disabled = true;
state_input.disabled = true;
fetch(api_url + "/set-regulator-state/" + state_input.value, { method: "POST" })
.then(async (response) => {
let delayres = await delay(300);
refresh_regulator_state();
});
}
2024-01-25 16:03:19 +11:00
function set_load_divisor() {
var set_button = document.getElementById("set-load-divisor");
var number_input = document.getElementById("load-divisor");
2024-01-23 10:40:56 +11:00
if (!isNaN(number_input.value)) {
set_button.disabled = true;
number_input.disabled = true;
2024-01-25 16:03:19 +11:00
fetch(api_url + "/pid-settings/load_divisor/" + number_input.value, { method: "POST" })
2024-01-23 10:40:56 +11:00
.then(async (response) => {
let delayres = await delay(100);
refresh_gains();
});
}
}
function disable_automatic_control() {
if (is_automatic_control) {
document.getElementById('control-disabled').checked = true;
document.body.classList.add("loading");
fetch(api_url + "/disable-control", { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
2024-01-23 10:40:56 +11:00
refresh_buttons();
});
}
}
function enable_automatic_control() {
if (!is_automatic_control) {
document.getElementById('control-enabled').checked = true;
document.body.classList.add("loading");
fetch(api_url + "/enable-control", { method: "POST" })
.then(async (response) => {
let delayres = await delay(100);
2024-01-23 10:40:56 +11:00
refresh_buttons();
});
}
}
function update_control_buttons(data) {
current_max_rate = data.max_rate;
current_min_rate = data.min_rate;
var number_input_min = document.getElementById("min-rate");
if (number_input_min.disabled || number_input_min.value == "") {
number_input_min.value = data.min_rate;
number_input_min.disabled = false;
}
document.getElementById("set-minimum").disabled = (number_input_min.value == current_min_rate);
var number_input_max = document.getElementById("max-rate");
if (number_input_max.disabled || number_input_max.value == "") {
number_input_max.value = data.max_rate;
number_input_max.disabled = false;
}
document.getElementById("set-maximum").disabled = (number_input_max.value == current_max_rate);
document.body.classList.remove("loading");
is_automatic_control = data.control_enable;
if (data.control_enable) {
document.getElementById('control-enabled').checked = true;
} else {
document.getElementById('control-disabled').checked = true;
}
var control_selector = document.getElementById("control-selector");
if (data.is_charging_at_home) {
if (control_selector.classList.contains('disabled')) {
control_selector.classList.remove('disabled');
}
document.getElementsByName('control').enable();
}
else {
if (!control_selector.classList.contains('disabled')) {
control_selector.classList.add('disabled');
}
document.getElementsByName('control').disable();
}
}
function refresh_gains() {
fetch(api_url + "/pid-settings/status")
.then((response) => response.json())
.then((json) => update_gains(json));
}
function update_gains(data) {
var proportional_set_button = document.getElementById("set-proportional");
var proportional_number_input = document.getElementById("proportional-gain");
proportional_set_button.disabled = false;
proportional_number_input.disabled = false;
proportional_number_input.value = data.proportional_gain;
var derivative_set_button = document.getElementById("set-derivative");
var derivative_number_input = document.getElementById("derivative-gain");
derivative_set_button.disabled = false;
derivative_number_input.disabled = false;
derivative_number_input.value = data.derivative_gain;
2024-01-25 16:03:19 +11:00
var load_divisor_button = document.getElementById("set-load-divisor");
var load_divisor_input = document.getElementById("load-divisor");
load_divisor_button.disabled = false;
load_divisor_input.disabled = false;
load_divisor_input.value = data.load_divisor;
2024-01-23 10:40:56 +11:00
}
function refresh_shutoff() {
fetch(api_url + "/shutoff/status")
.then((response) => response.json())
.then((json) => update_shutoff(json));
}
2024-02-13 09:32:35 +11:00
function refresh_regulator_state() {
var set_button = document.getElementById("set-regulator-state");
var state_input = document.getElementById("regstate");
set_button.disabled = false;
state_input.disabled = false;
fetch(api_url + "/regulator-state")
2024-02-13 09:53:19 +11:00
.then((response) => response.json())
.catch(() => null)
2024-02-13 09:32:35 +11:00
.then((json) => update_regulator_state(json));
}
function update_shutoff(data) {
var voltage_set_button = document.getElementById("set-shutoff-voltage");
var voltage_number_input = document.getElementById("shutoff-voltage");
voltage_set_button.disabled = false;
voltage_number_input.disabled = false;
voltage_number_input.value = data.voltage;
var time_set_button = document.getElementById("set-shutoff-time");
var time_number_input = document.getElementById("shutoff-time");
time_set_button.disabled = false;
time_number_input.disabled = false;
time_number_input.value = data.time;
}
2024-02-13 09:32:35 +11:00
function update_regulator_state(state) {
console.log(state);
if (state == null) { var cur = "Unknown" } else { var cur = state.regulator_state }
var current_state = document.getElementById("current-state");
current_state.textContent = "Current state: " + cur;
}
2024-01-23 10:40:56 +11:00
function refresh_buttons() {
fetch(api_url + "/control-state")
.then((response) => response.json())
.then((json) => update_control_buttons(json));
}
function refresh() {
set_favicon(null);
refresh_buttons();
fetch(api_url + "/car-state")
.then((response) => response.json())
.then((json) => update_state(json));
}
function refresh_info() {
set_favicon(null);
fetch(api_url + "/car-state")
.then((response) => response.json())
.then((json) => update_info(json));
}
function update_info(state) {
set_favicon(state.charge_state);
var info_div = document.getElementById("info");
while (info_div.childElementCount > 0) { info_div.removeChild(info_div.firstChild) }
el = document.createElement('p');
state_json = document.createElement('pre');
state_json.appendChild(document.createTextNode(JSON.stringify(state, null, '\t')));
el.appendChild(state_json);
info_div.appendChild(el);
}
function update_state(state) {
set_favicon(state.charge_state);
var info_div = document.getElementById("info");
while (info_div.childElementCount > 0) { info_div.removeChild(info_div.firstChild) }
el = document.createElement('p');
var charging_state_info = "";
switch (state.charge_state.charging_state) {
case "Charging":
charging_state_info = "charging at " + state.charge_state.charge_rate + "A";
break;
case "Stopped":
charging_state_info = "charge stopped";
break;
case "Disconnected":
charging_state_info = "disconnected"
break;
}
if (state.location_data.home) {
if (state.charge_state.charging_state == "Charging") {
charging_state_info = "set at " + state.charge_state.charge_current_request + "A, " + charging_state_info;
}
charging_state_info = "At home; " + charging_state_info;
} else {
charging_state_info = "Not home; " + charging_state_info;
}
el.appendChild(document.createTextNode(charging_state_info));
info_div.appendChild(el);
}
function set_favicon(charge_state) {
let favicon = document.getElementById("favicon");
favicon.setAttribute("href", "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>" + get_emoji(charge_state) + "</text></svg>");
}
function get_emoji(charge_state) {
if (charge_state == null) {
return "⏳";
}
else if (charge_state.charge_rate > 0) {
return "🔌";
} else if (charge_state.battery_level < 60) {
return "🪫"
} else return "🔋";
}