407 lines
13 KiB
HTML
407 lines
13 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
|
/>
|
|
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
|
<title>Victron Multiplus Monitor</title>
|
|
<style>
|
|
.dot-off {
|
|
height: 25px;
|
|
width: 25px;
|
|
background-color: #bbb;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
}
|
|
|
|
.dot-green {
|
|
height: 25px;
|
|
width: 25px;
|
|
background-color: #2aed4e;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
}
|
|
.dot-red {
|
|
height: 25px;
|
|
width: 25px;
|
|
background-color: #ed3d34;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
}
|
|
.blink-red {
|
|
height: 25px;
|
|
width: 25px;
|
|
background-color: #ed3d34;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
animation: blinkingRedDot 1s infinite;
|
|
}
|
|
@keyframes blinkingRedDot {
|
|
0% {
|
|
background-color: #ed3d34;
|
|
}
|
|
49% {
|
|
background-color: transparent;
|
|
}
|
|
50% {
|
|
background-color: transparent;
|
|
}
|
|
99% {
|
|
background-color: #ed3d34;
|
|
}
|
|
100% {
|
|
background-color: #ed3d34;
|
|
}
|
|
}
|
|
.blink-green {
|
|
height: 25px;
|
|
width: 25px;
|
|
background-color: #2aed4e;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
animation: blinkingGreenDot 1s infinite;
|
|
}
|
|
@keyframes blinkingGreenDot {
|
|
0% {
|
|
background-color: #2aed4e;
|
|
}
|
|
49% {
|
|
background-color: transparent;
|
|
}
|
|
50% {
|
|
background-color: transparent;
|
|
}
|
|
99% {
|
|
background-color: #2aed4e;
|
|
}
|
|
100% {
|
|
background-color: #2aed4e;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<script src="js/vue.js"></script>
|
|
<script src="js/controller.js"></script>
|
|
<script type="text/javascript">
|
|
window.onload = function() {
|
|
loadContent();
|
|
};
|
|
</script>
|
|
|
|
<h1 class="display-4 text-center">Inverter GUI</h1>
|
|
<div class="container" id="app">
|
|
<div class="alert alert-danger" role="alert" v-if="error.has_error">
|
|
{{ error.error_message }}
|
|
</div>
|
|
<div
|
|
class="alert"
|
|
v-if="control.message !== ''"
|
|
v-bind:class="[control.has_error ? 'alert-danger' : 'alert-success']"
|
|
>
|
|
{{ control.message }}
|
|
</div>
|
|
<div class="row">
|
|
<div class="col">
|
|
<div class="card mb-3">
|
|
<div class="card-body">
|
|
<h4 class="card-title">Remote Panel Control</h4>
|
|
<p class="text-muted mb-2">
|
|
Mode and current limit are applied together, equivalent to
|
|
<code>set_remote_panel_state</code>.
|
|
</p>
|
|
<p class="mb-1">
|
|
<strong>Current Mode:</strong>
|
|
{{ remoteModeLabel(state.remote_panel) }}
|
|
</p>
|
|
<p class="mb-1">
|
|
<strong>Current Limit:</strong>
|
|
{{ state.remote_panel.current_limit === null || state.remote_panel.current_limit === undefined ? 'Unknown' : state.remote_panel.current_limit + ' A' }}
|
|
</p>
|
|
<p class="mb-3">
|
|
<strong>Standby:</strong>
|
|
{{ remoteStandbyLabel(state.remote_panel) }}
|
|
</p>
|
|
<div class="row">
|
|
<div class="col-md-8">
|
|
<form v-on:submit.prevent="applyRemotePanelState">
|
|
<div class="form-row">
|
|
<div class="form-group col-md-6">
|
|
<label for="modeSelect">Remote Panel Mode</label>
|
|
<select
|
|
class="form-control"
|
|
id="modeSelect"
|
|
v-model="remote_form.mode"
|
|
v-bind:disabled="!state.remote_panel.writable || control.busy"
|
|
>
|
|
<option value="on">on</option>
|
|
<option value="off">off</option>
|
|
<option value="charger_only">charger_only</option>
|
|
<option value="inverter_only">inverter_only</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group col-md-6">
|
|
<label for="currentLimitInput">AC Input Current Limit (A)</label>
|
|
<input
|
|
id="currentLimitInput"
|
|
type="number"
|
|
min="0"
|
|
step="0.1"
|
|
class="form-control"
|
|
v-model="remote_form.current_limit"
|
|
placeholder="leave blank to keep current"
|
|
v-bind:disabled="!state.remote_panel.writable || control.busy"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
class="btn btn-primary"
|
|
v-bind:disabled="!state.remote_panel.writable || control.busy"
|
|
>
|
|
Apply Mode + Current Limit
|
|
</button>
|
|
</form>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<form v-on:submit.prevent="applyStandby">
|
|
<div class="form-group">
|
|
<div class="form-check mt-4">
|
|
<input
|
|
id="standbySwitch"
|
|
type="checkbox"
|
|
class="form-check-input"
|
|
v-model="remote_form.standby"
|
|
v-bind:disabled="!state.remote_panel.writable || control.busy"
|
|
/>
|
|
<label class="form-check-label" for="standbySwitch">
|
|
Prevent sleep while off
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
class="btn btn-secondary"
|
|
v-bind:disabled="!state.remote_panel.writable || control.busy"
|
|
>
|
|
Apply Standby
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="mt-3 text-muted" v-if="state.remote_panel.last_updated">
|
|
Last update {{ state.remote_panel.last_updated }}
|
|
<span v-if="state.remote_panel.last_command">
|
|
({{ state.remote_panel.last_command }})
|
|
</span>
|
|
</div>
|
|
<div class="mt-2 text-danger" v-if="state.remote_panel.last_error">
|
|
{{ state.remote_panel.last_error }}
|
|
</div>
|
|
<div class="mt-2 text-warning" v-if="!state.remote_panel.writable">
|
|
Remote control is unavailable for this data source.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col">
|
|
<hr />
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-sm p-auto">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Output Current</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.output_current }} A
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Output Voltage</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.output_voltage }} V
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Output Frequency</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.output_frequency }} Hz
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Output Power</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.output_power }} W
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-auto">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Input Current</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.input_current }} A
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Input Voltage</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.input_voltage }} V
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Input Frequency</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.input_frequency }} Hz
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Input Power</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.input_power }} W
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-auto">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Battery Current</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.battery_current }} A
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Battery Voltage</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.battery_voltage }} V
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Battery Charge</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.battery_charge }} %
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Battery Power</h5>
|
|
<blockquote class="blockquote">
|
|
{{ state.battery_power }} W
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col">
|
|
<hr />
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Mains</h5>
|
|
<span v-bind:class="[state.led_map.led_mains]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Absorption</h5>
|
|
<span v-bind:class="[state.led_map.led_absorb]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Bulk</h5>
|
|
<span v-bind:class="[state.led_map.led_bulk]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center ">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Float</h5>
|
|
<span v-bind:class="[state.led_map.led_float]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Inverter</h5>
|
|
<span v-bind:class="[state.led_map.led_inverter]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Overload</h5>
|
|
<span v-bind:class="[state.led_map.led_overload]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Low Battery</h5>
|
|
<span v-bind:class="[state.led_map.led_bat_low]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm p-3">
|
|
<div class="card text-center">
|
|
<div class="card-body">
|
|
<h5 class="card-title">Temperature</h5>
|
|
<span v-bind:class="[state.led_map.led_over_temp]"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|