281 lines
7.5 KiB
JavaScript
281 lines
7.5 KiB
JavaScript
var app;
|
|
const timeoutMax = 30000;
|
|
const timeoutMin = 1000;
|
|
var timeout = timeoutMin;
|
|
|
|
function defaultRemotePanelState() {
|
|
return {
|
|
writable: false,
|
|
mode: "unknown",
|
|
current_limit: null,
|
|
standby: null,
|
|
last_command: "",
|
|
last_error: "",
|
|
last_updated: ""
|
|
};
|
|
}
|
|
|
|
function defaultState() {
|
|
return {
|
|
output_current: null,
|
|
output_voltage: 0,
|
|
output_frequency: 0,
|
|
output_power: 0,
|
|
input_current: 0,
|
|
input_voltage: 0,
|
|
input_frequency: 0,
|
|
input_power: 0,
|
|
battery_current: 0,
|
|
battery_voltage: 0,
|
|
battery_charge: 0,
|
|
battery_power: 0,
|
|
led_map: {
|
|
led_mains: "dot-off",
|
|
led_absorb: "dot-off",
|
|
led_bulk: "dot-off",
|
|
led_float: "dot-off",
|
|
led_inverter: "dot-off",
|
|
led_overload: "dot-off",
|
|
led_bat_low: "dot-off",
|
|
led_over_temp: "dot-off"
|
|
},
|
|
remote_panel: defaultRemotePanelState()
|
|
};
|
|
}
|
|
|
|
function loadContent() {
|
|
app = new Vue({
|
|
el: "#app",
|
|
data: {
|
|
error: {
|
|
has_error: false,
|
|
error_message: ""
|
|
},
|
|
control: {
|
|
busy: false,
|
|
has_error: false,
|
|
message: ""
|
|
},
|
|
remote_form: {
|
|
mode: "on",
|
|
current_limit: "",
|
|
standby: false
|
|
},
|
|
state: defaultState()
|
|
},
|
|
methods: {
|
|
syncRemoteFormFromState: function(remoteState) {
|
|
if (!remoteState) {
|
|
return;
|
|
}
|
|
if (remoteState.mode && remoteState.mode !== "unknown") {
|
|
this.remote_form.mode = remoteState.mode;
|
|
}
|
|
if (remoteState.current_limit === null || remoteState.current_limit === undefined) {
|
|
this.remote_form.current_limit = "";
|
|
} else {
|
|
this.remote_form.current_limit = String(remoteState.current_limit);
|
|
}
|
|
if (remoteState.standby === null || remoteState.standby === undefined) {
|
|
this.remote_form.standby = false;
|
|
} else {
|
|
this.remote_form.standby = !!remoteState.standby;
|
|
}
|
|
},
|
|
remoteModeLabel: function(remoteState) {
|
|
var mode = (remoteState && remoteState.mode) || "unknown";
|
|
if (mode === "charger_only") {
|
|
return "Charger Only";
|
|
}
|
|
if (mode === "inverter_only") {
|
|
return "Inverter Only";
|
|
}
|
|
if (mode === "on") {
|
|
return "On";
|
|
}
|
|
if (mode === "off") {
|
|
return "Off";
|
|
}
|
|
return "Unknown";
|
|
},
|
|
remoteStandbyLabel: function(remoteState) {
|
|
if (!remoteState || remoteState.standby === null || remoteState.standby === undefined) {
|
|
return "Unknown";
|
|
}
|
|
return remoteState.standby ? "Enabled" : "Disabled";
|
|
},
|
|
refreshRemoteState: function() {
|
|
var self = this;
|
|
fetch(getAPIURI("api/remote-panel/state"))
|
|
.then(function(resp) {
|
|
if (!resp.ok) {
|
|
throw new Error("Could not load remote panel state.");
|
|
}
|
|
return resp.json();
|
|
})
|
|
.then(function(payload) {
|
|
self.state.remote_panel = payload;
|
|
self.syncRemoteFormFromState(payload);
|
|
})
|
|
.catch(function(err) {
|
|
self.control.has_error = true;
|
|
self.control.message = err.message;
|
|
});
|
|
},
|
|
applyRemotePanelState: function() {
|
|
var self = this;
|
|
if (!self.state.remote_panel.writable) {
|
|
return;
|
|
}
|
|
|
|
var body = {
|
|
mode: self.remote_form.mode
|
|
};
|
|
if (self.remote_form.current_limit !== "") {
|
|
var parsed = parseFloat(self.remote_form.current_limit);
|
|
if (isNaN(parsed)) {
|
|
self.control.has_error = true;
|
|
self.control.message = "Current limit must be numeric.";
|
|
return;
|
|
}
|
|
body.current_limit = parsed;
|
|
}
|
|
|
|
self.control.busy = true;
|
|
self.control.has_error = false;
|
|
self.control.message = "";
|
|
fetch(getAPIURI("api/remote-panel/state"), {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: JSON.stringify(body)
|
|
})
|
|
.then(function(resp) {
|
|
if (!resp.ok) {
|
|
return resp.text().then(function(text) {
|
|
throw new Error(text || "Failed to set remote panel mode/current limit.");
|
|
});
|
|
}
|
|
return resp.json();
|
|
})
|
|
.then(function(payload) {
|
|
self.state.remote_panel = payload;
|
|
self.syncRemoteFormFromState(payload);
|
|
self.control.has_error = false;
|
|
self.control.message = "Remote panel state updated.";
|
|
})
|
|
.catch(function(err) {
|
|
self.control.has_error = true;
|
|
self.control.message = err.message;
|
|
})
|
|
.finally(function() {
|
|
self.control.busy = false;
|
|
});
|
|
},
|
|
applyStandby: function() {
|
|
var self = this;
|
|
if (!self.state.remote_panel.writable) {
|
|
return;
|
|
}
|
|
|
|
self.control.busy = true;
|
|
self.control.has_error = false;
|
|
self.control.message = "";
|
|
fetch(getAPIURI("api/remote-panel/standby"), {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: JSON.stringify({
|
|
standby: !!self.remote_form.standby
|
|
})
|
|
})
|
|
.then(function(resp) {
|
|
if (!resp.ok) {
|
|
return resp.text().then(function(text) {
|
|
throw new Error(text || "Failed to set standby mode.");
|
|
});
|
|
}
|
|
return resp.json();
|
|
})
|
|
.then(function(payload) {
|
|
self.state.remote_panel = payload;
|
|
self.syncRemoteFormFromState(payload);
|
|
self.control.has_error = false;
|
|
self.control.message = "Standby mode updated.";
|
|
})
|
|
.catch(function(err) {
|
|
self.control.has_error = true;
|
|
self.control.message = err.message;
|
|
})
|
|
.finally(function() {
|
|
self.control.busy = false;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
app.refreshRemoteState();
|
|
connect();
|
|
}
|
|
|
|
function connect() {
|
|
if (window["WebSocket"]) {
|
|
var conn = new WebSocket(getURI());
|
|
conn.onclose = function(evt) {
|
|
app.error.has_error = true;
|
|
app.error.error_message =
|
|
"Server not reachable. Trying to reconnect in " +
|
|
timeout / 1000 +
|
|
" second(s).";
|
|
|
|
console.log(app.error.error_message, evt.reason);
|
|
setTimeout(function() {
|
|
connect();
|
|
}, timeout);
|
|
timeout = timeout * 2;
|
|
if (timeout > timeoutMax) {
|
|
timeout = timeoutMax;
|
|
}
|
|
};
|
|
|
|
conn.onopen = function() {
|
|
timeout = timeoutMin;
|
|
app.error.has_error = false;
|
|
};
|
|
|
|
conn.onmessage = function(evt) {
|
|
var update = JSON.parse(evt.data);
|
|
app.state = update;
|
|
if (!app.control.busy) {
|
|
app.syncRemoteFormFromState(update.remote_panel);
|
|
}
|
|
};
|
|
} else {
|
|
app.error.has_error = true;
|
|
app.error.error_message = "Our browser does not support WebSockets.";
|
|
}
|
|
}
|
|
|
|
function getURI() {
|
|
var loc = window.location,
|
|
new_uri;
|
|
if (loc.protocol === "https:") {
|
|
new_uri = "wss:";
|
|
} else {
|
|
new_uri = "ws:";
|
|
}
|
|
new_uri += "//" + loc.host;
|
|
new_uri += loc.pathname + "ws";
|
|
return new_uri;
|
|
}
|
|
|
|
function getAPIURI(path) {
|
|
var base = window.location.pathname;
|
|
if (base.slice(-1) !== "/") {
|
|
base += "/";
|
|
}
|
|
return base + path.replace(/^\/+/, "");
|
|
}
|