webapp: apply formatter on downstream sources
This commit is contained in:
parent
77af085ad3
commit
4334e60030
@ -5,30 +5,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="'values' in batteryData"> <!-- suppress the card for MQTT battery provider -->
|
<div v-else-if="'values' in batteryData">
|
||||||
|
<!-- suppress the card for MQTT battery provider -->
|
||||||
<div class="row gy-3 mt-0">
|
<div class="row gy-3 mt-0">
|
||||||
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center" :class="{
|
<div
|
||||||
|
class="card-header d-flex justify-content-between align-items-center"
|
||||||
|
:class="{
|
||||||
'text-bg-danger': batteryData.data_age >= 20,
|
'text-bg-danger': batteryData.data_age >= 20,
|
||||||
'text-bg-primary': batteryData.data_age < 20,
|
'text-bg-primary': batteryData.data_age < 20,
|
||||||
}">
|
}"
|
||||||
|
>
|
||||||
<div class="p-1 flex-grow-1">
|
<div class="p-1 flex-grow-1">
|
||||||
<div class="d-flex flex-wrap">
|
<div class="d-flex flex-wrap">
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ $t('battery.battery') }}: {{ batteryData.manufacturer }}
|
{{ $t('battery.battery') }}: {{ batteryData.manufacturer }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;" v-if="'serial' in batteryData">
|
<div style="padding-right: 2em" v-if="'serial' in batteryData">
|
||||||
{{ $t('home.SerialNumber') }}{{ batteryData.serial }}
|
{{ $t('home.SerialNumber') }}{{ batteryData.serial }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;" v-if="'fwversion' in batteryData">
|
<div style="padding-right: 2em" v-if="'fwversion' in batteryData">
|
||||||
{{ $t('battery.FwVersion') }}: {{ batteryData.fwversion }}
|
{{ $t('battery.FwVersion') }}: {{ batteryData.fwversion }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;" v-if="'hwversion' in batteryData">
|
<div style="padding-right: 2em" v-if="'hwversion' in batteryData">
|
||||||
{{ $t('battery.HwVersion') }}: {{ batteryData.hwversion }}
|
{{ $t('battery.HwVersion') }}: {{ batteryData.hwversion }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ $t('battery.DataAge') }} {{ $t('battery.Seconds', { 'val': batteryData.data_age }) }}
|
{{ $t('battery.DataAge') }}
|
||||||
|
{{ $t('battery.Seconds', { val: batteryData.data_age }) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,7 +41,11 @@
|
|||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row flex-row flex-wrap align-items-start g-3">
|
<div class="row flex-row flex-wrap align-items-start g-3">
|
||||||
<div v-for="(values, section) in batteryData.values" v-bind:key="section" class="col order-0">
|
<div
|
||||||
|
v-for="(values, section) in batteryData.values"
|
||||||
|
v-bind:key="section"
|
||||||
|
class="col order-0"
|
||||||
|
>
|
||||||
<div class="card" :class="{ 'border-info': true }">
|
<div class="card" :class="{ 'border-info': true }">
|
||||||
<div class="card-header text-bg-info">{{ $t('battery.' + section) }}</div>
|
<div class="card-header text-bg-info">{{ $t('battery.' + section) }}</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -44,7 +53,9 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ $t('battery.Property') }}</th>
|
<th scope="col">{{ $t('battery.Property') }}</th>
|
||||||
<th style="text-align: right" scope="col">{{ $t('battery.Value') }}</th>
|
<th style="text-align: right" scope="col">
|
||||||
|
{{ $t('battery.Value') }}
|
||||||
|
</th>
|
||||||
<th scope="col">{{ $t('battery.Unit') }}</th>
|
<th scope="col">{{ $t('battery.Unit') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -59,15 +70,17 @@
|
|||||||
{{ prop.value }}
|
{{ prop.value }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ $n(prop.v, 'decimal', {
|
{{
|
||||||
|
$n(prop.v, 'decimal', {
|
||||||
minimumFractionDigits: prop.d,
|
minimumFractionDigits: prop.d,
|
||||||
maximumFractionDigits: prop.d})
|
maximumFractionDigits: prop.d,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<template v-if="!isStringValue(prop)">
|
<template v-if="!isStringValue(prop)">
|
||||||
{{prop.u}}
|
{{ prop.u }}
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -78,12 +91,21 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col order-1">
|
<div class="col order-1">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div :class="{'card-header': true, 'border-bottom-0': maxIssueValue === 0}">
|
<div :class="{ 'card-header': true, 'border-bottom-0': maxIssueValue === 0 }">
|
||||||
<div class="d-flex flex-row justify-content-between align-items-baseline">
|
<div class="d-flex flex-row justify-content-between align-items-baseline">
|
||||||
{{ $t('battery.issues') }}
|
{{ $t('battery.issues') }}
|
||||||
<div v-if="maxIssueValue === 0" class="badge text-bg-success">{{ $t('battery.noIssues') }}</div>
|
<div v-if="maxIssueValue === 0" class="badge text-bg-success">
|
||||||
<div v-else-if="maxIssueValue === 1" class="badge text-bg-warning text-dark">{{ $t('battery.warning') }}</div>
|
{{ $t('battery.noIssues') }}
|
||||||
<div v-else-if="maxIssueValue === 2" class="badge text-bg-danger">{{ $t('battery.alarm') }}</div>
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="maxIssueValue === 1"
|
||||||
|
class="badge text-bg-warning text-dark"
|
||||||
|
>
|
||||||
|
{{ $t('battery.warning') }}
|
||||||
|
</div>
|
||||||
|
<div v-else-if="maxIssueValue === 2" class="badge text-bg-danger">
|
||||||
|
{{ $t('battery.alarm') }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body" v-if="'issues' in batteryData">
|
<div class="card-body" v-if="'issues' in batteryData">
|
||||||
@ -98,11 +120,16 @@
|
|||||||
<tr v-for="(prop, key) in batteryData.issues" v-bind:key="key">
|
<tr v-for="(prop, key) in batteryData.issues" v-bind:key="key">
|
||||||
<th scope="row">{{ $t('battery.' + key) }}</th>
|
<th scope="row">{{ $t('battery.' + key) }}</th>
|
||||||
<td>
|
<td>
|
||||||
<span class="badge" :class="{
|
<span
|
||||||
|
class="badge"
|
||||||
|
:class="{
|
||||||
'text-bg-warning text-dark': prop === 1,
|
'text-bg-warning text-dark': prop === 1,
|
||||||
'text-bg-danger': prop === 2
|
'text-bg-danger': prop === 2,
|
||||||
}">
|
}"
|
||||||
<template v-if="prop === 1">{{ $t('battery.warning') }}</template>
|
>
|
||||||
|
<template v-if="prop === 1">{{
|
||||||
|
$t('battery.warning')
|
||||||
|
}}</template>
|
||||||
<template v-else>{{ $t('battery.alarm') }}</template>
|
<template v-else>{{ $t('battery.alarm') }}</template>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
@ -117,7 +144,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -128,8 +154,7 @@ import type { ValueObject } from '@/types/LiveDataStatus';
|
|||||||
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {},
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
socket: {} as WebSocket,
|
socket: {} as WebSocket,
|
||||||
@ -139,8 +164,8 @@ export default defineComponent({
|
|||||||
batteryData: {} as Battery,
|
batteryData: {} as Battery,
|
||||||
isFirstFetchAfterConnect: true,
|
isFirstFetchAfterConnect: true,
|
||||||
|
|
||||||
alertMessageLimit: "",
|
alertMessageLimit: '',
|
||||||
alertTypeLimit: "info",
|
alertTypeLimit: 'info',
|
||||||
showAlertLimit: false,
|
showAlertLimit: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
};
|
};
|
||||||
@ -154,14 +179,14 @@ export default defineComponent({
|
|||||||
this.closeSocket();
|
this.closeSocket();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
isStringValue(value: ValueObject | StringValue) : value is StringValue {
|
isStringValue(value: ValueObject | StringValue): value is StringValue {
|
||||||
return value && typeof value === 'object' && 'translate' in value;
|
return value && typeof value === 'object' && 'translate' in value;
|
||||||
},
|
},
|
||||||
getInitialData() {
|
getInitialData() {
|
||||||
console.log("Get initalData for Battery");
|
console.log('Get initalData for Battery');
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
|
|
||||||
fetch("/api/batterylivedata/status", { headers: authHeader() })
|
fetch('/api/batterylivedata/status', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.batteryData = data;
|
this.batteryData = data;
|
||||||
@ -169,12 +194,11 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
initSocket() {
|
initSocket() {
|
||||||
console.log("Starting connection to Battery WebSocket Server");
|
console.log('Starting connection to Battery WebSocket Server');
|
||||||
|
|
||||||
const { protocol, host } = location;
|
const { protocol, host } = location;
|
||||||
const authString = authUrl();
|
const authString = authUrl();
|
||||||
const webSocketUrl = `${protocol === "https:" ? "wss" : "ws"
|
const webSocketUrl = `${protocol === 'https:' ? 'wss' : 'ws'}://${authString}${host}/batterylivedata`;
|
||||||
}://${authString}${host}/batterylivedata`;
|
|
||||||
|
|
||||||
this.socket = new WebSocket(webSocketUrl);
|
this.socket = new WebSocket(webSocketUrl);
|
||||||
|
|
||||||
@ -187,7 +211,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.socket.onopen = function (event) {
|
this.socket.onopen = function (event) {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
console.log("Successfully connected to the Battery websocket server...");
|
console.log('Successfully connected to the Battery websocket server...');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
||||||
@ -208,7 +232,7 @@ export default defineComponent({
|
|||||||
this.heartInterval = setInterval(() => {
|
this.heartInterval = setInterval(() => {
|
||||||
if (this.socket.readyState === 1) {
|
if (this.socket.readyState === 1) {
|
||||||
// Connection status
|
// Connection status
|
||||||
this.socket.send("ping");
|
this.socket.send('ping');
|
||||||
} else {
|
} else {
|
||||||
this.initSocket(); // Breakpoint reconnection 5 Time
|
this.initSocket(); // Breakpoint reconnection 5 Time
|
||||||
}
|
}
|
||||||
@ -219,11 +243,11 @@ export default defineComponent({
|
|||||||
this.socket.close();
|
this.socket.close();
|
||||||
this.heartInterval && clearTimeout(this.heartInterval);
|
this.heartInterval && clearTimeout(this.heartInterval);
|
||||||
this.isFirstFetchAfterConnect = true;
|
this.isFirstFetchAfterConnect = true;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
maxIssueValue() {
|
maxIssueValue() {
|
||||||
return ('issues' in this.batteryData)?Math.max(...Object.values(this.batteryData.issues)):0;
|
return 'issues' in this.batteryData ? Math.max(...Object.values(this.batteryData.issues)) : 0;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,7 +8,8 @@
|
|||||||
placeholder="http://admin:supersecret@mypowermeter.home/status"
|
placeholder="http://admin:supersecret@mypowermeter.home/status"
|
||||||
prefix="GET "
|
prefix="GET "
|
||||||
:tooltip="$t('httprequestsettings.urlDescription')"
|
:tooltip="$t('httprequestsettings.urlDescription')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="auth_type" class="col-sm-4 col-form-label">{{ $t('httprequestsettings.authorization') }}</label>
|
<label for="auth_type" class="col-sm-4 col-form-label">{{ $t('httprequestsettings.authorization') }}</label>
|
||||||
@ -27,7 +28,8 @@
|
|||||||
v-model="cfg.username"
|
v-model="cfg.username"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement
|
<InputElement
|
||||||
v-if="cfg.auth_type != 0"
|
v-if="cfg.auth_type != 0"
|
||||||
@ -35,7 +37,8 @@
|
|||||||
v-model="cfg.password"
|
v-model="cfg.password"
|
||||||
type="password"
|
type="password"
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement
|
<InputElement
|
||||||
:label="$t('httprequestsettings.headerKey')"
|
:label="$t('httprequestsettings.headerKey')"
|
||||||
@ -43,21 +46,24 @@
|
|||||||
type="text"
|
type="text"
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
:tooltip="$t('httprequestsettings.headerKeyDescription')"
|
:tooltip="$t('httprequestsettings.headerKeyDescription')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement
|
<InputElement
|
||||||
:label="$t('httprequestsettings.headerValue')"
|
:label="$t('httprequestsettings.headerValue')"
|
||||||
v-model="cfg.header_value"
|
v-model="cfg.header_value"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256"
|
maxlength="256"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement
|
<InputElement
|
||||||
:label="$t('httprequestsettings.timeout')"
|
:label="$t('httprequestsettings.timeout')"
|
||||||
v-model="cfg.timeout"
|
v-model="cfg.timeout"
|
||||||
type="number"
|
type="number"
|
||||||
:postfix="$t('httprequestsettings.milliSeconds')"
|
:postfix="$t('httprequestsettings.milliSeconds')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -67,28 +73,28 @@ import type { HttpRequestConfig } from '@/types/HttpRequestConfig';
|
|||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: { 'modelValue': Object as () => HttpRequestConfig },
|
props: { modelValue: Object as () => HttpRequestConfig },
|
||||||
computed: {
|
computed: {
|
||||||
cfg: {
|
cfg: {
|
||||||
get(): HttpRequestConfig {
|
get(): HttpRequestConfig {
|
||||||
return this.modelValue || {} as HttpRequestConfig;
|
return this.modelValue || ({} as HttpRequestConfig);
|
||||||
},
|
},
|
||||||
set(newValue: HttpRequestConfig): void {
|
set(newValue: HttpRequestConfig): void {
|
||||||
this.$emit('update:modelValue', newValue);
|
this.$emit('update:modelValue', newValue);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
InputElement
|
InputElement,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
authTypeList: [
|
authTypeList: [
|
||||||
{ key: 0, value: "None" },
|
{ key: 0, value: 'None' },
|
||||||
{ key: 1, value: "Basic" },
|
{ key: 1, value: 'Basic' },
|
||||||
{ key: 2, value: "Digest" },
|
{ key: 2, value: 'Digest' },
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -9,25 +9,32 @@
|
|||||||
<div class="row gy-3 mt-0">
|
<div class="row gy-3 mt-0">
|
||||||
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center" :class="{
|
<div
|
||||||
|
class="card-header d-flex justify-content-between align-items-center"
|
||||||
|
:class="{
|
||||||
'text-bg-danger': huaweiData.data_age > 20,
|
'text-bg-danger': huaweiData.data_age > 20,
|
||||||
'text-bg-primary': huaweiData.data_age < 19,
|
'text-bg-primary': huaweiData.data_age < 19,
|
||||||
}">
|
}"
|
||||||
|
>
|
||||||
<div class="p-1 flex-grow-1">
|
<div class="p-1 flex-grow-1">
|
||||||
<div class="d-flex flex-wrap">
|
<div class="d-flex flex-wrap">
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">Huawei R4850G2</div>
|
||||||
Huawei R4850G2
|
<div style="padding-right: 2em">
|
||||||
</div>
|
{{ $t('huawei.DataAge') }} {{ $t('huawei.Seconds', { val: huaweiData.data_age }) }}
|
||||||
<div style="padding-right: 2em;">
|
|
||||||
{{ $t('huawei.DataAge') }} {{ $t('huawei.Seconds', { 'val': huaweiData.data_age }) }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-toolbar p-2" role="toolbar">
|
<div class="btn-toolbar p-2" role="toolbar">
|
||||||
<div class="btn-group me-2" role="group">
|
<div class="btn-group me-2" role="group">
|
||||||
<button :disabled="false" type="button" class="btn btn-sm btn-danger" @click="onShowLimitSettings()"
|
<button
|
||||||
v-tooltip :title="$t('huawei.ShowSetLimit')">
|
:disabled="false"
|
||||||
<BIconSpeedometer style="font-size:24px;" />
|
type="button"
|
||||||
|
class="btn btn-sm btn-danger"
|
||||||
|
@click="onShowLimitSettings()"
|
||||||
|
v-tooltip
|
||||||
|
:title="$t('huawei.ShowSetLimit')"
|
||||||
|
>
|
||||||
|
<BIconSpeedometer style="font-size: 24px" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,34 +50,46 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ $t('huawei.Property') }}</th>
|
<th scope="col">{{ $t('huawei.Property') }}</th>
|
||||||
<th style="text-align: right" scope="col">{{ $t('huawei.Value') }}</th>
|
<th style="text-align: right" scope="col">
|
||||||
|
{{ $t('huawei.Value') }}
|
||||||
|
</th>
|
||||||
<th scope="col">{{ $t('huawei.Unit') }}</th>
|
<th scope="col">{{ $t('huawei.Unit') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.input_voltage') }}</th>
|
<th scope="row">{{ $t('huawei.input_voltage') }}</th>
|
||||||
<td style="text-align: right">{{ formatNumber(huaweiData.input_voltage.v) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ formatNumber(huaweiData.input_voltage.v) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.input_voltage.u }}</td>
|
<td>{{ huaweiData.input_voltage.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.input_current') }}</th>
|
<th scope="row">{{ $t('huawei.input_current') }}</th>
|
||||||
<td style="text-align: right">{{ formatNumber(huaweiData.input_current.v) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ formatNumber(huaweiData.input_current.v) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.input_current.u }}</td>
|
<td>{{ huaweiData.input_current.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.input_power') }}</th>
|
<th scope="row">{{ $t('huawei.input_power') }}</th>
|
||||||
<td style="text-align: right">{{ formatNumber(huaweiData.input_power.v) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ formatNumber(huaweiData.input_power.v) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.input_power.u }}</td>
|
<td>{{ huaweiData.input_power.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.input_temp') }}</th>
|
<th scope="row">{{ $t('huawei.input_temp') }}</th>
|
||||||
<td style="text-align: right">{{ Math.round(huaweiData.input_temp.v) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ Math.round(huaweiData.input_temp.v) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.input_temp.u }}</td>
|
<td>{{ huaweiData.input_temp.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.efficiency') }}</th>
|
<th scope="row">{{ $t('huawei.efficiency') }}</th>
|
||||||
<td style="text-align: right">{{ huaweiData.efficiency.v.toFixed(1) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ huaweiData.efficiency.v.toFixed(1) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.efficiency.u }}</td>
|
<td>{{ huaweiData.efficiency.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -86,34 +105,46 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ $t('huawei.Property') }}</th>
|
<th scope="col">{{ $t('huawei.Property') }}</th>
|
||||||
<th style="text-align: right" scope="col">{{ $t('huawei.Value') }}</th>
|
<th style="text-align: right" scope="col">
|
||||||
|
{{ $t('huawei.Value') }}
|
||||||
|
</th>
|
||||||
<th scope="col">{{ $t('huawei.Unit') }}</th>
|
<th scope="col">{{ $t('huawei.Unit') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.output_voltage') }}</th>
|
<th scope="row">{{ $t('huawei.output_voltage') }}</th>
|
||||||
<td style="text-align: right">{{ huaweiData.output_voltage.v.toFixed(1) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ huaweiData.output_voltage.v.toFixed(1) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.output_voltage.u }}</td>
|
<td>{{ huaweiData.output_voltage.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.output_current') }}</th>
|
<th scope="row">{{ $t('huawei.output_current') }}</th>
|
||||||
<td style="text-align: right">{{ huaweiData.output_current.v.toFixed(2) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ huaweiData.output_current.v.toFixed(2) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.output_current.u }}</td>
|
<td>{{ huaweiData.output_current.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.max_output_current') }}</th>
|
<th scope="row">{{ $t('huawei.max_output_current') }}</th>
|
||||||
<td style="text-align: right">{{ huaweiData.max_output_current.v.toFixed(1) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ huaweiData.max_output_current.v.toFixed(1) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.max_output_current.u }}</td>
|
<td>{{ huaweiData.max_output_current.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.output_power') }}</th>
|
<th scope="row">{{ $t('huawei.output_power') }}</th>
|
||||||
<td style="text-align: right">{{ huaweiData.output_power.v.toFixed(1) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ huaweiData.output_power.v.toFixed(1) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.output_power.u }}</td>
|
<td>{{ huaweiData.output_power.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{{ $t('huawei.output_temp') }}</th>
|
<th scope="row">{{ $t('huawei.output_temp') }}</th>
|
||||||
<td style="text-align: right">{{ Math.round(huaweiData.output_temp.v) }}</td>
|
<td style="text-align: right">
|
||||||
|
{{ Math.round(huaweiData.output_temp.v) }}
|
||||||
|
</td>
|
||||||
<td>{{ huaweiData.output_temp.u }}</td>
|
<td>{{ huaweiData.output_temp.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -136,64 +167,98 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inputCurrentLimit" class="col-sm-3 col-form-label">{{ $t('huawei.CurrentLimit') }} </label>
|
<label for="inputCurrentLimit" class="col-sm-3 col-form-label"
|
||||||
|
>{{ $t('huawei.CurrentLimit') }}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3 align-items-center">
|
<div class="row mb-3 align-items-center">
|
||||||
<label for="inputVoltageTargetLimit" class="col-sm-3 col-form-label">{{ $t('huawei.SetVoltageLimit')
|
<label for="inputVoltageTargetLimit" class="col-sm-3 col-form-label">{{
|
||||||
|
$t('huawei.SetVoltageLimit')
|
||||||
}}</label>
|
}}</label>
|
||||||
|
|
||||||
<div class="col-sm-1">
|
<div class="col-sm-1">
|
||||||
<div class="form-switch form-check-inline">
|
<div class="form-switch form-check-inline">
|
||||||
<input class="form-check-input" type="checkbox" id="flexSwitchVoltage"
|
<input
|
||||||
v-model="targetLimitList.voltage_valid">
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
id="flexSwitchVoltage"
|
||||||
|
v-model="targetLimitList.voltage_valid"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-7">
|
<div class="col-sm-7">
|
||||||
<input type="number" step="0.01" name="inputVoltageTargetLimit" class="form-control" id="inputVoltageTargetLimit"
|
<input
|
||||||
:min="targetVoltageLimitMin" :max="targetVoltageLimitMax" v-model="targetLimitList.voltage"
|
type="number"
|
||||||
:disabled=!targetLimitList.voltage_valid>
|
step="0.01"
|
||||||
|
name="inputVoltageTargetLimit"
|
||||||
|
class="form-control"
|
||||||
|
id="inputVoltageTargetLimit"
|
||||||
|
:min="targetVoltageLimitMin"
|
||||||
|
:max="targetVoltageLimitMax"
|
||||||
|
v-model="targetLimitList.voltage"
|
||||||
|
:disabled="!targetLimitList.voltage_valid"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div v-if="targetLimitList.voltage < targetVoltageLimitMinOffline" class="alert alert-secondary mt-3"
|
<div
|
||||||
role="alert" v-html="$t('huawei.LimitHint')"></div>
|
v-if="targetLimitList.voltage < targetVoltageLimitMinOffline"
|
||||||
|
class="alert alert-secondary mt-3"
|
||||||
|
role="alert"
|
||||||
|
v-html="$t('huawei.LimitHint')"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mb-3 align-items-center">
|
<div class="row mb-3 align-items-center">
|
||||||
<label for="inputCurrentTargetLimit" class="col-sm-3 col-form-label">{{ $t('huawei.SetCurrentLimit')
|
<label for="inputCurrentTargetLimit" class="col-sm-3 col-form-label">{{
|
||||||
|
$t('huawei.SetCurrentLimit')
|
||||||
}}</label>
|
}}</label>
|
||||||
|
|
||||||
<div class="col-sm-1">
|
<div class="col-sm-1">
|
||||||
<div class="form-switch form-check-inline">
|
<div class="form-switch form-check-inline">
|
||||||
<input class="form-check-input" type="checkbox" id="flexSwitchCurrentt"
|
<input
|
||||||
v-model="targetLimitList.current_valid">
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
id="flexSwitchCurrentt"
|
||||||
|
v-model="targetLimitList.current_valid"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-sm-7">
|
<div class="col-sm-7">
|
||||||
<input type="number" step="0.1" name="inputCurrentTargetLimit" class="form-control" id="inputCurrentTargetLimit"
|
<input
|
||||||
:min="targetCurrentLimitMin" :max="targetCurrentLimitMax" v-model="targetLimitList.current"
|
type="number"
|
||||||
:disabled=!targetLimitList.current_valid>
|
step="0.1"
|
||||||
|
name="inputCurrentTargetLimit"
|
||||||
|
class="form-control"
|
||||||
|
id="inputCurrentTargetLimit"
|
||||||
|
:min="targetCurrentLimitMin"
|
||||||
|
:max="targetCurrentLimitMax"
|
||||||
|
v-model="targetLimitList.current"
|
||||||
|
:disabled="!targetLimitList.current_valid"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-danger" @click="onSetLimitSettings(true)">{{ $t('huawei.SetOnline')
|
<button type="submit" class="btn btn-danger" @click="onSetLimitSettings(true)">
|
||||||
}}</button>
|
{{ $t('huawei.SetOnline') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-danger" @click="onSetLimitSettings(false)">{{
|
<button type="submit" class="btn btn-danger" @click="onSetLimitSettings(false)">
|
||||||
$t('huawei.SetOffline')
|
{{ $t('huawei.SetOffline') }}
|
||||||
}}</button>
|
</button>
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ $t('huawei.Close') }}</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||||
|
{{ $t('huawei.Close') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
@ -209,13 +274,11 @@ import type { HuaweiLimitConfig } from '@/types/HuaweiLimitConfig';
|
|||||||
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
||||||
|
|
||||||
import * as bootstrap from 'bootstrap';
|
import * as bootstrap from 'bootstrap';
|
||||||
import {
|
import { BIconSpeedometer } from 'bootstrap-icons-vue';
|
||||||
BIconSpeedometer,
|
|
||||||
} from 'bootstrap-icons-vue';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
BIconSpeedometer
|
BIconSpeedometer,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -234,8 +297,8 @@ export default defineComponent({
|
|||||||
targetLimitPersistent: false,
|
targetLimitPersistent: false,
|
||||||
huaweiLimitSettingView: {} as bootstrap.Modal,
|
huaweiLimitSettingView: {} as bootstrap.Modal,
|
||||||
|
|
||||||
alertMessageLimit: "",
|
alertMessageLimit: '',
|
||||||
alertTypeLimit: "info",
|
alertTypeLimit: 'info',
|
||||||
showAlertLimit: false,
|
showAlertLimit: false,
|
||||||
checked: false,
|
checked: false,
|
||||||
};
|
};
|
||||||
@ -250,10 +313,10 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getInitialData() {
|
getInitialData() {
|
||||||
console.log("Get initalData for Huawei");
|
console.log('Get initalData for Huawei');
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
|
|
||||||
fetch("/api/huaweilivedata/status", { headers: authHeader() })
|
fetch('/api/huaweilivedata/status', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.huaweiData = data;
|
this.huaweiData = data;
|
||||||
@ -261,12 +324,11 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
initSocket() {
|
initSocket() {
|
||||||
console.log("Starting connection to Huawei WebSocket Server");
|
console.log('Starting connection to Huawei WebSocket Server');
|
||||||
|
|
||||||
const { protocol, host } = location;
|
const { protocol, host } = location;
|
||||||
const authString = authUrl();
|
const authString = authUrl();
|
||||||
const webSocketUrl = `${protocol === "https:" ? "wss" : "ws"
|
const webSocketUrl = `${protocol === 'https:' ? 'wss' : 'ws'}://${authString}${host}/huaweilivedata`;
|
||||||
}://${authString}${host}/huaweilivedata`;
|
|
||||||
|
|
||||||
this.socket = new WebSocket(webSocketUrl);
|
this.socket = new WebSocket(webSocketUrl);
|
||||||
|
|
||||||
@ -279,7 +341,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.socket.onopen = function (event) {
|
this.socket.onopen = function (event) {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
console.log("Successfully connected to the Huawei websocket server...");
|
console.log('Successfully connected to the Huawei websocket server...');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
||||||
@ -300,7 +362,7 @@ export default defineComponent({
|
|||||||
this.heartInterval = setInterval(() => {
|
this.heartInterval = setInterval(() => {
|
||||||
if (this.socket.readyState === 1) {
|
if (this.socket.readyState === 1) {
|
||||||
// Connection status
|
// Connection status
|
||||||
this.socket.send("ping");
|
this.socket.send('ping');
|
||||||
} else {
|
} else {
|
||||||
this.initSocket(); // Breakpoint reconnection 5 Time
|
this.initSocket(); // Breakpoint reconnection 5 Time
|
||||||
}
|
}
|
||||||
@ -313,9 +375,7 @@ export default defineComponent({
|
|||||||
this.isFirstFetchAfterConnect = true;
|
this.isFirstFetchAfterConnect = true;
|
||||||
},
|
},
|
||||||
formatNumber(num: number) {
|
formatNumber(num: number) {
|
||||||
return new Intl.NumberFormat(
|
return new Intl.NumberFormat(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(num);
|
||||||
undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }
|
|
||||||
).format(num);
|
|
||||||
},
|
},
|
||||||
onHideLimitSettings() {
|
onHideLimitSettings() {
|
||||||
this.showAlertLimit = false;
|
this.showAlertLimit = false;
|
||||||
@ -331,27 +391,25 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.targetLimitList));
|
formData.append('data', JSON.stringify(this.targetLimitList));
|
||||||
|
|
||||||
console.log(this.targetLimitList);
|
console.log(this.targetLimitList);
|
||||||
|
|
||||||
fetch("/api/huawei/limit/config", {
|
fetch('/api/huawei/limit/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
if (response.type == 'success') {
|
||||||
if (response.type == "success") {
|
|
||||||
this.huaweiLimitSettingView.hide();
|
this.huaweiLimitSettingView.hide();
|
||||||
} else {
|
} else {
|
||||||
this.alertMessageLimit = this.$t('apiresponse.' + response.code, response.param);
|
this.alertMessageLimit = this.$t('apiresponse.' + response.code, response.param);
|
||||||
this.alertTypeLimit = response.type;
|
this.alertTypeLimit = response.type;
|
||||||
this.showAlertLimit = true;
|
this.showAlertLimit = true;
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,12 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row row-cols-1 row-cols-md-3 g-3">
|
<div class="row row-cols-1 row-cols-md-3 g-3">
|
||||||
<div class="col" v-if="totalVeData.enabled">
|
<div class="col" v-if="totalVeData.enabled">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.MpptTotalYieldTotal')">
|
<CardElement
|
||||||
|
centerContent
|
||||||
|
textVariant="text-bg-success"
|
||||||
|
:text="$t('invertertotalinfo.MpptTotalYieldTotal')"
|
||||||
|
>
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalVeData.total.YieldTotal.v, 'decimal', {
|
{{
|
||||||
|
$n(totalVeData.total.YieldTotal.v, 'decimal', {
|
||||||
minimumFractionDigits: totalVeData.total.YieldTotal.d,
|
minimumFractionDigits: totalVeData.total.YieldTotal.d,
|
||||||
maximumFractionDigits:totalVeData.total.YieldTotal.d
|
maximumFractionDigits: totalVeData.total.YieldTotal.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalVeData.total.YieldTotal.u }}</small>
|
<small class="text-muted">{{ totalVeData.total.YieldTotal.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
@ -14,10 +20,12 @@
|
|||||||
<div class="col" v-if="totalVeData.enabled">
|
<div class="col" v-if="totalVeData.enabled">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.MpptTotalYieldDay')">
|
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.MpptTotalYieldDay')">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalVeData.total.YieldDay.v, 'decimal', {
|
{{
|
||||||
|
$n(totalVeData.total.YieldDay.v, 'decimal', {
|
||||||
minimumFractionDigits: totalVeData.total.YieldDay.d,
|
minimumFractionDigits: totalVeData.total.YieldDay.d,
|
||||||
maximumFractionDigits: totalVeData.total.YieldDay.d
|
maximumFractionDigits: totalVeData.total.YieldDay.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalVeData.total.YieldDay.u }}</small>
|
<small class="text-muted">{{ totalVeData.total.YieldDay.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
@ -25,16 +33,22 @@
|
|||||||
<div class="col" v-if="totalVeData.enabled">
|
<div class="col" v-if="totalVeData.enabled">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.MpptTotalPower')">
|
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.MpptTotalPower')">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalVeData.total.Power.v, 'decimal', {
|
{{
|
||||||
|
$n(totalVeData.total.Power.v, 'decimal', {
|
||||||
minimumFractionDigits: totalVeData.total.Power.d,
|
minimumFractionDigits: totalVeData.total.Power.d,
|
||||||
maximumFractionDigits: totalVeData.total.Power.d
|
maximumFractionDigits: totalVeData.total.Power.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalVeData.total.Power.u }}</small>
|
<small class="text-muted">{{ totalVeData.total.Power.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.InverterTotalYieldTotal')">
|
<CardElement
|
||||||
|
centerContent
|
||||||
|
textVariant="text-bg-success"
|
||||||
|
:text="$t('invertertotalinfo.InverterTotalYieldTotal')"
|
||||||
|
>
|
||||||
<h2>
|
<h2>
|
||||||
{{
|
{{
|
||||||
$n(totalData.YieldTotal.v, 'decimal', {
|
$n(totalData.YieldTotal.v, 'decimal', {
|
||||||
@ -47,7 +61,11 @@
|
|||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.InverterTotalYieldDay')">
|
<CardElement
|
||||||
|
centerContent
|
||||||
|
textVariant="text-bg-success"
|
||||||
|
:text="$t('invertertotalinfo.InverterTotalYieldDay')"
|
||||||
|
>
|
||||||
<h2>
|
<h2>
|
||||||
{{
|
{{
|
||||||
$n(totalData.YieldDay.v, 'decimal', {
|
$n(totalData.YieldDay.v, 'decimal', {
|
||||||
@ -74,46 +92,64 @@
|
|||||||
</div>
|
</div>
|
||||||
<template v-if="totalBattData.enabled">
|
<template v-if="totalBattData.enabled">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<CardElement centerContent flexChildren textVariant="text-bg-success" :text="$t('invertertotalinfo.BatteryCharge')">
|
<CardElement
|
||||||
|
centerContent
|
||||||
|
flexChildren
|
||||||
|
textVariant="text-bg-success"
|
||||||
|
:text="$t('invertertotalinfo.BatteryCharge')"
|
||||||
|
>
|
||||||
<div class="flex-fill" v-if="totalBattData.soc">
|
<div class="flex-fill" v-if="totalBattData.soc">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalBattData.soc.v, 'decimal', {
|
{{
|
||||||
|
$n(totalBattData.soc.v, 'decimal', {
|
||||||
minimumFractionDigits: totalBattData.soc.d,
|
minimumFractionDigits: totalBattData.soc.d,
|
||||||
maximumFractionDigits: totalBattData.soc.d
|
maximumFractionDigits: totalBattData.soc.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalBattData.soc.u }}</small>
|
<small class="text-muted">{{ totalBattData.soc.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-fill" v-if="totalBattData.voltage">
|
<div class="flex-fill" v-if="totalBattData.voltage">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalBattData.voltage.v, 'decimal', {
|
{{
|
||||||
|
$n(totalBattData.voltage.v, 'decimal', {
|
||||||
minimumFractionDigits: totalBattData.voltage.d,
|
minimumFractionDigits: totalBattData.voltage.d,
|
||||||
maximumFractionDigits: totalBattData.voltage.d
|
maximumFractionDigits: totalBattData.voltage.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalBattData.voltage.u }}</small>
|
<small class="text-muted">{{ totalBattData.voltage.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
<div class="col" v-if="totalBattData.power || totalBattData.current">
|
<div class="col" v-if="totalBattData.power || totalBattData.current">
|
||||||
<CardElement centerContent flexChildren textVariant="text-bg-success" :text="$t('invertertotalinfo.BatteryPower')">
|
<CardElement
|
||||||
|
centerContent
|
||||||
|
flexChildren
|
||||||
|
textVariant="text-bg-success"
|
||||||
|
:text="$t('invertertotalinfo.BatteryPower')"
|
||||||
|
>
|
||||||
<div class="flex-fill" v-if="totalBattData.power">
|
<div class="flex-fill" v-if="totalBattData.power">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalBattData.power.v, 'decimal', {
|
{{
|
||||||
|
$n(totalBattData.power.v, 'decimal', {
|
||||||
minimumFractionDigits: totalBattData.power.d,
|
minimumFractionDigits: totalBattData.power.d,
|
||||||
maximumFractionDigits: totalBattData.power.d
|
maximumFractionDigits: totalBattData.power.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalBattData.power.u }}</small>
|
<small class="text-muted">{{ totalBattData.power.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex-fill" v-if="totalBattData.current">
|
<div class="flex-fill" v-if="totalBattData.current">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(totalBattData.current.v, 'decimal', {
|
{{
|
||||||
|
$n(totalBattData.current.v, 'decimal', {
|
||||||
minimumFractionDigits: totalBattData.current.d,
|
minimumFractionDigits: totalBattData.current.d,
|
||||||
maximumFractionDigits: totalBattData.current.d
|
maximumFractionDigits: totalBattData.current.d,
|
||||||
}) }}
|
})
|
||||||
|
}}
|
||||||
<small class="text-muted">{{ totalBattData.current.u }}</small>
|
<small class="text-muted">{{ totalBattData.current.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@ -123,22 +159,26 @@
|
|||||||
<div class="col" v-if="powerMeterData.enabled">
|
<div class="col" v-if="powerMeterData.enabled">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.HomePower')">
|
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.HomePower')">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(powerMeterData.Power.v, 'decimal', {
|
{{
|
||||||
|
$n(powerMeterData.Power.v, 'decimal', {
|
||||||
minimumFractionDigits: powerMeterData.Power.d,
|
minimumFractionDigits: powerMeterData.Power.d,
|
||||||
maximumFractionDigits: powerMeterData.Power.d
|
maximumFractionDigits: powerMeterData.Power.d,
|
||||||
}) }}
|
})
|
||||||
<small class="text-muted">{{powerMeterData.Power.u }}</small>
|
}}
|
||||||
|
<small class="text-muted">{{ powerMeterData.Power.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
<div class="col" v-if="huaweiData.enabled">
|
<div class="col" v-if="huaweiData.enabled">
|
||||||
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.HuaweiPower')">
|
<CardElement centerContent textVariant="text-bg-success" :text="$t('invertertotalinfo.HuaweiPower')">
|
||||||
<h2>
|
<h2>
|
||||||
{{ $n(huaweiData.Power.v, 'decimal', {
|
{{
|
||||||
|
$n(huaweiData.Power.v, 'decimal', {
|
||||||
minimumFractionDigits: huaweiData.Power.d,
|
minimumFractionDigits: huaweiData.Power.d,
|
||||||
maximumFractionDigits: huaweiData.Power.d
|
maximumFractionDigits: huaweiData.Power.d,
|
||||||
}) }}
|
})
|
||||||
<small class="text-muted">{{huaweiData.Power.u }}</small>
|
}}
|
||||||
|
<small class="text-muted">{{ huaweiData.Power.u }}</small>
|
||||||
</h2>
|
</h2>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,7 +9,9 @@
|
|||||||
<BIconSun v-else width="30" height="30" class="d-inline-block align-text-top text-warning" />
|
<BIconSun v-else width="30" height="30" class="d-inline-block align-text-top text-warning" />
|
||||||
|
|
||||||
<span style="margin-left: 0.5rem"> OpenDTU-OnBattery </span>
|
<span style="margin-left: 0.5rem"> OpenDTU-OnBattery </span>
|
||||||
<span class="text-info mx-2"><BIconBatteryCharging width="20" height="20" class="d-inline-block align-text-center" /></span>
|
<span class="text-info mx-2"
|
||||||
|
><BIconBatteryCharging width="20" height="20" class="d-inline-block align-text-center"
|
||||||
|
/></span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<button
|
<button
|
||||||
class="navbar-toggler"
|
class="navbar-toggler"
|
||||||
@ -70,19 +72,29 @@
|
|||||||
}}</router-link>
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/vedirect">{{ $t('menu.VedirectSettings') }}</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/settings/vedirect">{{
|
||||||
|
$t('menu.VedirectSettings')
|
||||||
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/powermeter">{{ $t('menu.PowerMeterSettings') }}</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/settings/powermeter">{{
|
||||||
|
$t('menu.PowerMeterSettings')
|
||||||
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/powerlimiter">Dynamic Power Limiter</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/settings/powerlimiter"
|
||||||
|
>Dynamic Power Limiter</router-link
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/battery">{{ $t('menu.BatterySettings') }}</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/settings/battery">{{
|
||||||
|
$t('menu.BatterySettings')
|
||||||
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/chargerac">{{ $t('menu.AcChargerSettings') }}</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/settings/chargerac">{{
|
||||||
|
$t('menu.AcChargerSettings')
|
||||||
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/settings/device">{{
|
<router-link @click="onClick" class="dropdown-item" to="/settings/device">{{
|
||||||
@ -142,7 +154,9 @@
|
|||||||
}}</router-link>
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link @click="onClick" class="dropdown-item" to="/info/vedirect">{{ $t('menu.Vedirect') }}</router-link>
|
<router-link @click="onClick" class="dropdown-item" to="/info/vedirect">{{
|
||||||
|
$t('menu.Vedirect')
|
||||||
|
}}</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<hr class="dropdown-divider" />
|
<hr class="dropdown-divider" />
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="text-center" v-if="dataLoading">
|
<div class="text-center" v-if="dataLoading">
|
||||||
<div class="spinner-border" role="status">
|
<div class="spinner-border" role="status">
|
||||||
<span class="visually-hidden">Loading...</span>
|
<span class="visually-hidden">Loading...</span>
|
||||||
@ -10,44 +9,53 @@
|
|||||||
<div class="row gy-3 mt-0" v-for="(item, serial) in vedirect.instances" :key="serial">
|
<div class="row gy-3 mt-0" v-for="(item, serial) in vedirect.instances" :key="serial">
|
||||||
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
<div class="tab-content col-sm-12 col-md-12" id="v-pills-tabContent">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center"
|
<div
|
||||||
|
class="card-header d-flex justify-content-between align-items-center"
|
||||||
:class="{
|
:class="{
|
||||||
'text-bg-danger': item.data_age_ms >= 10000,
|
'text-bg-danger': item.data_age_ms >= 10000,
|
||||||
'text-bg-primary': item.data_age_ms < 10000,
|
'text-bg-primary': item.data_age_ms < 10000,
|
||||||
}">
|
}"
|
||||||
|
>
|
||||||
<div class="p-1 flex-grow-1">
|
<div class="p-1 flex-grow-1">
|
||||||
<div class="d-flex flex-wrap">
|
<div class="d-flex flex-wrap">
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ item.product_id }}
|
{{ item.product_id }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ $t('vedirecthome.SerialNumber') }}: {{ serial }}
|
{{ $t('vedirecthome.SerialNumber') }}: {{ serial }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ $t('vedirecthome.FirmwareVersion') }}: {{ item.firmware_version }}
|
{{ $t('vedirecthome.FirmwareVersion') }}: {{ item.firmware_version }}
|
||||||
</div>
|
</div>
|
||||||
<div style="padding-right: 2em;">
|
<div style="padding-right: 2em">
|
||||||
{{ $t('vedirecthome.DataAge') }}: {{ $t('vedirecthome.Seconds', {'val': Math.floor(item.data_age_ms / 1000)}) }}
|
{{ $t('vedirecthome.DataAge') }}:
|
||||||
|
{{ $t('vedirecthome.Seconds', { val: Math.floor(item.data_age_ms / 1000) }) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group me-2" role="group">
|
<div class="btn-group me-2" role="group">
|
||||||
<button type="button"
|
<button
|
||||||
class="btn btn-sm" v-tooltip :title="$t('vedirecthome.PowerLimiterState')">
|
type="button"
|
||||||
|
class="btn btn-sm"
|
||||||
|
v-tooltip
|
||||||
|
:title="$t('vedirecthome.PowerLimiterState')"
|
||||||
|
>
|
||||||
<div v-if="dplData.PLSTATE == 0">
|
<div v-if="dplData.PLSTATE == 0">
|
||||||
<BIconXCircleFill style="font-size:24px;" />
|
<BIconXCircleFill style="font-size: 24px" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="dplData.PLSTATE == 1">
|
<div v-else-if="dplData.PLSTATE == 1">
|
||||||
<BIconBatteryCharging style="font-size:24px;" />
|
<BIconBatteryCharging style="font-size: 24px" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="dplData.PLSTATE == 2">
|
<div v-else-if="dplData.PLSTATE == 2">
|
||||||
<BIconSun style="font-size:24px;" />
|
<BIconSun style="font-size: 24px" />
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="dplData.PLSTATE == 3">
|
<div v-else-if="dplData.PLSTATE == 3">
|
||||||
<BIconBatteryHalf style="font-size:24px;" />
|
<BIconBatteryHalf style="font-size: 24px" />
|
||||||
</div>
|
</div>
|
||||||
<span v-if="dplData.PLSTATE != -1"
|
<span
|
||||||
class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-info">
|
v-if="dplData.PLSTATE != -1"
|
||||||
|
class="position-absolute top-0 start-100 translate-middle badge rounded-pill text-bg-info"
|
||||||
|
>
|
||||||
{{ dplData.PLLIMIT }} W
|
{{ dplData.PLLIMIT }} W
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@ -56,34 +64,42 @@
|
|||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row flex-row flex-wrap align-items-start g-3">
|
<div class="row flex-row flex-wrap align-items-start g-3">
|
||||||
<div v-for="(values, section) in item.values" v-bind:key="section" class="col order-0">
|
<div v-for="(values, section) in item.values" v-bind:key="section" class="col order-0">
|
||||||
<div class="card" :class="{ 'border-info': (section === 'device') }">
|
<div class="card" :class="{ 'border-info': section === 'device' }">
|
||||||
<div :class="(section === 'device')?'card-header text-bg-info':'card-header'">{{ $t('vedirecthome.section_' + section) }}</div>
|
<div :class="section === 'device' ? 'card-header text-bg-info' : 'card-header'">
|
||||||
|
{{ $t('vedirecthome.section_' + section) }}
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-striped table-hover">
|
<table class="table table-striped table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{{ $t('vedirecthome.Property') }}</th>
|
<th scope="col">{{ $t('vedirecthome.Property') }}</th>
|
||||||
<th style="text-align: right" scope="col">{{ $t('vedirecthome.Value') }}</th>
|
<th style="text-align: right" scope="col">
|
||||||
|
{{ $t('vedirecthome.Value') }}
|
||||||
|
</th>
|
||||||
<th scope="col">{{ $t('vedirecthome.Unit') }}</th>
|
<th scope="col">{{ $t('vedirecthome.Unit') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(prop, key) in values" v-bind:key="key">
|
<tr v-for="(prop, key) in values" v-bind:key="key">
|
||||||
<th scope="row">{{ $t('vedirecthome.' + section + '.' + key) }}</th>
|
<th scope="row">
|
||||||
|
{{ $t('vedirecthome.' + section + '.' + key) }}
|
||||||
|
</th>
|
||||||
<td style="text-align: right">
|
<td style="text-align: right">
|
||||||
<template v-if="typeof prop === 'string'">
|
<template v-if="typeof prop === 'string'">
|
||||||
{{ prop }}
|
{{ prop }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ $n(prop.v, 'decimal', {
|
{{
|
||||||
|
$n(prop.v, 'decimal', {
|
||||||
minimumFractionDigits: prop.d,
|
minimumFractionDigits: prop.d,
|
||||||
maximumFractionDigits: prop.d})
|
maximumFractionDigits: prop.d,
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="typeof prop === 'string'"></td>
|
<td v-if="typeof prop === 'string'"></td>
|
||||||
<td v-else>{{prop.u}}</td>
|
<td v-else>{{ prop.u }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -97,29 +113,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { DynamicPowerLimiter, Vedirect } from '@/types/VedirectLiveDataStatus';
|
import type { DynamicPowerLimiter, Vedirect } from '@/types/VedirectLiveDataStatus';
|
||||||
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
import { handleResponse, authHeader, authUrl } from '@/utils/authentication';
|
||||||
import {
|
import { BIconSun, BIconBatteryCharging, BIconBatteryHalf, BIconXCircleFill } from 'bootstrap-icons-vue';
|
||||||
BIconSun,
|
|
||||||
BIconBatteryCharging,
|
|
||||||
BIconBatteryHalf,
|
|
||||||
BIconXCircleFill
|
|
||||||
} from 'bootstrap-icons-vue';
|
|
||||||
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
BIconSun,
|
BIconSun,
|
||||||
BIconBatteryCharging,
|
BIconBatteryCharging,
|
||||||
BIconBatteryHalf,
|
BIconBatteryHalf,
|
||||||
BIconXCircleFill
|
BIconXCircleFill,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -141,44 +148,43 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getInitialData() {
|
getInitialData() {
|
||||||
console.log("Get initalData for VeDirect");
|
console.log('Get initalData for VeDirect');
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/vedirectlivedata/status", { headers: authHeader() })
|
fetch('/api/vedirectlivedata/status', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((root) => {
|
.then((root) => {
|
||||||
this.dplData = root["dpl"];
|
this.dplData = root['dpl'];
|
||||||
this.vedirect = root["vedirect"];
|
this.vedirect = root['vedirect'];
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
this.resetDataAging(Object.keys(root["vedirect"]["instances"]));
|
this.resetDataAging(Object.keys(root['vedirect']['instances']));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
initSocket() {
|
initSocket() {
|
||||||
console.log("Starting connection to VeDirect WebSocket Server");
|
console.log('Starting connection to VeDirect WebSocket Server');
|
||||||
|
|
||||||
const { protocol, host } = location;
|
const { protocol, host } = location;
|
||||||
const authString = authUrl();
|
const authString = authUrl();
|
||||||
const webSocketUrl = `${protocol === "https:" ? "wss" : "ws"
|
const webSocketUrl = `${protocol === 'https:' ? 'wss' : 'ws'}://${authString}${host}/vedirectlivedata`;
|
||||||
}://${authString}${host}/vedirectlivedata`;
|
|
||||||
|
|
||||||
this.socket = new WebSocket(webSocketUrl);
|
this.socket = new WebSocket(webSocketUrl);
|
||||||
|
|
||||||
this.socket.onmessage = (event) => {
|
this.socket.onmessage = (event) => {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
const root = JSON.parse(event.data);
|
const root = JSON.parse(event.data);
|
||||||
this.dplData = root["dpl"];
|
this.dplData = root['dpl'];
|
||||||
if (root["vedirect"]["full_update"] === true) {
|
if (root['vedirect']['full_update'] === true) {
|
||||||
this.vedirect = root["vedirect"];
|
this.vedirect = root['vedirect'];
|
||||||
} else {
|
} else {
|
||||||
Object.assign(this.vedirect.instances, root["vedirect"]["instances"]);
|
Object.assign(this.vedirect.instances, root['vedirect']['instances']);
|
||||||
}
|
}
|
||||||
this.resetDataAging(Object.keys(root["vedirect"]["instances"]));
|
this.resetDataAging(Object.keys(root['vedirect']['instances']));
|
||||||
this.dataLoading = false;
|
this.dataLoading = false;
|
||||||
this.heartCheck(); // Reset heartbeat detection
|
this.heartCheck(); // Reset heartbeat detection
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.onopen = function (event) {
|
this.socket.onopen = function (event) {
|
||||||
console.log(event);
|
console.log(event);
|
||||||
console.log("Successfully connected to the VeDirect websocket server...");
|
console.log('Successfully connected to the VeDirect websocket server...');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
// Listen to window events , When the window closes , Take the initiative to disconnect websocket Connect
|
||||||
@ -199,7 +205,9 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
doDataAging(serial: string) {
|
doDataAging(serial: string) {
|
||||||
if (this.vedirect?.instances?.[serial] === undefined) { return; }
|
if (this.vedirect?.instances?.[serial] === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.vedirect.instances[serial].data_age_ms += 1000;
|
this.vedirect.instances[serial].data_age_ms += 1000;
|
||||||
|
|
||||||
@ -213,7 +221,7 @@ export default defineComponent({
|
|||||||
this.heartInterval = setInterval(() => {
|
this.heartInterval = setInterval(() => {
|
||||||
if (this.socket.readyState === 1) {
|
if (this.socket.readyState === 1) {
|
||||||
// Connection status
|
// Connection status
|
||||||
this.socket.send("ping");
|
this.socket.send('ping');
|
||||||
} else {
|
} else {
|
||||||
this.initSocket(); // Breakpoint reconnection 5 Time
|
this.initSocket(); // Breakpoint reconnection 5 Time
|
||||||
}
|
}
|
||||||
|
|||||||
@ -366,7 +366,7 @@
|
|||||||
"Disconnected": "getrennt"
|
"Disconnected": "getrennt"
|
||||||
},
|
},
|
||||||
"vedirectinfo": {
|
"vedirectinfo": {
|
||||||
"VedirectInformation" : "VE.Direct Info",
|
"VedirectInformation": "VE.Direct Info",
|
||||||
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
||||||
"Status": "@:ntpinfo.Status",
|
"Status": "@:ntpinfo.Status",
|
||||||
"Enabled": "@:mqttinfo.Enabled",
|
"Enabled": "@:mqttinfo.Enabled",
|
||||||
@ -553,7 +553,7 @@
|
|||||||
"VerboseLogging": "@:base.VerboseLogging",
|
"VerboseLogging": "@:base.VerboseLogging",
|
||||||
"UpdatesOnly": "Werte nur bei Änderung an MQTT broker senden"
|
"UpdatesOnly": "Werte nur bei Änderung an MQTT broker senden"
|
||||||
},
|
},
|
||||||
"powermeteradmin":{
|
"powermeteradmin": {
|
||||||
"PowerMeterSettings": "Stromzähler Einstellungen",
|
"PowerMeterSettings": "Stromzähler Einstellungen",
|
||||||
"PowerMeterConfiguration": "Stromzähler Konfiguration",
|
"PowerMeterConfiguration": "Stromzähler Konfiguration",
|
||||||
"PowerMeterEnable": "Aktiviere Stromzähler",
|
"PowerMeterEnable": "Aktiviere Stromzähler",
|
||||||
|
|||||||
@ -368,7 +368,7 @@
|
|||||||
"Disconnected": "disconnected"
|
"Disconnected": "disconnected"
|
||||||
},
|
},
|
||||||
"vedirectinfo": {
|
"vedirectinfo": {
|
||||||
"VedirectInformation" : "VE.Direct Info",
|
"VedirectInformation": "VE.Direct Info",
|
||||||
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
||||||
"Status": "@:ntpinfo.Status",
|
"Status": "@:ntpinfo.Status",
|
||||||
"Enabled": "@:mqttinfo.Enabled",
|
"Enabled": "@:mqttinfo.Enabled",
|
||||||
@ -555,7 +555,7 @@
|
|||||||
"VerboseLogging": "@:base.VerboseLogging",
|
"VerboseLogging": "@:base.VerboseLogging",
|
||||||
"UpdatesOnly": "Publish values to MQTT only when they change"
|
"UpdatesOnly": "Publish values to MQTT only when they change"
|
||||||
},
|
},
|
||||||
"powermeteradmin":{
|
"powermeteradmin": {
|
||||||
"PowerMeterSettings": "Power Meter Settings",
|
"PowerMeterSettings": "Power Meter Settings",
|
||||||
"PowerMeterConfiguration": "Power Meter Configuration",
|
"PowerMeterConfiguration": "Power Meter Configuration",
|
||||||
"PowerMeterEnable": "Enable Power Meter",
|
"PowerMeterEnable": "Enable Power Meter",
|
||||||
|
|||||||
@ -401,7 +401,7 @@
|
|||||||
"Disconnected": "déconnecté"
|
"Disconnected": "déconnecté"
|
||||||
},
|
},
|
||||||
"vedirectinfo": {
|
"vedirectinfo": {
|
||||||
"VedirectInformation" : "VE.Direct Info",
|
"VedirectInformation": "VE.Direct Info",
|
||||||
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
"ConfigurationSummary": "@:ntpinfo.ConfigurationSummary",
|
||||||
"Status": "@:ntpinfo.Status",
|
"Status": "@:ntpinfo.Status",
|
||||||
"Enabled": "@:mqttinfo.Enabled",
|
"Enabled": "@:mqttinfo.Enabled",
|
||||||
|
|||||||
@ -8,10 +8,10 @@ import DtuAdminView from '@/views/DtuAdminView.vue';
|
|||||||
import ErrorView from '@/views/ErrorView.vue';
|
import ErrorView from '@/views/ErrorView.vue';
|
||||||
import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue';
|
import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue';
|
||||||
import HomeView from '@/views/HomeView.vue';
|
import HomeView from '@/views/HomeView.vue';
|
||||||
import VedirectAdminView from '@/views/VedirectAdminView.vue'
|
import VedirectAdminView from '@/views/VedirectAdminView.vue';
|
||||||
import PowerMeterAdminView from '@/views/PowerMeterAdminView.vue'
|
import PowerMeterAdminView from '@/views/PowerMeterAdminView.vue';
|
||||||
import PowerLimiterAdminView from '@/views/PowerLimiterAdminView.vue'
|
import PowerLimiterAdminView from '@/views/PowerLimiterAdminView.vue';
|
||||||
import VedirectInfoView from '@/views/VedirectInfoView.vue'
|
import VedirectInfoView from '@/views/VedirectInfoView.vue';
|
||||||
import InverterAdminView from '@/views/InverterAdminView.vue';
|
import InverterAdminView from '@/views/InverterAdminView.vue';
|
||||||
import LoginView from '@/views/LoginView.vue';
|
import LoginView from '@/views/LoginView.vue';
|
||||||
import MaintenanceRebootView from '@/views/MaintenanceRebootView.vue';
|
import MaintenanceRebootView from '@/views/MaintenanceRebootView.vue';
|
||||||
@ -77,7 +77,7 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/info/vedirect',
|
path: '/info/vedirect',
|
||||||
name: 'VE.Direct',
|
name: 'VE.Direct',
|
||||||
component: VedirectInfoView
|
component: VedirectInfoView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/network',
|
path: '/settings/network',
|
||||||
@ -92,27 +92,27 @@ const router = createRouter({
|
|||||||
{
|
{
|
||||||
path: '/settings/vedirect',
|
path: '/settings/vedirect',
|
||||||
name: 'VE.Direct Settings',
|
name: 'VE.Direct Settings',
|
||||||
component: VedirectAdminView
|
component: VedirectAdminView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/powermeter',
|
path: '/settings/powermeter',
|
||||||
name: 'Power meter Settings',
|
name: 'Power meter Settings',
|
||||||
component: PowerMeterAdminView
|
component: PowerMeterAdminView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/powerlimiter',
|
path: '/settings/powerlimiter',
|
||||||
name: 'Power limiter Settings',
|
name: 'Power limiter Settings',
|
||||||
component: PowerLimiterAdminView
|
component: PowerLimiterAdminView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/battery',
|
path: '/settings/battery',
|
||||||
name: 'Battery Settings',
|
name: 'Battery Settings',
|
||||||
component: BatteryAdminView
|
component: BatteryAdminView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/chargerac',
|
path: '/settings/chargerac',
|
||||||
name: 'Charger Settings',
|
name: 'Charger Settings',
|
||||||
component: AcChargerAdminView
|
component: AcChargerAdminView,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/settings/mqtt',
|
path: '/settings/mqtt',
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export interface PowerMeterMqttConfig {
|
|||||||
export interface PowerMeterSerialSdmConfig {
|
export interface PowerMeterSerialSdmConfig {
|
||||||
polling_interval: number;
|
polling_interval: number;
|
||||||
address: number;
|
address: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface PowerMeterHttpJsonValue {
|
export interface PowerMeterHttpJsonValue {
|
||||||
http_request: HttpRequestConfig;
|
http_request: HttpRequestConfig;
|
||||||
|
|||||||
@ -6,9 +6,12 @@
|
|||||||
|
|
||||||
<form @submit="saveChargerConfig">
|
<form @submit="saveChargerConfig">
|
||||||
<CardElement :text="$t('acchargeradmin.Configuration')" textVariant="text-bg-primary">
|
<CardElement :text="$t('acchargeradmin.Configuration')" textVariant="text-bg-primary">
|
||||||
<InputElement :label="$t('acchargeradmin.EnableHuawei')"
|
<InputElement
|
||||||
|
:label="$t('acchargeradmin.EnableHuawei')"
|
||||||
v-model="acChargerConfigList.enabled"
|
v-model="acChargerConfigList.enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-show="acChargerConfigList.enabled">
|
<div class="row mb-3" v-show="acChargerConfigList.enabled">
|
||||||
<label class="col-sm-4 col-form-label">
|
<label class="col-sm-4 col-form-label">
|
||||||
@ -16,103 +19,186 @@
|
|||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select class="form-select" v-model="acChargerConfigList.can_controller_frequency">
|
<select class="form-select" v-model="acChargerConfigList.can_controller_frequency">
|
||||||
<option v-for="frequency in frequencyTypeList" :key="frequency.key" :value="frequency.value">
|
<option
|
||||||
|
v-for="frequency in frequencyTypeList"
|
||||||
|
:key="frequency.key"
|
||||||
|
:value="frequency.value"
|
||||||
|
>
|
||||||
{{ frequency.key }} MHz
|
{{ frequency.key }} MHz
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InputElement v-show="acChargerConfigList.enabled"
|
<InputElement
|
||||||
|
v-show="acChargerConfigList.enabled"
|
||||||
:label="$t('acchargeradmin.VerboseLogging')"
|
:label="$t('acchargeradmin.VerboseLogging')"
|
||||||
v-model="acChargerConfigList.verbose_logging"
|
v-model="acChargerConfigList.verbose_logging"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="acChargerConfigList.enabled"
|
<InputElement
|
||||||
|
v-show="acChargerConfigList.enabled"
|
||||||
:label="$t('acchargeradmin.EnableAutoPower')"
|
:label="$t('acchargeradmin.EnableAutoPower')"
|
||||||
v-model="acChargerConfigList.auto_power_enabled"
|
v-model="acChargerConfigList.auto_power_enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="acChargerConfigList.enabled && acChargerConfigList.auto_power_enabled"
|
<InputElement
|
||||||
|
v-show="acChargerConfigList.enabled && acChargerConfigList.auto_power_enabled"
|
||||||
:label="$t('acchargeradmin.EnableBatterySoCLimits')"
|
:label="$t('acchargeradmin.EnableBatterySoCLimits')"
|
||||||
v-model="acChargerConfigList.auto_power_batterysoc_limits_enabled"
|
v-model="acChargerConfigList.auto_power_batterysoc_limits_enabled"
|
||||||
type="checkbox" wide />
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="acChargerConfigList.enabled"
|
<InputElement
|
||||||
|
v-show="acChargerConfigList.enabled"
|
||||||
:label="$t('acchargeradmin.EnableEmergencyCharge')"
|
:label="$t('acchargeradmin.EnableEmergencyCharge')"
|
||||||
v-model="acChargerConfigList.emergency_charge_enabled"
|
v-model="acChargerConfigList.emergency_charge_enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<CardElement :text="$t('acchargeradmin.Limits')" textVariant="text-bg-primary" add-space
|
<CardElement
|
||||||
v-show="acChargerConfigList.auto_power_enabled || acChargerConfigList.emergency_charge_enabled">
|
:text="$t('acchargeradmin.Limits')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-show="acChargerConfigList.auto_power_enabled || acChargerConfigList.emergency_charge_enabled"
|
||||||
|
>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="voltageLimit" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.VoltageLimit') }}:
|
<label for="voltageLimit" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.VoltageLimit') }}:
|
||||||
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.stopVoltageLimitHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.stopVoltageLimitHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" step="0.01" class="form-control" id="voltageLimit"
|
<input
|
||||||
placeholder="42" v-model="acChargerConfigList.voltage_limit"
|
type="number"
|
||||||
aria-describedby="voltageLimitDescription" min="42" max="58.5" required/>
|
step="0.01"
|
||||||
|
class="form-control"
|
||||||
|
id="voltageLimit"
|
||||||
|
placeholder="42"
|
||||||
|
v-model="acChargerConfigList.voltage_limit"
|
||||||
|
aria-describedby="voltageLimitDescription"
|
||||||
|
min="42"
|
||||||
|
max="58.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="voltageLimitDescription">V</span>
|
<span class="input-group-text" id="voltageLimitDescription">V</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label for="enableVoltageLimit" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.enableVoltageLimit') }}:
|
<label for="enableVoltageLimit" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.enableVoltageLimit') }}:
|
||||||
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.enableVoltageLimitHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.enableVoltageLimitHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" step="0.01" class="form-control" id="enableVoltageLimit"
|
<input
|
||||||
placeholder="42" v-model="acChargerConfigList.enable_voltage_limit"
|
type="number"
|
||||||
aria-describedby="enableVoltageLimitDescription" min="42" max="58.5" required/>
|
step="0.01"
|
||||||
|
class="form-control"
|
||||||
|
id="enableVoltageLimit"
|
||||||
|
placeholder="42"
|
||||||
|
v-model="acChargerConfigList.enable_voltage_limit"
|
||||||
|
aria-describedby="enableVoltageLimitDescription"
|
||||||
|
min="42"
|
||||||
|
max="58.5"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="enableVoltageLimitDescription">V</span>
|
<span class="input-group-text" id="enableVoltageLimitDescription">V</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label for="lowerPowerLimit" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.lowerPowerLimit') }}:</label>
|
<label for="lowerPowerLimit" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.lowerPowerLimit') }}:</label
|
||||||
|
>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="lowerPowerLimit"
|
<input
|
||||||
placeholder="150" v-model="acChargerConfigList.lower_power_limit"
|
type="number"
|
||||||
aria-describedby="lowerPowerLimitDescription" min="50" max="3000" required/>
|
class="form-control"
|
||||||
|
id="lowerPowerLimit"
|
||||||
|
placeholder="150"
|
||||||
|
v-model="acChargerConfigList.lower_power_limit"
|
||||||
|
aria-describedby="lowerPowerLimitDescription"
|
||||||
|
min="50"
|
||||||
|
max="3000"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="lowerPowerLimitDescription">W</span>
|
<span class="input-group-text" id="lowerPowerLimitDescription">W</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label for="upperPowerLimit" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.upperPowerLimit') }}:
|
<label for="upperPowerLimit" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.upperPowerLimit') }}:
|
||||||
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.upperPowerLimitHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.upperPowerLimitHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="upperPowerLimit"
|
<input
|
||||||
placeholder="2000" v-model="acChargerConfigList.upper_power_limit"
|
type="number"
|
||||||
aria-describedby="upperPowerLimitDescription" min="100" max="3000" required/>
|
class="form-control"
|
||||||
|
id="upperPowerLimit"
|
||||||
|
placeholder="2000"
|
||||||
|
v-model="acChargerConfigList.upper_power_limit"
|
||||||
|
aria-describedby="upperPowerLimitDescription"
|
||||||
|
min="100"
|
||||||
|
max="3000"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="upperPowerLimitDescription">W</span>
|
<span class="input-group-text" id="upperPowerLimitDescription">W</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<label for="targetPowerConsumption" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.targetPowerConsumption') }}:
|
<label for="targetPowerConsumption" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.targetPowerConsumption') }}:
|
||||||
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.targetPowerConsumptionHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.targetPowerConsumptionHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="targetPowerConsumption"
|
<input
|
||||||
placeholder="0" v-model="acChargerConfigList.target_power_consumption"
|
type="number"
|
||||||
aria-describedby="targetPowerConsumptionDescription" min="-3000" max="3000" required/>
|
class="form-control"
|
||||||
|
id="targetPowerConsumption"
|
||||||
|
placeholder="0"
|
||||||
|
v-model="acChargerConfigList.target_power_consumption"
|
||||||
|
aria-describedby="targetPowerConsumptionDescription"
|
||||||
|
min="-3000"
|
||||||
|
max="3000"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="targetPowerConsumptionDescription">W</span>
|
<span class="input-group-text" id="targetPowerConsumptionDescription">W</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
<CardElement :text="$t('acchargeradmin.BatterySoCLimits')" textVariant="text-bg-primary" add-space
|
<CardElement
|
||||||
v-show="acChargerConfigList.auto_power_enabled && acChargerConfigList.auto_power_batterysoc_limits_enabled">
|
:text="$t('acchargeradmin.BatterySoCLimits')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-show="
|
||||||
|
acChargerConfigList.auto_power_enabled &&
|
||||||
|
acChargerConfigList.auto_power_batterysoc_limits_enabled
|
||||||
|
"
|
||||||
|
>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="stopBatterySoCThreshold" class="col-sm-2 col-form-label">{{ $t('acchargeradmin.StopBatterySoCThreshold') }}:
|
<label for="stopBatterySoCThreshold" class="col-sm-2 col-form-label"
|
||||||
|
>{{ $t('acchargeradmin.StopBatterySoCThreshold') }}:
|
||||||
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.StopBatterySoCThresholdHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('acchargeradmin.StopBatterySoCThresholdHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="number" class="form-control" id="stopBatterySoCThreshold"
|
<input
|
||||||
placeholder="95" v-model="acChargerConfigList.stop_batterysoc_threshold"
|
type="number"
|
||||||
aria-describedby="stopBatterySoCThresholdDescription" min="2" max="99" required/>
|
class="form-control"
|
||||||
|
id="stopBatterySoCThreshold"
|
||||||
|
placeholder="95"
|
||||||
|
v-model="acChargerConfigList.stop_batterysoc_threshold"
|
||||||
|
aria-describedby="stopBatterySoCThresholdDescription"
|
||||||
|
min="2"
|
||||||
|
max="99"
|
||||||
|
required
|
||||||
|
/>
|
||||||
<span class="input-group-text" id="stopBatterySoCThresholdDescription">%</span>
|
<span class="input-group-text" id="stopBatterySoCThresholdDescription">%</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -120,19 +206,19 @@
|
|||||||
</CardElement>
|
</CardElement>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<FormFooter @reload="getChargerConfig"/>
|
<FormFooter @reload="getChargerConfig" />
|
||||||
</form>
|
</form>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import FormFooter from '@/components/FormFooter.vue';
|
import FormFooter from '@/components/FormFooter.vue';
|
||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
import { BIconInfoCircle } from 'bootstrap-icons-vue';
|
import { BIconInfoCircle } from 'bootstrap-icons-vue';
|
||||||
import type { AcChargerConfig } from "@/types/AcChargerConfig";
|
import type { AcChargerConfig } from '@/types/AcChargerConfig';
|
||||||
import { authHeader, handleResponse } from '@/utils/authentication';
|
import { authHeader, handleResponse } from '@/utils/authentication';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
@ -149,8 +235,8 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
acChargerConfigList: {} as AcChargerConfig,
|
acChargerConfigList: {} as AcChargerConfig,
|
||||||
alertMessage: "",
|
alertMessage: '',
|
||||||
alertType: "info",
|
alertType: 'info',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
frequencyTypeList: [
|
frequencyTypeList: [
|
||||||
{ key: 8, value: 8000000 },
|
{ key: 8, value: 8000000 },
|
||||||
@ -164,7 +250,7 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
getChargerConfig() {
|
getChargerConfig() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/huawei/config", { headers: authHeader() })
|
fetch('/api/huawei/config', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.acChargerConfigList = data;
|
this.acChargerConfigList = data;
|
||||||
@ -175,21 +261,19 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.acChargerConfigList));
|
formData.append('data', JSON.stringify(this.acChargerConfigList));
|
||||||
|
|
||||||
fetch("/api/huawei/config", {
|
fetch('/api/huawei/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
||||||
this.alertType = response.type;
|
this.alertType = response.type;
|
||||||
this.showAlert = true;
|
this.showAlert = true;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,14 +6,18 @@
|
|||||||
|
|
||||||
<form @submit="saveBatteryConfig">
|
<form @submit="saveBatteryConfig">
|
||||||
<CardElement :text="$t('batteryadmin.BatteryConfiguration')" textVariant="text-bg-primary">
|
<CardElement :text="$t('batteryadmin.BatteryConfiguration')" textVariant="text-bg-primary">
|
||||||
<InputElement :label="$t('batteryadmin.EnableBattery')"
|
<InputElement
|
||||||
|
:label="$t('batteryadmin.EnableBattery')"
|
||||||
v-model="batteryConfigList.enabled"
|
v-model="batteryConfigList.enabled"
|
||||||
type="checkbox" />
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="batteryConfigList.enabled"
|
<InputElement
|
||||||
|
v-show="batteryConfigList.enabled"
|
||||||
:label="$t('batteryadmin.VerboseLogging')"
|
:label="$t('batteryadmin.VerboseLogging')"
|
||||||
v-model="batteryConfigList.verbose_logging"
|
v-model="batteryConfigList.verbose_logging"
|
||||||
type="checkbox"/>
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-show="batteryConfigList.enabled">
|
<div class="row mb-3" v-show="batteryConfigList.enabled">
|
||||||
<label class="col-sm-2 col-form-label">
|
<label class="col-sm-2 col-form-label">
|
||||||
@ -29,61 +33,84 @@
|
|||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement v-show="batteryConfigList.enabled && batteryConfigList.provider == 1"
|
<CardElement
|
||||||
:text="$t('batteryadmin.JkBmsConfiguration')" textVariant="text-bg-primary" addSpace>
|
v-show="batteryConfigList.enabled && batteryConfigList.provider == 1"
|
||||||
|
:text="$t('batteryadmin.JkBmsConfiguration')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
addSpace
|
||||||
|
>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label class="col-sm-2 col-form-label">
|
<label class="col-sm-2 col-form-label">
|
||||||
{{ $t('batteryadmin.JkBmsInterface') }}
|
{{ $t('batteryadmin.JkBmsInterface') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<select class="form-select" v-model="batteryConfigList.jkbms_interface">
|
<select class="form-select" v-model="batteryConfigList.jkbms_interface">
|
||||||
<option v-for="jkBmsInterface in jkBmsInterfaceTypeList" :key="jkBmsInterface.key" :value="jkBmsInterface.key">
|
<option
|
||||||
|
v-for="jkBmsInterface in jkBmsInterfaceTypeList"
|
||||||
|
:key="jkBmsInterface.key"
|
||||||
|
:value="jkBmsInterface.key"
|
||||||
|
>
|
||||||
{{ $t(`batteryadmin.JkBmsInterface` + jkBmsInterface.value) }}
|
{{ $t(`batteryadmin.JkBmsInterface` + jkBmsInterface.value) }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InputElement :label="$t('batteryadmin.PollingInterval')"
|
<InputElement
|
||||||
|
:label="$t('batteryadmin.PollingInterval')"
|
||||||
v-model="batteryConfigList.jkbms_polling_interval"
|
v-model="batteryConfigList.jkbms_polling_interval"
|
||||||
type="number" min="2" max="90" step="1" :postfix="$t('batteryadmin.Seconds')"/>
|
type="number"
|
||||||
|
min="2"
|
||||||
|
max="90"
|
||||||
|
step="1"
|
||||||
|
:postfix="$t('batteryadmin.Seconds')"
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<template v-if="batteryConfigList.enabled && batteryConfigList.provider == 2">
|
<template v-if="batteryConfigList.enabled && batteryConfigList.provider == 2">
|
||||||
<CardElement :text="$t('batteryadmin.MqttSocConfiguration')" textVariant="text-bg-primary" addSpace>
|
<CardElement :text="$t('batteryadmin.MqttSocConfiguration')" textVariant="text-bg-primary" addSpace>
|
||||||
|
<InputElement
|
||||||
<InputElement :label="$t('batteryadmin.MqttSocTopic')"
|
:label="$t('batteryadmin.MqttSocTopic')"
|
||||||
v-model="batteryConfigList.mqtt_soc_topic"
|
v-model="batteryConfigList.mqtt_soc_topic"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256" />
|
maxlength="256"
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('batteryadmin.MqttJsonPath')"
|
<InputElement
|
||||||
|
:label="$t('batteryadmin.MqttJsonPath')"
|
||||||
v-model="batteryConfigList.mqtt_soc_json_path"
|
v-model="batteryConfigList.mqtt_soc_json_path"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="128"
|
maxlength="128"
|
||||||
:tooltip="$t('batteryadmin.MqttJsonPathDescription')" />
|
:tooltip="$t('batteryadmin.MqttJsonPathDescription')"
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('batteryadmin.MqttVoltageConfiguration')" textVariant="text-bg-primary" addSpace>
|
<CardElement :text="$t('batteryadmin.MqttVoltageConfiguration')" textVariant="text-bg-primary" addSpace>
|
||||||
|
<InputElement
|
||||||
<InputElement :label="$t('batteryadmin.MqttVoltageTopic')"
|
:label="$t('batteryadmin.MqttVoltageTopic')"
|
||||||
v-model="batteryConfigList.mqtt_voltage_topic"
|
v-model="batteryConfigList.mqtt_voltage_topic"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256" />
|
maxlength="256"
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('batteryadmin.MqttJsonPath')"
|
<InputElement
|
||||||
|
:label="$t('batteryadmin.MqttJsonPath')"
|
||||||
v-model="batteryConfigList.mqtt_voltage_json_path"
|
v-model="batteryConfigList.mqtt_voltage_json_path"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="128"
|
maxlength="128"
|
||||||
:tooltip="$t('batteryadmin.MqttJsonPathDescription')" />
|
:tooltip="$t('batteryadmin.MqttJsonPathDescription')"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="mqtt_voltage_unit" class="col-sm-2 col-form-label">
|
<label for="mqtt_voltage_unit" class="col-sm-2 col-form-label">
|
||||||
{{ $t('batteryadmin.MqttVoltageUnit') }}
|
{{ $t('batteryadmin.MqttVoltageUnit') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<select id="mqtt_voltage_unit" class="form-select" v-model="batteryConfigList.mqtt_voltage_unit">
|
<select
|
||||||
|
id="mqtt_voltage_unit"
|
||||||
|
class="form-select"
|
||||||
|
v-model="batteryConfigList.mqtt_voltage_unit"
|
||||||
|
>
|
||||||
<option v-for="u in voltageUnitTypeList" :key="u.key" :value="u.key">
|
<option v-for="u in voltageUnitTypeList" :key="u.key" :value="u.key">
|
||||||
{{ u.value }}
|
{{ u.value }}
|
||||||
</option>
|
</option>
|
||||||
@ -93,18 +120,18 @@
|
|||||||
</CardElement>
|
</CardElement>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<FormFooter @reload="getBatteryConfig"/>
|
<FormFooter @reload="getBatteryConfig" />
|
||||||
</form>
|
</form>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import FormFooter from '@/components/FormFooter.vue';
|
import FormFooter from '@/components/FormFooter.vue';
|
||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
import type { BatteryConfig } from "@/types/BatteryConfig";
|
import type { BatteryConfig } from '@/types/BatteryConfig';
|
||||||
import { authHeader, handleResponse } from '@/utils/authentication';
|
import { authHeader, handleResponse } from '@/utils/authentication';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
@ -120,8 +147,8 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
batteryConfigList: {} as BatteryConfig,
|
batteryConfigList: {} as BatteryConfig,
|
||||||
alertMessage: "",
|
alertMessage: '',
|
||||||
alertType: "info",
|
alertType: 'info',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
providerTypeList: [
|
providerTypeList: [
|
||||||
{ key: 0, value: 'PylontechCan' },
|
{ key: 0, value: 'PylontechCan' },
|
||||||
@ -135,10 +162,10 @@ export default defineComponent({
|
|||||||
{ key: 1, value: 'Transceiver' },
|
{ key: 1, value: 'Transceiver' },
|
||||||
],
|
],
|
||||||
voltageUnitTypeList: [
|
voltageUnitTypeList: [
|
||||||
{ key: 3, value: "mV" },
|
{ key: 3, value: 'mV' },
|
||||||
{ key: 2, value: "cV" },
|
{ key: 2, value: 'cV' },
|
||||||
{ key: 1, value: "dV" },
|
{ key: 1, value: 'dV' },
|
||||||
{ key: 0, value: "V" },
|
{ key: 0, value: 'V' },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -148,7 +175,7 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
getBatteryConfig() {
|
getBatteryConfig() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/battery/config", { headers: authHeader() })
|
fetch('/api/battery/config', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.batteryConfigList = data;
|
this.batteryConfigList = data;
|
||||||
@ -159,21 +186,19 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.batteryConfigList));
|
formData.append('data', JSON.stringify(this.batteryConfigList));
|
||||||
|
|
||||||
fetch("/api/battery/config", {
|
fetch('/api/battery/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
||||||
this.alertType = response.type;
|
this.alertType = response.type;
|
||||||
this.showAlert = true;
|
this.showAlert = true;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -24,9 +24,11 @@
|
|||||||
:postfix="$t('dtuadmin.Seconds')"
|
:postfix="$t('dtuadmin.Seconds')"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('dtuadmin.VerboseLogging')"
|
<InputElement
|
||||||
|
:label="$t('dtuadmin.VerboseLogging')"
|
||||||
v-model="dtuConfigList.verbose_logging"
|
v-model="dtuConfigList.verbose_logging"
|
||||||
type="checkbox"/>
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-if="dtuConfigList.nrf_enabled">
|
<div class="row mb-3" v-if="dtuConfigList.nrf_enabled">
|
||||||
<label for="inputNrfPaLevel" class="col-sm-2 col-form-label">
|
<label for="inputNrfPaLevel" class="col-sm-2 col-form-label">
|
||||||
|
|||||||
@ -8,7 +8,13 @@
|
|||||||
@reload="reloadData"
|
@reload="reloadData"
|
||||||
>
|
>
|
||||||
<HintView :hints="liveData.hints" />
|
<HintView :hints="liveData.hints" />
|
||||||
<InverterTotalInfo :totalData="liveData.total" :totalVeData="liveData.vedirect" :totalBattData="liveData.battery" :powerMeterData="liveData.power_meter" :huaweiData="liveData.huawei"/>
|
<InverterTotalInfo
|
||||||
|
:totalData="liveData.total"
|
||||||
|
:totalVeData="liveData.vedirect"
|
||||||
|
:totalBattData="liveData.battery"
|
||||||
|
:powerMeterData="liveData.power_meter"
|
||||||
|
:huaweiData="liveData.huawei"
|
||||||
|
/>
|
||||||
<div class="row gy-3 mt-0">
|
<div class="row gy-3 mt-0">
|
||||||
<div class="col-sm-3 col-md-2" :style="[inverterData.length == 1 ? { display: 'none' } : {}]">
|
<div class="col-sm-3 col-md-2" :style="[inverterData.length == 1 ? { display: 'none' } : {}]">
|
||||||
<div class="nav nav-pills row-cols-sm-1" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
<div class="nav nav-pills row-cols-sm-1" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||||
@ -383,8 +389,8 @@ import InverterChannelInfo from '@/components/InverterChannelInfo.vue';
|
|||||||
import InverterTotalInfo from '@/components/InverterTotalInfo.vue';
|
import InverterTotalInfo from '@/components/InverterTotalInfo.vue';
|
||||||
import ModalDialog from '@/components/ModalDialog.vue';
|
import ModalDialog from '@/components/ModalDialog.vue';
|
||||||
import VedirectView from '@/components/VedirectView.vue';
|
import VedirectView from '@/components/VedirectView.vue';
|
||||||
import HuaweiView from '@/components/HuaweiView.vue'
|
import HuaweiView from '@/components/HuaweiView.vue';
|
||||||
import BatteryView from '@/components/BatteryView.vue'
|
import BatteryView from '@/components/BatteryView.vue';
|
||||||
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
import type { DevInfoStatus } from '@/types/DevInfoStatus';
|
||||||
import type { EventlogItems } from '@/types/EventlogStatus';
|
import type { EventlogItems } from '@/types/EventlogStatus';
|
||||||
import type { GridProfileStatus } from '@/types/GridProfileStatus';
|
import type { GridProfileStatus } from '@/types/GridProfileStatus';
|
||||||
@ -433,7 +439,7 @@ export default defineComponent({
|
|||||||
BIconXCircleFill,
|
BIconXCircleFill,
|
||||||
VedirectView,
|
VedirectView,
|
||||||
HuaweiView,
|
HuaweiView,
|
||||||
BatteryView
|
BatteryView,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -577,12 +583,22 @@ export default defineComponent({
|
|||||||
if (event.data != '{}') {
|
if (event.data != '{}') {
|
||||||
const newData = JSON.parse(event.data);
|
const newData = JSON.parse(event.data);
|
||||||
|
|
||||||
if (typeof newData.vedirect !== 'undefined') { Object.assign(this.liveData.vedirect, newData.vedirect); }
|
if (typeof newData.vedirect !== 'undefined') {
|
||||||
if (typeof newData.huawei !== 'undefined') { Object.assign(this.liveData.huawei, newData.huawei); }
|
Object.assign(this.liveData.vedirect, newData.vedirect);
|
||||||
if (typeof newData.battery !== 'undefined') { Object.assign(this.liveData.battery, newData.battery); }
|
}
|
||||||
if (typeof newData.power_meter !== 'undefined') { Object.assign(this.liveData.power_meter, newData.power_meter); }
|
if (typeof newData.huawei !== 'undefined') {
|
||||||
|
Object.assign(this.liveData.huawei, newData.huawei);
|
||||||
|
}
|
||||||
|
if (typeof newData.battery !== 'undefined') {
|
||||||
|
Object.assign(this.liveData.battery, newData.battery);
|
||||||
|
}
|
||||||
|
if (typeof newData.power_meter !== 'undefined') {
|
||||||
|
Object.assign(this.liveData.power_meter, newData.power_meter);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof newData.total === 'undefined') { return; }
|
if (typeof newData.total === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(this.liveData.total, newData.total);
|
Object.assign(this.liveData.total, newData.total);
|
||||||
Object.assign(this.liveData.hints, newData.hints);
|
Object.assign(this.liveData.hints, newData.hints);
|
||||||
|
|||||||
@ -13,10 +13,13 @@
|
|||||||
wide
|
wide
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InputElement v-show="mqttConfigList.mqtt_enabled"
|
<InputElement
|
||||||
|
v-show="mqttConfigList.mqtt_enabled"
|
||||||
:label="$t('mqttadmin.VerboseLogging')"
|
:label="$t('mqttadmin.VerboseLogging')"
|
||||||
v-model="mqttConfigList.mqtt_verbose_logging"
|
v-model="mqttConfigList.mqtt_verbose_logging"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement
|
<InputElement
|
||||||
v-show="mqttConfigList.mqtt_enabled"
|
v-show="mqttConfigList.mqtt_enabled"
|
||||||
|
|||||||
@ -22,7 +22,11 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('mqttinfo.VerboseLogging') }}</th>
|
<th>{{ $t('mqttinfo.VerboseLogging') }}</th>
|
||||||
<td>
|
<td>
|
||||||
<StatusBadge :status="mqttDataList.mqtt_verbose_logging" true_text="mqttinfo.Enabled" false_text="mqttinfo.Disabled" />
|
<StatusBadge
|
||||||
|
:status="mqttDataList.mqtt_verbose_logging"
|
||||||
|
true_text="mqttinfo.Enabled"
|
||||||
|
false_text="mqttinfo.Disabled"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@ -8,13 +8,19 @@
|
|||||||
{{ $t('powerlimiteradmin.ConfigAlertMessage') }}
|
{{ $t('powerlimiteradmin.ConfigAlertMessage') }}
|
||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
|
|
||||||
<CardElement :text="$t('powerlimiteradmin.ConfigHints')" textVariant="text-bg-primary" v-if="getConfigHints().length">
|
<CardElement
|
||||||
|
:text="$t('powerlimiteradmin.ConfigHints')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
v-if="getConfigHints().length"
|
||||||
|
>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
{{ $t('powerlimiteradmin.ConfigHintsIntro') }}
|
{{ $t('powerlimiteradmin.ConfigHintsIntro') }}
|
||||||
<ul class="mb-0">
|
<ul class="mb-0">
|
||||||
<li v-for="(hint, idx) in getConfigHints()" :key="idx">
|
<li v-for="(hint, idx) in getConfigHints()" :key="idx">
|
||||||
<b v-if="hint.severity === 'requirement'">{{ $t('powerlimiteradmin.ConfigHintRequirement') }}:</b>
|
<b v-if="hint.severity === 'requirement'"
|
||||||
|
>{{ $t('powerlimiteradmin.ConfigHintRequirement') }}:</b
|
||||||
|
>
|
||||||
<b v-if="hint.severity === 'optional'">{{ $t('powerlimiteradmin.ConfigHintOptional') }}:</b>
|
<b v-if="hint.severity === 'optional'">{{ $t('powerlimiteradmin.ConfigHintOptional') }}:</b>
|
||||||
{{ $t('powerlimiteradmin.ConfigHint' + hint.subject) }}
|
{{ $t('powerlimiteradmin.ConfigHint' + hint.subject) }}
|
||||||
</li>
|
</li>
|
||||||
@ -25,91 +31,153 @@
|
|||||||
|
|
||||||
<form @submit="savePowerLimiterConfig" v-if="!configAlert">
|
<form @submit="savePowerLimiterConfig" v-if="!configAlert">
|
||||||
<CardElement :text="$t('powerlimiteradmin.General')" textVariant="text-bg-primary" add-space>
|
<CardElement :text="$t('powerlimiteradmin.General')" textVariant="text-bg-primary" add-space>
|
||||||
<InputElement :label="$t('powerlimiteradmin.Enable')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.Enable')"
|
||||||
v-model="powerLimiterConfigList.enabled"
|
v-model="powerLimiterConfigList.enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="isEnabled()"
|
<InputElement
|
||||||
|
v-show="isEnabled()"
|
||||||
:label="$t('powerlimiteradmin.VerboseLogging')"
|
:label="$t('powerlimiteradmin.VerboseLogging')"
|
||||||
v-model="powerLimiterConfigList.verbose_logging"
|
v-model="powerLimiterConfigList.verbose_logging"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="isEnabled() && hasPowerMeter()"
|
<InputElement
|
||||||
|
v-show="isEnabled() && hasPowerMeter()"
|
||||||
:label="$t('powerlimiteradmin.TargetPowerConsumption')"
|
:label="$t('powerlimiteradmin.TargetPowerConsumption')"
|
||||||
:tooltip="$t('powerlimiteradmin.TargetPowerConsumptionHint')"
|
:tooltip="$t('powerlimiteradmin.TargetPowerConsumptionHint')"
|
||||||
v-model="powerLimiterConfigList.target_power_consumption"
|
v-model="powerLimiterConfigList.target_power_consumption"
|
||||||
postfix="W"
|
postfix="W"
|
||||||
type="number" wide/>
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="isEnabled()"
|
<InputElement
|
||||||
|
v-show="isEnabled()"
|
||||||
:label="$t('powerlimiteradmin.TargetPowerConsumptionHysteresis')"
|
:label="$t('powerlimiteradmin.TargetPowerConsumptionHysteresis')"
|
||||||
:tooltip="$t('powerlimiteradmin.TargetPowerConsumptionHysteresisHint')"
|
:tooltip="$t('powerlimiteradmin.TargetPowerConsumptionHysteresisHint')"
|
||||||
v-model="powerLimiterConfigList.target_power_consumption_hysteresis"
|
v-model="powerLimiterConfigList.target_power_consumption_hysteresis"
|
||||||
postfix="W"
|
postfix="W"
|
||||||
type="number" wide/>
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('powerlimiteradmin.InverterSettings')" textVariant="text-bg-primary" add-space v-if="isEnabled()">
|
<CardElement
|
||||||
|
:text="$t('powerlimiteradmin.InverterSettings')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-if="isEnabled()"
|
||||||
|
>
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="inverter_serial" class="col-sm-4 col-form-label">
|
<label for="inverter_serial" class="col-sm-4 col-form-label">
|
||||||
{{ $t('powerlimiteradmin.Inverter') }}
|
{{ $t('powerlimiteradmin.Inverter') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select id="inverter_serial" class="form-select" v-model="powerLimiterConfigList.inverter_serial" required>
|
<select
|
||||||
<option value="" disabled hidden selected>{{ $t('powerlimiteradmin.SelectInverter') }}</option>
|
id="inverter_serial"
|
||||||
<option v-for="(inv, serial) in powerLimiterMetaData.inverters" :key="serial" :value="serial">
|
class="form-select"
|
||||||
|
v-model="powerLimiterConfigList.inverter_serial"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="" disabled hidden selected>
|
||||||
|
{{ $t('powerlimiteradmin.SelectInverter') }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(inv, serial) in powerLimiterMetaData.inverters"
|
||||||
|
:key="serial"
|
||||||
|
:value="serial"
|
||||||
|
>
|
||||||
{{ inv.name }} ({{ inv.type }})
|
{{ inv.name }} ({{ inv.type }})
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.InverterIsSolarPowered')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.InverterIsSolarPowered')"
|
||||||
v-model="powerLimiterConfigList.is_inverter_solar_powered"
|
v-model="powerLimiterConfigList.is_inverter_solar_powered"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="canUseOverscaling()"
|
<InputElement
|
||||||
|
v-show="canUseOverscaling()"
|
||||||
:label="$t('powerlimiteradmin.UseOverscalingToCompensateShading')"
|
:label="$t('powerlimiteradmin.UseOverscalingToCompensateShading')"
|
||||||
:tooltip="$t('powerlimiteradmin.UseOverscalingToCompensateShadingHint')"
|
:tooltip="$t('powerlimiteradmin.UseOverscalingToCompensateShadingHint')"
|
||||||
v-model="powerLimiterConfigList.use_overscaling_to_compensate_shading"
|
v-model="powerLimiterConfigList.use_overscaling_to_compensate_shading"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-if="needsChannelSelection()">
|
<div class="row mb-3" v-if="needsChannelSelection()">
|
||||||
<label for="inverter_channel" class="col-sm-4 col-form-label">
|
<label for="inverter_channel" class="col-sm-4 col-form-label">
|
||||||
{{ $t('powerlimiteradmin.InverterChannelId') }}
|
{{ $t('powerlimiteradmin.InverterChannelId') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select id="inverter_channel" class="form-select" v-model="powerLimiterConfigList.inverter_channel_id">
|
<select
|
||||||
<option v-for="channel in range(powerLimiterMetaData.inverters[powerLimiterConfigList.inverter_serial].channels)" :key="channel" :value="channel">
|
id="inverter_channel"
|
||||||
|
class="form-select"
|
||||||
|
v-model="powerLimiterConfigList.inverter_channel_id"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-for="channel in range(
|
||||||
|
powerLimiterMetaData.inverters[powerLimiterConfigList.inverter_serial].channels
|
||||||
|
)"
|
||||||
|
:key="channel"
|
||||||
|
:value="channel"
|
||||||
|
>
|
||||||
{{ channel + 1 }}
|
{{ channel + 1 }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.LowerPowerLimit')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.LowerPowerLimit')"
|
||||||
:tooltip="$t('powerlimiteradmin.LowerPowerLimitHint')"
|
:tooltip="$t('powerlimiteradmin.LowerPowerLimitHint')"
|
||||||
v-model="powerLimiterConfigList.lower_power_limit"
|
v-model="powerLimiterConfigList.lower_power_limit"
|
||||||
placeholder="50" min="10" postfix="W"
|
placeholder="50"
|
||||||
type="number" wide/>
|
min="10"
|
||||||
|
postfix="W"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.BaseLoadLimit')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.BaseLoadLimit')"
|
||||||
:tooltip="$t('powerlimiteradmin.BaseLoadLimitHint')"
|
:tooltip="$t('powerlimiteradmin.BaseLoadLimitHint')"
|
||||||
v-model="powerLimiterConfigList.base_load_limit"
|
v-model="powerLimiterConfigList.base_load_limit"
|
||||||
placeholder="200" :min="(powerLimiterConfigList.lower_power_limit + 1).toString()" postfix="W"
|
placeholder="200"
|
||||||
type="number" wide/>
|
:min="(powerLimiterConfigList.lower_power_limit + 1).toString()"
|
||||||
|
postfix="W"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.UpperPowerLimit')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.UpperPowerLimit')"
|
||||||
v-model="powerLimiterConfigList.upper_power_limit"
|
v-model="powerLimiterConfigList.upper_power_limit"
|
||||||
:tooltip="$t('powerlimiteradmin.UpperPowerLimitHint')"
|
:tooltip="$t('powerlimiteradmin.UpperPowerLimitHint')"
|
||||||
placeholder="800" :min="(powerLimiterConfigList.base_load_limit + 1).toString()" postfix="W"
|
placeholder="800"
|
||||||
type="number" wide/>
|
:min="(powerLimiterConfigList.base_load_limit + 1).toString()"
|
||||||
|
postfix="W"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="hasPowerMeter()"
|
<InputElement
|
||||||
|
v-show="hasPowerMeter()"
|
||||||
:label="$t('powerlimiteradmin.InverterIsBehindPowerMeter')"
|
:label="$t('powerlimiteradmin.InverterIsBehindPowerMeter')"
|
||||||
v-model="powerLimiterConfigList.is_inverter_behind_powermeter"
|
v-model="powerLimiterConfigList.is_inverter_behind_powermeter"
|
||||||
:tooltip="$t('powerlimiteradmin.InverterIsBehindPowerMeterHint')"
|
:tooltip="$t('powerlimiteradmin.InverterIsBehindPowerMeterHint')"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-if="!powerLimiterConfigList.is_inverter_solar_powered">
|
<div class="row mb-3" v-if="!powerLimiterConfigList.is_inverter_solar_powered">
|
||||||
<label for="inverter_restart" class="col-sm-4 col-form-label">
|
<label for="inverter_restart" class="col-sm-4 col-form-label">
|
||||||
@ -117,100 +185,200 @@
|
|||||||
<BIconInfoCircle v-tooltip :title="$t('powerlimiteradmin.InverterRestartHint')" />
|
<BIconInfoCircle v-tooltip :title="$t('powerlimiteradmin.InverterRestartHint')" />
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select id="inverter_restart" class="form-select" v-model="powerLimiterConfigList.inverter_restart_hour">
|
<select
|
||||||
|
id="inverter_restart"
|
||||||
|
class="form-select"
|
||||||
|
v-model="powerLimiterConfigList.inverter_restart_hour"
|
||||||
|
>
|
||||||
<option value="-1">
|
<option value="-1">
|
||||||
{{ $t('powerlimiteradmin.InverterRestartDisabled') }}
|
{{ $t('powerlimiteradmin.InverterRestartDisabled') }}
|
||||||
</option>
|
</option>
|
||||||
<option v-for="hour in range(24)" :key="hour" :value="hour">
|
<option v-for="hour in range(24)" :key="hour" :value="hour">
|
||||||
{{ (hour > 9) ? hour : "0"+hour }}:00
|
{{ hour > 9 ? hour : '0' + hour }}:00
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('powerlimiteradmin.SolarPassthrough')" textVariant="text-bg-primary" add-space v-if="canUseSolarPassthrough()">
|
<CardElement
|
||||||
<div class="alert alert-secondary" role="alert" v-html="$t('powerlimiteradmin.SolarpassthroughInfo')"></div>
|
:text="$t('powerlimiteradmin.SolarPassthrough')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-if="canUseSolarPassthrough()"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="alert alert-secondary"
|
||||||
|
role="alert"
|
||||||
|
v-html="$t('powerlimiteradmin.SolarpassthroughInfo')"
|
||||||
|
></div>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.EnableSolarPassthrough')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.EnableSolarPassthrough')"
|
||||||
v-model="powerLimiterConfigList.solar_passthrough_enabled"
|
v-model="powerLimiterConfigList.solar_passthrough_enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div v-if="powerLimiterConfigList.solar_passthrough_enabled">
|
<div v-if="powerLimiterConfigList.solar_passthrough_enabled">
|
||||||
<InputElement :label="$t('powerlimiteradmin.BatteryDischargeAtNight')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.BatteryDischargeAtNight')"
|
||||||
v-model="powerLimiterConfigList.battery_always_use_at_night"
|
v-model="powerLimiterConfigList.battery_always_use_at_night"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.SolarPassthroughLosses')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.SolarPassthroughLosses')"
|
||||||
v-model="powerLimiterConfigList.solar_passthrough_losses"
|
v-model="powerLimiterConfigList.solar_passthrough_losses"
|
||||||
placeholder="3" min="0" max="10" postfix="%"
|
placeholder="3"
|
||||||
type="number" wide/>
|
min="0"
|
||||||
|
max="10"
|
||||||
|
postfix="%"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="alert alert-secondary" role="alert" v-html="$t('powerlimiteradmin.SolarPassthroughLossesInfo')"></div>
|
<div
|
||||||
|
class="alert alert-secondary"
|
||||||
|
role="alert"
|
||||||
|
v-html="$t('powerlimiteradmin.SolarPassthroughLossesInfo')"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('powerlimiteradmin.SocThresholds')" textVariant="text-bg-primary" add-space v-if="canUseSoCThresholds()">
|
<CardElement
|
||||||
|
:text="$t('powerlimiteradmin.SocThresholds')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-if="canUseSoCThresholds()"
|
||||||
|
>
|
||||||
<InputElement
|
<InputElement
|
||||||
:label="$t('powerlimiteradmin.IgnoreSoc')"
|
:label="$t('powerlimiteradmin.IgnoreSoc')"
|
||||||
v-model="powerLimiterConfigList.ignore_soc"
|
v-model="powerLimiterConfigList.ignore_soc"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div v-if="!powerLimiterConfigList.ignore_soc">
|
<div v-if="!powerLimiterConfigList.ignore_soc">
|
||||||
<div class="alert alert-secondary" role="alert" v-html="$t('powerlimiteradmin.BatterySocInfo')"></div>
|
<div
|
||||||
|
class="alert alert-secondary"
|
||||||
|
role="alert"
|
||||||
|
v-html="$t('powerlimiteradmin.BatterySocInfo')"
|
||||||
|
></div>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.StartThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.StartThreshold')"
|
||||||
v-model="powerLimiterConfigList.battery_soc_start_threshold"
|
v-model="powerLimiterConfigList.battery_soc_start_threshold"
|
||||||
placeholder="80" min="0" max="100" postfix="%"
|
placeholder="80"
|
||||||
type="number" wide/>
|
min="0"
|
||||||
|
max="100"
|
||||||
|
postfix="%"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.StopThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.StopThreshold')"
|
||||||
v-model="powerLimiterConfigList.battery_soc_stop_threshold"
|
v-model="powerLimiterConfigList.battery_soc_stop_threshold"
|
||||||
placeholder="20" min="0" max="100" postfix="%"
|
placeholder="20"
|
||||||
type="number" wide/>
|
min="0"
|
||||||
|
max="100"
|
||||||
|
postfix="%"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.FullSolarPassthroughStartThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.FullSolarPassthroughStartThreshold')"
|
||||||
:tooltip="$t('powerlimiteradmin.FullSolarPassthroughStartThresholdHint')"
|
:tooltip="$t('powerlimiteradmin.FullSolarPassthroughStartThresholdHint')"
|
||||||
v-model="powerLimiterConfigList.full_solar_passthrough_soc"
|
v-model="powerLimiterConfigList.full_solar_passthrough_soc"
|
||||||
v-if="isSolarPassthroughEnabled()"
|
v-if="isSolarPassthroughEnabled()"
|
||||||
placeholder="80" min="0" max="100" postfix="%"
|
placeholder="80"
|
||||||
type="number" wide/>
|
min="0"
|
||||||
|
max="100"
|
||||||
|
postfix="%"
|
||||||
|
type="number"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('powerlimiteradmin.VoltageThresholds')" textVariant="text-bg-primary" add-space v-if="canUseVoltageThresholds()">
|
<CardElement
|
||||||
<InputElement :label="$t('powerlimiteradmin.StartThreshold')"
|
:text="$t('powerlimiteradmin.VoltageThresholds')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
|
add-space
|
||||||
|
v-if="canUseVoltageThresholds()"
|
||||||
|
>
|
||||||
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.StartThreshold')"
|
||||||
v-model="powerLimiterConfigList.voltage_start_threshold"
|
v-model="powerLimiterConfigList.voltage_start_threshold"
|
||||||
placeholder="50" min="16" max="66" postfix="V"
|
placeholder="50"
|
||||||
type="number" step="0.01" wide/>
|
min="16"
|
||||||
|
max="66"
|
||||||
|
postfix="V"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.StopThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.StopThreshold')"
|
||||||
v-model="powerLimiterConfigList.voltage_stop_threshold"
|
v-model="powerLimiterConfigList.voltage_stop_threshold"
|
||||||
placeholder="49" min="16" max="66" postfix="V"
|
placeholder="49"
|
||||||
type="number" step="0.01" wide/>
|
min="16"
|
||||||
|
max="66"
|
||||||
|
postfix="V"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div v-if="isSolarPassthroughEnabled()">
|
<div v-if="isSolarPassthroughEnabled()">
|
||||||
<InputElement :label="$t('powerlimiteradmin.FullSolarPassthroughStartThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.FullSolarPassthroughStartThreshold')"
|
||||||
:tooltip="$t('powerlimiteradmin.FullSolarPassthroughStartThresholdHint')"
|
:tooltip="$t('powerlimiteradmin.FullSolarPassthroughStartThresholdHint')"
|
||||||
v-model="powerLimiterConfigList.full_solar_passthrough_start_voltage"
|
v-model="powerLimiterConfigList.full_solar_passthrough_start_voltage"
|
||||||
placeholder="49" min="16" max="66" postfix="V"
|
placeholder="49"
|
||||||
type="number" step="0.01" wide/>
|
min="16"
|
||||||
|
max="66"
|
||||||
|
postfix="V"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.VoltageSolarPassthroughStopThreshold')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.VoltageSolarPassthroughStopThreshold')"
|
||||||
v-model="powerLimiterConfigList.full_solar_passthrough_stop_voltage"
|
v-model="powerLimiterConfigList.full_solar_passthrough_stop_voltage"
|
||||||
placeholder="49" min="16" max="66" postfix="V"
|
placeholder="49"
|
||||||
type="number" step="0.01" wide/>
|
min="16"
|
||||||
|
max="66"
|
||||||
|
postfix="V"
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<InputElement :label="$t('powerlimiteradmin.VoltageLoadCorrectionFactor')"
|
<InputElement
|
||||||
|
:label="$t('powerlimiteradmin.VoltageLoadCorrectionFactor')"
|
||||||
v-model="powerLimiterConfigList.voltage_load_correction_factor"
|
v-model="powerLimiterConfigList.voltage_load_correction_factor"
|
||||||
placeholder="0.0001" postfix="1/A"
|
placeholder="0.0001"
|
||||||
type="number" step="0.0001" wide/>
|
postfix="1/A"
|
||||||
|
type="number"
|
||||||
|
step="0.0001"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="alert alert-secondary" role="alert" v-html="$t('powerlimiteradmin.VoltageLoadCorrectionInfo')"></div>
|
<div
|
||||||
|
class="alert alert-secondary"
|
||||||
|
role="alert"
|
||||||
|
v-html="$t('powerlimiteradmin.VoltageLoadCorrectionInfo')"
|
||||||
|
></div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<FormFooter @reload="getAllData"/>
|
<FormFooter @reload="getAllData" />
|
||||||
</form>
|
</form>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
@ -218,13 +386,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import { handleResponse, authHeader } from '@/utils/authentication';
|
import { handleResponse, authHeader } from '@/utils/authentication';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import FormFooter from '@/components/FormFooter.vue';
|
import FormFooter from '@/components/FormFooter.vue';
|
||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
import { BIconInfoCircle } from 'bootstrap-icons-vue';
|
import { BIconInfoCircle } from 'bootstrap-icons-vue';
|
||||||
import type { PowerLimiterConfig, PowerLimiterMetaData } from "@/types/PowerLimiterConfig";
|
import type { PowerLimiterConfig, PowerLimiterMetaData } from '@/types/PowerLimiterConfig';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -240,8 +408,8 @@ export default defineComponent({
|
|||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
powerLimiterConfigList: {} as PowerLimiterConfig,
|
powerLimiterConfigList: {} as PowerLimiterConfig,
|
||||||
powerLimiterMetaData: {} as PowerLimiterMetaData,
|
powerLimiterMetaData: {} as PowerLimiterMetaData,
|
||||||
alertMessage: "",
|
alertMessage: '',
|
||||||
alertType: "info",
|
alertType: 'info',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
configAlert: false,
|
configAlert: false,
|
||||||
};
|
};
|
||||||
@ -254,9 +422,13 @@ export default defineComponent({
|
|||||||
const cfg = this.powerLimiterConfigList;
|
const cfg = this.powerLimiterConfigList;
|
||||||
const meta = this.powerLimiterMetaData;
|
const meta = this.powerLimiterMetaData;
|
||||||
|
|
||||||
if (newVal === "") { return; } // do not try to convert the placeholder value
|
if (newVal === '') {
|
||||||
|
return;
|
||||||
|
} // do not try to convert the placeholder value
|
||||||
|
|
||||||
if (meta.inverters[newVal] !== undefined) { return; }
|
if (meta.inverters[newVal] !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const [serial, inverter] of Object.entries(meta.inverters)) {
|
for (const [serial, inverter] of Object.entries(meta.inverters)) {
|
||||||
// cfg.inverter_serial might be too large to parse as a 32 bit
|
// cfg.inverter_serial might be too large to parse as a 32 bit
|
||||||
@ -274,7 +446,7 @@ export default defineComponent({
|
|||||||
// previously selected inverter was deleted. marks serial as
|
// previously selected inverter was deleted. marks serial as
|
||||||
// invalid, selects placeholder option.
|
// invalid, selects placeholder option.
|
||||||
cfg.inverter_serial = '';
|
cfg.inverter_serial = '';
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getConfigHints() {
|
getConfigHints() {
|
||||||
@ -283,27 +455,29 @@ export default defineComponent({
|
|||||||
const hints = [];
|
const hints = [];
|
||||||
|
|
||||||
if (meta.power_meter_enabled !== true) {
|
if (meta.power_meter_enabled !== true) {
|
||||||
hints.push({severity: "optional", subject: "PowerMeterDisabled"});
|
hints.push({ severity: 'optional', subject: 'PowerMeterDisabled' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof meta.inverters === "undefined" || Object.keys(meta.inverters).length == 0) {
|
if (typeof meta.inverters === 'undefined' || Object.keys(meta.inverters).length == 0) {
|
||||||
hints.push({severity: "requirement", subject: "NoInverter"});
|
hints.push({ severity: 'requirement', subject: 'NoInverter' });
|
||||||
this.configAlert = true;
|
this.configAlert = true;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const inv = meta.inverters[cfg.inverter_serial];
|
const inv = meta.inverters[cfg.inverter_serial];
|
||||||
if (inv !== undefined && !(inv.poll_enable && inv.command_enable && inv.poll_enable_night && inv.command_enable_night)) {
|
if (
|
||||||
hints.push({severity: "requirement", subject: "InverterCommunication"});
|
inv !== undefined &&
|
||||||
|
!(inv.poll_enable && inv.command_enable && inv.poll_enable_night && inv.command_enable_night)
|
||||||
|
) {
|
||||||
|
hints.push({ severity: 'requirement', subject: 'InverterCommunication' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cfg.is_inverter_solar_powered) {
|
if (!cfg.is_inverter_solar_powered) {
|
||||||
if (!meta.charge_controller_enabled) {
|
if (!meta.charge_controller_enabled) {
|
||||||
hints.push({severity: "optional", subject: "NoChargeController"});
|
hints.push({ severity: 'optional', subject: 'NoChargeController' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!meta.battery_enabled) {
|
if (!meta.battery_enabled) {
|
||||||
hints.push({severity: "optional", subject: "NoBatteryInterface"});
|
hints.push({ severity: 'optional', subject: 'NoBatteryInterface' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +497,9 @@ export default defineComponent({
|
|||||||
const cfg = this.powerLimiterConfigList;
|
const cfg = this.powerLimiterConfigList;
|
||||||
const meta = this.powerLimiterMetaData;
|
const meta = this.powerLimiterMetaData;
|
||||||
const canUse = this.isEnabled() && meta.charge_controller_enabled && !cfg.is_inverter_solar_powered;
|
const canUse = this.isEnabled() && meta.charge_controller_enabled && !cfg.is_inverter_solar_powered;
|
||||||
if (!canUse) { cfg.solar_passthrough_enabled = false; }
|
if (!canUse) {
|
||||||
|
cfg.solar_passthrough_enabled = false;
|
||||||
|
}
|
||||||
return canUse;
|
return canUse;
|
||||||
},
|
},
|
||||||
canUseSoCThresholds() {
|
canUseSoCThresholds() {
|
||||||
@ -345,17 +521,23 @@ export default defineComponent({
|
|||||||
const cfg = this.powerLimiterConfigList;
|
const cfg = this.powerLimiterConfigList;
|
||||||
const meta = this.powerLimiterMetaData;
|
const meta = this.powerLimiterMetaData;
|
||||||
|
|
||||||
const reset = function() {
|
const reset = function () {
|
||||||
cfg.inverter_channel_id = 0;
|
cfg.inverter_channel_id = 0;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (cfg.inverter_serial === '') { return reset(); }
|
if (cfg.inverter_serial === '') {
|
||||||
|
return reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg.is_inverter_solar_powered) { return reset(); }
|
if (cfg.is_inverter_solar_powered) {
|
||||||
|
return reset();
|
||||||
|
}
|
||||||
|
|
||||||
const inverter = meta.inverters[cfg.inverter_serial];
|
const inverter = meta.inverters[cfg.inverter_serial];
|
||||||
if (inverter === undefined) { return reset(); }
|
if (inverter === undefined) {
|
||||||
|
return reset();
|
||||||
|
}
|
||||||
|
|
||||||
if (cfg.inverter_channel_id >= inverter.channels) {
|
if (cfg.inverter_channel_id >= inverter.channels) {
|
||||||
reset();
|
reset();
|
||||||
@ -365,11 +547,11 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
getAllData() {
|
getAllData() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/powerlimiter/metadata", { headers: authHeader() })
|
fetch('/api/powerlimiter/metadata', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.powerLimiterMetaData = data;
|
this.powerLimiterMetaData = data;
|
||||||
fetch("/api/powerlimiter/config", { headers: authHeader() })
|
fetch('/api/powerlimiter/config', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.powerLimiterConfigList = data;
|
this.powerLimiterConfigList = data;
|
||||||
@ -381,21 +563,19 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.powerLimiterConfigList));
|
formData.append('data', JSON.stringify(this.powerLimiterConfigList));
|
||||||
|
|
||||||
fetch("/api/powerlimiter/config", {
|
fetch('/api/powerlimiter/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.alertMessage = response.message;
|
this.alertMessage = response.message;
|
||||||
this.alertType = response.type;
|
this.alertType = response.type;
|
||||||
this.showAlert = true;
|
this.showAlert = true;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,20 +5,26 @@
|
|||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
|
|
||||||
<form @submit="savePowerMeterConfig">
|
<form @submit="savePowerMeterConfig">
|
||||||
<CardElement :text="$t('powermeteradmin.PowerMeterConfiguration')"
|
<CardElement :text="$t('powermeteradmin.PowerMeterConfiguration')" textVariant="text-bg-primary">
|
||||||
textVariant="text-bg-primary">
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.PowerMeterEnable')"
|
||||||
<InputElement :label="$t('powermeteradmin.PowerMeterEnable')"
|
|
||||||
v-model="powerMeterConfigList.enabled"
|
v-model="powerMeterConfigList.enabled"
|
||||||
type="checkbox" wide />
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement v-show="powerMeterConfigList.enabled"
|
<InputElement
|
||||||
|
v-show="powerMeterConfigList.enabled"
|
||||||
:label="$t('powermeteradmin.VerboseLogging')"
|
:label="$t('powermeteradmin.VerboseLogging')"
|
||||||
v-model="powerMeterConfigList.verbose_logging"
|
v-model="powerMeterConfigList.verbose_logging"
|
||||||
type="checkbox" wide />
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3" v-show="powerMeterConfigList.enabled">
|
<div class="row mb-3" v-show="powerMeterConfigList.enabled">
|
||||||
<label for="inputPowerMeterSource" class="col-sm-4 col-form-label">{{ $t('powermeteradmin.PowerMeterSource') }}</label>
|
<label for="inputPowerMeterSource" class="col-sm-4 col-form-label">{{
|
||||||
|
$t('powermeteradmin.PowerMeterSource')
|
||||||
|
}}</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
<select id="inputPowerMeterSource" class="form-select" v-model="powerMeterConfigList.source">
|
<select id="inputPowerMeterSource" class="form-select" v-model="powerMeterConfigList.source">
|
||||||
<option v-for="source in powerMeterSourceList" :key="source.key" :value="source.key">
|
<option v-for="source in powerMeterSourceList" :key="source.key" :value="source.key">
|
||||||
@ -35,8 +41,20 @@
|
|||||||
<h2>{{ $t('powermeteradmin.jsonPathExamplesHeading') }}:</h2>
|
<h2>{{ $t('powermeteradmin.jsonPathExamplesHeading') }}:</h2>
|
||||||
{{ $t('powermeteradmin.jsonPathExamplesExplanation') }}
|
{{ $t('powermeteradmin.jsonPathExamplesExplanation') }}
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>power/total/watts</code> — <code>{ "power": { "phase1": { "factor": 0.98, "watts": 42 }, "total": { "watts": 123.4 } } }</code></li>
|
<li>
|
||||||
<li><code>data/[1]/power</code> — <code>{ "data": [ { "factor": 0.98, "power": 42 }, { "factor": 1.0, "power": 123.4 } ] } }</code></li>
|
<code>power/total/watts</code> —
|
||||||
|
<code
|
||||||
|
>{ "power": { "phase1": { "factor": 0.98, "watts": 42 }, "total": { "watts": 123.4 }
|
||||||
|
} }</code
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>data/[1]/power</code> —
|
||||||
|
<code
|
||||||
|
>{ "data": [ { "factor": 0.98, "power": 42 }, { "factor": 1.0, "power": 123.4 } ] }
|
||||||
|
}</code
|
||||||
|
>
|
||||||
|
</li>
|
||||||
<li><code>total</code> — <code>{ "othervalue": 66, "total": 123.4 }</code></li>
|
<li><code>total</code> — <code>{ "othervalue": 66, "total": 123.4 }</code></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -45,23 +63,28 @@
|
|||||||
<!-- yarn linter wants us to not combine v-if with v-for, so we need to wrap the CardElements //-->
|
<!-- yarn linter wants us to not combine v-if with v-for, so we need to wrap the CardElements //-->
|
||||||
<div v-if="powerMeterConfigList.source === 0">
|
<div v-if="powerMeterConfigList.source === 0">
|
||||||
<CardElement
|
<CardElement
|
||||||
v-for="(mqtt, index) in powerMeterConfigList.mqtt.values" v-bind:key="index"
|
v-for="(mqtt, index) in powerMeterConfigList.mqtt.values"
|
||||||
:text="$t('powermeteradmin.MqttValue', { valueNumber: index + 1})"
|
v-bind:key="index"
|
||||||
|
:text="$t('powermeteradmin.MqttValue', { valueNumber: index + 1 })"
|
||||||
textVariant="text-bg-primary"
|
textVariant="text-bg-primary"
|
||||||
add-space>
|
add-space
|
||||||
|
>
|
||||||
<InputElement :label="$t('powermeteradmin.MqttTopic')"
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.MqttTopic')"
|
||||||
v-model="mqtt.topic"
|
v-model="mqtt.topic"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256"
|
maxlength="256"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powermeteradmin.mqttJsonPath')"
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.mqttJsonPath')"
|
||||||
v-model="mqtt.json_path"
|
v-model="mqtt.json_path"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256"
|
maxlength="256"
|
||||||
:tooltip="$t('powermeteradmin.valueJsonPathDescription')"
|
:tooltip="$t('powermeteradmin.valueJsonPathDescription')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="mqtt_power_unit" class="col-sm-4 col-form-label">
|
<label for="mqtt_power_unit" class="col-sm-4 col-form-label">
|
||||||
@ -81,27 +104,33 @@
|
|||||||
v-model="mqtt.sign_inverted"
|
v-model="mqtt.sign_inverted"
|
||||||
:tooltip="$t('powermeteradmin.valueSignInvertedHint')"
|
:tooltip="$t('powermeteradmin.valueSignInvertedHint')"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CardElement v-if="(powerMeterConfigList.source === 1 || powerMeterConfigList.source === 2)"
|
<CardElement
|
||||||
|
v-if="powerMeterConfigList.source === 1 || powerMeterConfigList.source === 2"
|
||||||
:text="$t('powermeteradmin.SDM')"
|
:text="$t('powermeteradmin.SDM')"
|
||||||
textVariant="text-bg-primary"
|
textVariant="text-bg-primary"
|
||||||
add-space>
|
add-space
|
||||||
|
>
|
||||||
<InputElement :label="$t('powermeteradmin.pollingInterval')"
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.pollingInterval')"
|
||||||
v-model="powerMeterConfigList.serial_sdm.polling_interval"
|
v-model="powerMeterConfigList.serial_sdm.polling_interval"
|
||||||
type="number"
|
type="number"
|
||||||
min=1
|
min="1"
|
||||||
max=15
|
max="15"
|
||||||
:postfix="$t('powermeteradmin.seconds')"
|
:postfix="$t('powermeteradmin.seconds')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powermeteradmin.sdmaddress')"
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.sdmaddress')"
|
||||||
v-model="powerMeterConfigList.serial_sdm.address"
|
v-model="powerMeterConfigList.serial_sdm.address"
|
||||||
type="number"
|
type="number"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<div v-if="powerMeterConfigList.source === 3">
|
<div v-if="powerMeterConfigList.source === 3">
|
||||||
@ -115,21 +144,23 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CardElement :text="$t('powermeteradmin.HTTP')"
|
<CardElement :text="$t('powermeteradmin.HTTP')" textVariant="text-bg-primary" add-space>
|
||||||
textVariant="text-bg-primary"
|
<InputElement
|
||||||
add-space>
|
:label="$t('powermeteradmin.httpIndividualRequests')"
|
||||||
<InputElement :label="$t('powermeteradmin.httpIndividualRequests')"
|
|
||||||
v-model="powerMeterConfigList.http_json.individual_requests"
|
v-model="powerMeterConfigList.http_json.individual_requests"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('powermeteradmin.pollingInterval')"
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.pollingInterval')"
|
||||||
v-model="powerMeterConfigList.http_json.polling_interval"
|
v-model="powerMeterConfigList.http_json.polling_interval"
|
||||||
type="number"
|
type="number"
|
||||||
min=1
|
min="1"
|
||||||
max=15
|
max="15"
|
||||||
:postfix="$t('powermeteradmin.seconds')"
|
:postfix="$t('powermeteradmin.seconds')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement
|
<CardElement
|
||||||
@ -137,23 +168,30 @@
|
|||||||
:key="index"
|
:key="index"
|
||||||
:text="$t('powermeteradmin.httpValue', { valueNumber: index + 1 })"
|
:text="$t('powermeteradmin.httpValue', { valueNumber: index + 1 })"
|
||||||
textVariant="text-bg-primary"
|
textVariant="text-bg-primary"
|
||||||
add-space>
|
add-space
|
||||||
|
>
|
||||||
<InputElement
|
<InputElement
|
||||||
v-if="index > 0"
|
v-if="index > 0"
|
||||||
:label="$t('powermeteradmin.httpEnabled')"
|
:label="$t('powermeteradmin.httpEnabled')"
|
||||||
v-model="httpJson.enabled"
|
v-model="httpJson.enabled"
|
||||||
type="checkbox" wide />
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div v-if="httpJson.enabled || index == 0">
|
<div v-if="httpJson.enabled || index == 0">
|
||||||
|
<HttpRequestSettings
|
||||||
|
v-model="httpJson.http_request"
|
||||||
|
v-if="index == 0 || powerMeterConfigList.http_json.individual_requests"
|
||||||
|
/>
|
||||||
|
|
||||||
<HttpRequestSettings v-model="httpJson.http_request" v-if="index == 0 || powerMeterConfigList.http_json.individual_requests"/>
|
<InputElement
|
||||||
|
:label="$t('powermeteradmin.valueJsonPath')"
|
||||||
<InputElement :label="$t('powermeteradmin.valueJsonPath')"
|
|
||||||
v-model="httpJson.json_path"
|
v-model="httpJson.json_path"
|
||||||
type="text"
|
type="text"
|
||||||
maxlength="256"
|
maxlength="256"
|
||||||
:tooltip="$t('powermeteradmin.valueJsonPathDescription')"
|
:tooltip="$t('powermeteradmin.valueJsonPathDescription')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<label for="power_unit" class="col-sm-4 col-form-label">
|
<label for="power_unit" class="col-sm-4 col-form-label">
|
||||||
@ -173,39 +211,43 @@
|
|||||||
v-model="httpJson.sign_inverted"
|
v-model="httpJson.sign_inverted"
|
||||||
:tooltip="$t('powermeteradmin.valueSignInvertedHint')"
|
:tooltip="$t('powermeteradmin.valueSignInvertedHint')"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement
|
<CardElement
|
||||||
:text="$t('powermeteradmin.testHttpJsonHeader')"
|
:text="$t('powermeteradmin.testHttpJsonHeader')"
|
||||||
textVariant="text-bg-primary"
|
textVariant="text-bg-primary"
|
||||||
add-space>
|
add-space
|
||||||
|
>
|
||||||
<div class="text-center mt-3 mb-3">
|
<div class="text-center mt-3 mb-3">
|
||||||
<button type="button" class="btn btn-primary" @click="testHttpJsonRequest()">
|
<button type="button" class="btn btn-primary" @click="testHttpJsonRequest()">
|
||||||
{{ $t('powermeteradmin.testHttpJsonRequest') }}
|
{{ $t('powermeteradmin.testHttpJsonRequest') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BootstrapAlert v-model="testHttpJsonRequestAlert.show" dismissible :variant="testHttpJsonRequestAlert.type">
|
<BootstrapAlert
|
||||||
|
v-model="testHttpJsonRequestAlert.show"
|
||||||
|
dismissible
|
||||||
|
:variant="testHttpJsonRequestAlert.type"
|
||||||
|
>
|
||||||
{{ testHttpJsonRequestAlert.message }}
|
{{ testHttpJsonRequestAlert.message }}
|
||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="powerMeterConfigList.source === 6">
|
<div v-if="powerMeterConfigList.source === 6">
|
||||||
<CardElement :text="$t('powermeteradmin.HTTP_SML')"
|
<CardElement :text="$t('powermeteradmin.HTTP_SML')" textVariant="text-bg-primary" add-space>
|
||||||
textVariant="text-bg-primary"
|
<InputElement
|
||||||
add-space>
|
:label="$t('powermeteradmin.pollingInterval')"
|
||||||
|
|
||||||
<InputElement :label="$t('powermeteradmin.pollingInterval')"
|
|
||||||
v-model="powerMeterConfigList.http_sml.polling_interval"
|
v-model="powerMeterConfigList.http_sml.polling_interval"
|
||||||
type="number"
|
type="number"
|
||||||
min=1
|
min="1"
|
||||||
max=15
|
max="15"
|
||||||
:postfix="$t('powermeteradmin.seconds')"
|
:postfix="$t('powermeteradmin.seconds')"
|
||||||
wide />
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<HttpRequestSettings v-model="powerMeterConfigList.http_sml.http_request" />
|
<HttpRequestSettings v-model="powerMeterConfigList.http_sml.http_request" />
|
||||||
</CardElement>
|
</CardElement>
|
||||||
@ -213,23 +255,26 @@
|
|||||||
<CardElement
|
<CardElement
|
||||||
:text="$t('powermeteradmin.testHttpSmlHeader')"
|
:text="$t('powermeteradmin.testHttpSmlHeader')"
|
||||||
textVariant="text-bg-primary"
|
textVariant="text-bg-primary"
|
||||||
add-space>
|
add-space
|
||||||
|
>
|
||||||
<div class="text-center mt-3 mb-3">
|
<div class="text-center mt-3 mb-3">
|
||||||
<button type="button" class="btn btn-primary" @click="testHttpSmlRequest()">
|
<button type="button" class="btn btn-primary" @click="testHttpSmlRequest()">
|
||||||
{{ $t('powermeteradmin.testHttpSmlRequest') }}
|
{{ $t('powermeteradmin.testHttpSmlRequest') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BootstrapAlert v-model="testHttpSmlRequestAlert.show" dismissible :variant="testHttpSmlRequestAlert.type">
|
<BootstrapAlert
|
||||||
|
v-model="testHttpSmlRequestAlert.show"
|
||||||
|
dismissible
|
||||||
|
:variant="testHttpSmlRequestAlert.type"
|
||||||
|
>
|
||||||
{{ testHttpSmlRequestAlert.message }}
|
{{ testHttpSmlRequestAlert.message }}
|
||||||
</BootstrapAlert>
|
</BootstrapAlert>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<FormFooter @reload="getPowerMeterConfig"/>
|
<FormFooter @reload="getPowerMeterConfig" />
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
@ -237,13 +282,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import FormFooter from '@/components/FormFooter.vue';
|
import FormFooter from '@/components/FormFooter.vue';
|
||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
import HttpRequestSettings from '@/components/HttpRequestSettings.vue';
|
import HttpRequestSettings from '@/components/HttpRequestSettings.vue';
|
||||||
import { handleResponse, authHeader } from '@/utils/authentication';
|
import { handleResponse, authHeader } from '@/utils/authentication';
|
||||||
import type { PowerMeterConfig } from "@/types/PowerMeterConfig";
|
import type { PowerMeterConfig } from '@/types/PowerMeterConfig';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
@ -252,7 +297,7 @@ export default defineComponent({
|
|||||||
CardElement,
|
CardElement,
|
||||||
FormFooter,
|
FormFooter,
|
||||||
HttpRequestSettings,
|
HttpRequestSettings,
|
||||||
InputElement
|
InputElement,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -268,15 +313,23 @@ export default defineComponent({
|
|||||||
{ key: 6, value: this.$t('powermeteradmin.typeHTTP_SML') },
|
{ key: 6, value: this.$t('powermeteradmin.typeHTTP_SML') },
|
||||||
],
|
],
|
||||||
unitTypeList: [
|
unitTypeList: [
|
||||||
{ key: 1, value: "mW" },
|
{ key: 1, value: 'mW' },
|
||||||
{ key: 0, value: "W" },
|
{ key: 0, value: 'W' },
|
||||||
{ key: 2, value: "kW" },
|
{ key: 2, value: 'kW' },
|
||||||
],
|
],
|
||||||
alertMessage: "",
|
alertMessage: '',
|
||||||
alertType: "info",
|
alertType: 'info',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
testHttpJsonRequestAlert: {message: "", type: "", show: false} as { message: string; type: string; show: boolean; },
|
testHttpJsonRequestAlert: { message: '', type: '', show: false } as {
|
||||||
testHttpSmlRequestAlert: {message: "", type: "", show: false} as { message: string; type: string; show: boolean; }
|
message: string;
|
||||||
|
type: string;
|
||||||
|
show: boolean;
|
||||||
|
},
|
||||||
|
testHttpSmlRequestAlert: { message: '', type: '', show: false } as {
|
||||||
|
message: string;
|
||||||
|
type: string;
|
||||||
|
show: boolean;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -285,7 +338,7 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
getPowerMeterConfig() {
|
getPowerMeterConfig() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/powermeter/config", { headers: authHeader() })
|
fetch('/api/powermeter/config', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.powerMeterConfigList = data;
|
this.powerMeterConfigList = data;
|
||||||
@ -296,74 +349,68 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.powerMeterConfigList));
|
formData.append('data', JSON.stringify(this.powerMeterConfigList));
|
||||||
|
|
||||||
fetch("/api/powermeter/config", {
|
fetch('/api/powermeter/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.alertMessage = response.message;
|
this.alertMessage = response.message;
|
||||||
this.alertType = response.type;
|
this.alertType = response.type;
|
||||||
this.showAlert = true;
|
this.showAlert = true;
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
testHttpJsonRequest() {
|
testHttpJsonRequest() {
|
||||||
this.testHttpJsonRequestAlert = {
|
this.testHttpJsonRequestAlert = {
|
||||||
message: "Triggering HTTP request...",
|
message: 'Triggering HTTP request...',
|
||||||
type: "info",
|
type: 'info',
|
||||||
show: true,
|
show: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.powerMeterConfigList));
|
formData.append('data', JSON.stringify(this.powerMeterConfigList));
|
||||||
|
|
||||||
fetch("/api/powermeter/testhttpjsonrequest", {
|
fetch('/api/powermeter/testhttpjsonrequest', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.testHttpJsonRequestAlert = {
|
this.testHttpJsonRequestAlert = {
|
||||||
message: response.message,
|
message: response.message,
|
||||||
type: response.type,
|
type: response.type,
|
||||||
show: true,
|
show: true,
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
)
|
|
||||||
},
|
},
|
||||||
testHttpSmlRequest() {
|
testHttpSmlRequest() {
|
||||||
this.testHttpSmlRequestAlert = {
|
this.testHttpSmlRequestAlert = {
|
||||||
message: "Triggering HTTP request...",
|
message: 'Triggering HTTP request...',
|
||||||
type: "info",
|
type: 'info',
|
||||||
show: true,
|
show: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.powerMeterConfigList));
|
formData.append('data', JSON.stringify(this.powerMeterConfigList));
|
||||||
|
|
||||||
fetch("/api/powermeter/testhttpsmlrequest", {
|
fetch('/api/powermeter/testhttpsmlrequest', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.testHttpSmlRequestAlert = {
|
this.testHttpSmlRequestAlert = {
|
||||||
message: response.message,
|
message: response.message,
|
||||||
type: response.type,
|
type: response.type,
|
||||||
show: true,
|
show: true,
|
||||||
};
|
};
|
||||||
}
|
});
|
||||||
)
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -77,7 +77,9 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fetchUrl =
|
const fetchUrl =
|
||||||
'https://api.github.com/repos/helgeerbe/OpenDTU-OnBattery/compare/' + this.systemDataList.git_hash + '...HEAD';
|
'https://api.github.com/repos/helgeerbe/OpenDTU-OnBattery/compare/' +
|
||||||
|
this.systemDataList.git_hash +
|
||||||
|
'...HEAD';
|
||||||
|
|
||||||
fetch(fetchUrl)
|
fetch(fetchUrl)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
|
|||||||
@ -6,35 +6,47 @@
|
|||||||
|
|
||||||
<form @submit="saveVedirectConfig">
|
<form @submit="saveVedirectConfig">
|
||||||
<CardElement :text="$t('vedirectadmin.VedirectConfiguration')" textVariant="text-bg-primary">
|
<CardElement :text="$t('vedirectadmin.VedirectConfiguration')" textVariant="text-bg-primary">
|
||||||
<InputElement :label="$t('vedirectadmin.EnableVedirect')"
|
<InputElement
|
||||||
|
:label="$t('vedirectadmin.EnableVedirect')"
|
||||||
v-model="vedirectConfigList.vedirect_enabled"
|
v-model="vedirectConfigList.vedirect_enabled"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<CardElement :text="$t('vedirectadmin.VedirectParameter')" textVariant="text-bg-primary" add-space
|
<CardElement
|
||||||
v-show="vedirectConfigList.vedirect_enabled">
|
:text="$t('vedirectadmin.VedirectParameter')"
|
||||||
|
textVariant="text-bg-primary"
|
||||||
<InputElement :label="$t('vedirectadmin.VerboseLogging')"
|
add-space
|
||||||
|
v-show="vedirectConfigList.vedirect_enabled"
|
||||||
|
>
|
||||||
|
<InputElement
|
||||||
|
:label="$t('vedirectadmin.VerboseLogging')"
|
||||||
v-model="vedirectConfigList.verbose_logging"
|
v-model="vedirectConfigList.verbose_logging"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
|
|
||||||
<InputElement :label="$t('vedirectadmin.UpdatesOnly')"
|
<InputElement
|
||||||
|
:label="$t('vedirectadmin.UpdatesOnly')"
|
||||||
v-model="vedirectConfigList.vedirect_updatesonly"
|
v-model="vedirectConfigList.vedirect_updatesonly"
|
||||||
type="checkbox" wide/>
|
type="checkbox"
|
||||||
|
wide
|
||||||
|
/>
|
||||||
</CardElement>
|
</CardElement>
|
||||||
|
|
||||||
<FormFooter @reload="getVedirectConfig"/>
|
<FormFooter @reload="getVedirectConfig" />
|
||||||
</form>
|
</form>
|
||||||
</BasePage>
|
</BasePage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
import BootstrapAlert from '@/components/BootstrapAlert.vue';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import FormFooter from '@/components/FormFooter.vue';
|
import FormFooter from '@/components/FormFooter.vue';
|
||||||
import InputElement from '@/components/InputElement.vue';
|
import InputElement from '@/components/InputElement.vue';
|
||||||
import type { VedirectConfig } from "@/types/VedirectConfig";
|
import type { VedirectConfig } from '@/types/VedirectConfig';
|
||||||
import { authHeader, handleResponse } from '@/utils/authentication';
|
import { authHeader, handleResponse } from '@/utils/authentication';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
@ -50,8 +62,8 @@ export default defineComponent({
|
|||||||
return {
|
return {
|
||||||
dataLoading: true,
|
dataLoading: true,
|
||||||
vedirectConfigList: {} as VedirectConfig,
|
vedirectConfigList: {} as VedirectConfig,
|
||||||
alertMessage: "",
|
alertMessage: '',
|
||||||
alertType: "info",
|
alertType: 'info',
|
||||||
showAlert: false,
|
showAlert: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -61,7 +73,7 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
getVedirectConfig() {
|
getVedirectConfig() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/vedirect/config", { headers: authHeader() })
|
fetch('/api/vedirect/config', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.vedirectConfigList = data;
|
this.vedirectConfigList = data;
|
||||||
@ -72,21 +84,19 @@ export default defineComponent({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("data", JSON.stringify(this.vedirectConfigList));
|
formData.append('data', JSON.stringify(this.vedirectConfigList));
|
||||||
|
|
||||||
fetch("/api/vedirect/config", {
|
fetch('/api/vedirect/config', {
|
||||||
method: "POST",
|
method: 'POST',
|
||||||
headers: authHeader(),
|
headers: authHeader(),
|
||||||
body: formData,
|
body: formData,
|
||||||
})
|
})
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then(
|
.then((response) => {
|
||||||
(response) => {
|
|
||||||
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
this.alertMessage = this.$t('apiresponse.' + response.code, response.param);
|
||||||
this.alertType = response.type;
|
this.alertType = response.type;
|
||||||
this.showAlert = true;
|
this.showAlert = true;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,19 +7,31 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('vedirectinfo.Status') }}</th>
|
<th>{{ $t('vedirectinfo.Status') }}</th>
|
||||||
<td>
|
<td>
|
||||||
<StatusBadge :status="vedirectDataList.vedirect_enabled" true_text="vedirectinfo.Enabled" false_text="vedirectinfo.Disabled" />
|
<StatusBadge
|
||||||
|
:status="vedirectDataList.vedirect_enabled"
|
||||||
|
true_text="vedirectinfo.Enabled"
|
||||||
|
false_text="vedirectinfo.Disabled"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('vedirectinfo.VerboseLogging') }}</th>
|
<th>{{ $t('vedirectinfo.VerboseLogging') }}</th>
|
||||||
<td>
|
<td>
|
||||||
<StatusBadge :status="vedirectDataList.verbose_logging" true_text="vedirectinfo.Enabled" false_text="vedirectinfo.Disabled" />
|
<StatusBadge
|
||||||
|
:status="vedirectDataList.verbose_logging"
|
||||||
|
true_text="vedirectinfo.Enabled"
|
||||||
|
false_text="vedirectinfo.Disabled"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ $t('vedirectinfo.UpdatesOnly') }}</th>
|
<th>{{ $t('vedirectinfo.UpdatesOnly') }}</th>
|
||||||
<td>
|
<td>
|
||||||
<StatusBadge :status="vedirectDataList.vedirect_updatesonly" true_text="vedirectinfo.UpdatesEnabled" false_text="vedirectinfo.UpdatesDisabled" />
|
<StatusBadge
|
||||||
|
:status="vedirectDataList.vedirect_updatesonly"
|
||||||
|
true_text="vedirectinfo.UpdatesEnabled"
|
||||||
|
false_text="vedirectinfo.UpdatesDisabled"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -33,7 +45,7 @@
|
|||||||
import BasePage from '@/components/BasePage.vue';
|
import BasePage from '@/components/BasePage.vue';
|
||||||
import CardElement from '@/components/CardElement.vue';
|
import CardElement from '@/components/CardElement.vue';
|
||||||
import StatusBadge from '@/components/StatusBadge.vue';
|
import StatusBadge from '@/components/StatusBadge.vue';
|
||||||
import type { VedirectStatus } from "@/types/VedirectStatus";
|
import type { VedirectStatus } from '@/types/VedirectStatus';
|
||||||
import { authHeader, handleResponse } from '@/utils/authentication';
|
import { authHeader, handleResponse } from '@/utils/authentication';
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
@ -41,7 +53,7 @@ export default defineComponent({
|
|||||||
components: {
|
components: {
|
||||||
BasePage,
|
BasePage,
|
||||||
CardElement,
|
CardElement,
|
||||||
StatusBadge
|
StatusBadge,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -55,7 +67,7 @@ export default defineComponent({
|
|||||||
methods: {
|
methods: {
|
||||||
getVedirectInfo() {
|
getVedirectInfo() {
|
||||||
this.dataLoading = true;
|
this.dataLoading = true;
|
||||||
fetch("/api/vedirect/status", { headers: authHeader() })
|
fetch('/api/vedirect/status', { headers: authHeader() })
|
||||||
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
.then((response) => handleResponse(response, this.$emitter, this.$router))
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.vedirectDataList = data;
|
this.vedirectDataList = data;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user