Added device reboot functionality
This commit is contained in:
parent
8ba0a654a3
commit
e60619b867
@ -8,6 +8,7 @@
|
||||
#include "WebApi_firmware.h"
|
||||
#include "WebApi_inverter.h"
|
||||
#include "WebApi_limit.h"
|
||||
#include "WebApi_maintenance.h"
|
||||
#include "WebApi_mqtt.h"
|
||||
#include "WebApi_network.h"
|
||||
#include "WebApi_ntp.h"
|
||||
@ -38,6 +39,7 @@ private:
|
||||
WebApiFirmwareClass _webApiFirmware;
|
||||
WebApiInverterClass _webApiInverter;
|
||||
WebApiLimitClass _webApiLimit;
|
||||
WebApiMaintenanceClass _webApiMaintenance;
|
||||
WebApiMqttClass _webApiMqtt;
|
||||
WebApiNetworkClass _webApiNetwork;
|
||||
WebApiNtpClass _webApiNtp;
|
||||
|
||||
15
include/WebApi_maintenance.h
Normal file
15
include/WebApi_maintenance.h
Normal file
@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
|
||||
class WebApiMaintenanceClass {
|
||||
public:
|
||||
void init(AsyncWebServer* server);
|
||||
void loop();
|
||||
|
||||
private:
|
||||
void onRebootPost(AsyncWebServerRequest* request);
|
||||
|
||||
AsyncWebServer* _server;
|
||||
};
|
||||
@ -25,6 +25,7 @@ void WebApiClass::init()
|
||||
_webApiFirmware.init(&_server);
|
||||
_webApiInverter.init(&_server);
|
||||
_webApiLimit.init(&_server);
|
||||
_webApiMaintenance.init(&_server);
|
||||
_webApiMqtt.init(&_server);
|
||||
_webApiNetwork.init(&_server);
|
||||
_webApiNtp.init(&_server);
|
||||
@ -47,6 +48,7 @@ void WebApiClass::loop()
|
||||
_webApiFirmware.loop();
|
||||
_webApiInverter.loop();
|
||||
_webApiLimit.loop();
|
||||
_webApiMaintenance.loop();
|
||||
_webApiMqtt.loop();
|
||||
_webApiNetwork.loop();
|
||||
_webApiNtp.loop();
|
||||
|
||||
82
src/WebApi_maintenance.cpp
Normal file
82
src/WebApi_maintenance.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (C) 2022 Thomas Basler and others
|
||||
*/
|
||||
|
||||
#include "WebApi_maintenance.h"
|
||||
#include "AsyncJson.h"
|
||||
#include "WebApi.h"
|
||||
|
||||
void WebApiMaintenanceClass::init(AsyncWebServer* server)
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
|
||||
_server = server;
|
||||
|
||||
_server->on("/api/maintenance/reboot", HTTP_POST, std::bind(&WebApiMaintenanceClass::onRebootPost, this, _1));
|
||||
}
|
||||
|
||||
void WebApiMaintenanceClass::loop()
|
||||
{
|
||||
}
|
||||
|
||||
void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (!WebApi.checkCredentials(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE);
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > MQTT_JSON_DOC_SIZE) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument root(MQTT_JSON_DOC_SIZE);
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("reboot"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (root[F("reboot")].as<bool>()) {
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Reboot triggered!");
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
yield();
|
||||
delay(1000);
|
||||
yield();
|
||||
ESP.restart();
|
||||
} else {
|
||||
retMsg[F("message")] = F("Reboot cancled!");
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
}
|
||||
@ -46,6 +46,9 @@
|
||||
<li>
|
||||
<router-link @click="onClick" class="dropdown-item" to="/firmware/upgrade">Firmware Upgrade</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link @click="onClick" class="dropdown-item" to="/maintenance/reboot">Device Reboot</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
|
||||
@ -14,6 +14,7 @@ import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue'
|
||||
import ConfigAdminView from '@/views/ConfigAdminView.vue'
|
||||
import SecurityAdminView from '@/views/SecurityAdminView.vue'
|
||||
import LoginView from '@/views/LoginView.vue'
|
||||
import MaintenanceRebootView from '@/views/MaintenanceRebootView.vue';
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@ -93,6 +94,11 @@ const router = createRouter({
|
||||
path: '/settings/security',
|
||||
name: 'Security',
|
||||
component: SecurityAdminView
|
||||
},
|
||||
{
|
||||
path: '/maintenance/reboot',
|
||||
name: 'Device Reboot',
|
||||
component: MaintenanceRebootView
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
97
webapp/src/views/MaintenanceRebootView.vue
Normal file
97
webapp/src/views/MaintenanceRebootView.vue
Normal file
@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<BasePage :title="'Device Reboot'" :isLoading="dataLoading">
|
||||
<BootstrapAlert v-model="showAlert" dismissible :variant="alertType">
|
||||
{{ alertMessage }}
|
||||
</BootstrapAlert>
|
||||
|
||||
<div class="card mt-5">
|
||||
<div class="card-header text-bg-primary">Perform Reboot</div>
|
||||
<div class="card-body text-center">
|
||||
|
||||
<button class="btn btn-danger" @click="onOpenModal(performReboot)">Reboot!
|
||||
</button>
|
||||
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<b>Note:</b> A manual reboot does not normally have to be performed. OpenDTU performs any required
|
||||
reboot (e.g. after a firmware update) automatically. Settings are also adopted without rebooting. If
|
||||
you need to reboot due to an error, please consider reporting it at <a
|
||||
href="https://github.com/tbnobody/OpenDTU/issues" class="alert-link"
|
||||
target="_blank">https://github.com/tbnobody/OpenDTU/issues</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BasePage>
|
||||
|
||||
<div class="modal" id="performReboot" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Reboot OpenDTU</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Do you really want to reboot the device?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @click="onCloseModal(performReboot)"
|
||||
data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger" @click="onReboot">Reboot</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import * as bootstrap from 'bootstrap';
|
||||
import BasePage from '@/components/BasePage.vue';
|
||||
import BootstrapAlert from "@/components/BootstrapAlert.vue";
|
||||
import { handleResponse, authHeader } from '@/utils/authentication';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
BasePage,
|
||||
BootstrapAlert,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
performReboot: {} as bootstrap.Modal,
|
||||
|
||||
dataLoading: false,
|
||||
|
||||
alertMessage: "",
|
||||
alertType: "info",
|
||||
showAlert: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.performReboot = new bootstrap.Modal('#performReboot');
|
||||
},
|
||||
methods: {
|
||||
onReboot() {
|
||||
const formData = new FormData();
|
||||
formData.append("data", JSON.stringify({ reboot: true }));
|
||||
|
||||
fetch("/api/maintenance/reboot", {
|
||||
method: "POST",
|
||||
headers: authHeader(),
|
||||
body: formData,
|
||||
})
|
||||
.then((response) => handleResponse(response, this.$emitter))
|
||||
.then((data) => {
|
||||
this.alertMessage = data.message;
|
||||
this.alertType = data.type;
|
||||
this.showAlert = true;
|
||||
});
|
||||
this.onCloseModal(this.performReboot);
|
||||
},
|
||||
onOpenModal(modal: bootstrap.Modal) {
|
||||
modal.show();
|
||||
},
|
||||
onCloseModal(modal: bootstrap.Modal) {
|
||||
modal.hide();
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
Loading…
Reference in New Issue
Block a user