diff --git a/README.md b/README.md
index b8ec39b85..cda5fd7ea 100644
--- a/README.md
+++ b/README.md
@@ -163,6 +163,7 @@ This can be achieved by editing the 'platformio.ini' file and add/change one or
* clean the sources: `platformio run -e generic -t clean`
* erase flash: `platformio run -e generic -t erase`
### using the pre-compiled .bin files
+The pre-compiled files can be found on the [github page](https://github.com/tbnobody/OpenDTU) in the tab "Actions" and the sub menu "OpenDTU Build". Just choose the latest build from the master branch (blue font). You need to be logged in with your github account to download the files.
Use a ESP32 flash tool of your choice and flash the .bin files to the right addresses:
| Address | File |
@@ -172,7 +173,8 @@ Use a ESP32 flash tool of your choice and flash the .bin files to the right addr
| 0xe000 | boot_app0.bin |
| 0x10000 | opendtu-*.bin |
-Make sure too uncheck the DoNotChgBin option. Otherwise you will maybe get errors like "invalid header"
+Make sure too uncheck the DoNotChgBin option. Otherwise you will maybe get errors like "invalid header".
+For further upgraded you can just use the web interface and upload the opendtu-*.bin file.
## First configuration
* After the initial flashing of the microcontroller, an Access Point called "OpenDTU-*" is opened. The default password is "openDTU42".
diff --git a/docs/MQTT_Topics.md b/docs/MQTT_Topics.md
index 7cc1c4183..c9ba54b81 100644
--- a/docs/MQTT_Topics.md
+++ b/docs/MQTT_Topics.md
@@ -39,7 +39,7 @@ serial will be replaced with the serial number of the inverter.
| [serial]/0/temperature | R | Temperature of inverter in degree celsius | Degree Celsius (°C) |
| [serial]/0/voltage | R | AC voltage in volt | Volt (V) |
| [serial]/0/yieldday | R | Energy converted to AC per day in watt hours | Watt hours (Wh) |
-| [serial]/0/yieldtotal | R | Energy converted to AC since reset watt hours | Watt hours (Wh) |
+| [serial]/0/yieldtotal | R | Energy converted to AC since reset watt hours | Watt hours (kWh) |
### DC input channel topics
@@ -52,7 +52,7 @@ serial will be replaced with the serial number of the inverter.
| [serial]/[1-4]/power | R | DC power of specific input in watt | Watt (W) |
| [serial]/[1-4]/voltage | R | DC voltage of specific input in volt | Volt (V) |
| [serial]/[1-4]/yieldday | R | Energy converted to AC per day on specific input | Watt hours (Wh) |
-| [serial]/[1-4]/yieldtotal | R | Energy converted to AC since reset on specific input | Watt hours (Wh) |
+| [serial]/[1-4]/yieldtotal | R | Energy converted to AC since reset on specific input | Watt hours (kWh) |
### Inverter limit specific topics
@@ -69,4 +69,4 @@ cmd topics are used to set values. Status topics are updated from values set in
| [serial]/cmd/limit_nonpersistent_relative | W | Set the inverter limit as a percentage of total production capability. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic immediatly. | % |
| [serial]/cmd/limit_nonpersistent_absolute | W | Set the inverter limit as a absolute value. The value will reset to the last persistent value at night without power. The updated value will show up in the web GUI and limit_relative topic after around 4 minutes. | Watt (W) |
| [serial]/cmd/power | W | Turn the inverter on (1) or off (0) | 0 or 1 |
-| [serial]/cmd/restart | W | Restarts the inverters (also resets YieldDay) | 1 |
\ No newline at end of file
+| [serial]/cmd/restart | W | Restarts the inverters (also resets YieldDay) | 1 |
diff --git a/webapp/.eslintrc.cjs b/webapp/.eslintrc.cjs
new file mode 100644
index 000000000..ade85716e
--- /dev/null
+++ b/webapp/.eslintrc.cjs
@@ -0,0 +1,14 @@
+/* eslint-env node */
+require('@rushstack/eslint-patch/modern-module-resolution')
+
+module.exports = {
+ root: true,
+ 'extends': [
+ 'plugin:vue/vue3-essential',
+ 'eslint:recommended',
+ '@vue/eslint-config-typescript'
+ ],
+ parserOptions: {
+ ecmaVersion: 'latest'
+ }
+}
diff --git a/webapp/.gitignore b/webapp/.gitignore
index 403adbc1e..38adffa64 100644
--- a/webapp/.gitignore
+++ b/webapp/.gitignore
@@ -1,21 +1,26 @@
-.DS_Store
-node_modules
-/dist
-
-
-# local env files
-.env.local
-.env.*.local
-
-# Log files
+# Logs
+logs
+*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+.DS_Store
+dist
+dist-ssr
+coverage
+*.local
+
+/cypress/videos/
+/cypress/screenshots/
# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
.idea
-.vscode
*.suo
*.ntvs*
*.njsproj
diff --git a/webapp/.vscode/extensions.json b/webapp/.vscode/extensions.json
new file mode 100644
index 000000000..c0a6e5a48
--- /dev/null
+++ b/webapp/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
+}
diff --git a/webapp/README.md b/webapp/README.md
index b0a4ed1bf..d7c36533e 100644
--- a/webapp/README.md
+++ b/webapp/README.md
@@ -1,24 +1,25 @@
# opendtu
-## Project setup
-```
+## Project Setup
+
+```sh
yarn install
```
-### Compiles and hot-reloads for development
-```
-yarn serve
-```
+### Compile and Hot-Reload for Development
-### Compiles and minifies for production
+```sh
+yarn dev
```
+
+### Type-Check, Compile and Minify for Production
+
+```sh
yarn build
```
-### Lints and fixes files
-```
-yarn lint
-```
+### Lint with [ESLint](https://eslint.org/)
-### Customize configuration
-See [Configuration Reference](https://cli.vuejs.org/config/).
+```sh
+yarn lint
+```
\ No newline at end of file
diff --git a/webapp/babel.config.js b/webapp/babel.config.js
deleted file mode 100644
index e9558405f..000000000
--- a/webapp/babel.config.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- presets: [
- '@vue/cli-plugin-babel/preset'
- ]
-}
diff --git a/webapp/env.d.ts b/webapp/env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/webapp/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/webapp/index.html b/webapp/index.html
new file mode 100644
index 000000000..36236f188
--- /dev/null
+++ b/webapp/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webapp/src/components/FirmwareInfo.vue b/webapp/src/components/FirmwareInfo.vue
new file mode 100644
index 000000000..385d22b27
--- /dev/null
+++ b/webapp/src/components/FirmwareInfo.vue
@@ -0,0 +1,73 @@
+
+
-
-
-
\ No newline at end of file
diff --git a/webapp/src/components/partials/InterfaceApInfo.vue b/webapp/src/components/InterfaceApInfo.vue
similarity index 69%
rename from webapp/src/components/partials/InterfaceApInfo.vue
rename to webapp/src/components/InterfaceApInfo.vue
index 21c1324b8..adea9810c 100644
--- a/webapp/src/components/partials/InterfaceApInfo.vue
+++ b/webapp/src/components/InterfaceApInfo.vue
@@ -9,11 +9,11 @@
IP Address
-
{{ ap_ip }}
+
{{ networkStatus.ap_ip }}
MAC Address
-
{{ ap_mac }}
+
{{ networkStatus.ap_mac }}
@@ -23,12 +23,12 @@
diff --git a/webapp/src/components/partials/InterfaceNetworkInfo.vue b/webapp/src/components/InterfaceNetworkInfo.vue
similarity index 61%
rename from webapp/src/components/partials/InterfaceNetworkInfo.vue
rename to webapp/src/components/InterfaceNetworkInfo.vue
index c640da57b..dd0902a1c 100644
--- a/webapp/src/components/partials/InterfaceNetworkInfo.vue
+++ b/webapp/src/components/InterfaceNetworkInfo.vue
@@ -1,7 +1,7 @@
-
-
-
\ No newline at end of file
diff --git a/webapp/src/components/NetworkInfoView.vue b/webapp/src/components/NetworkInfoView.vue
deleted file mode 100644
index 4417df65e..000000000
--- a/webapp/src/components/NetworkInfoView.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
Network Info
-
-
-
- Loading...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/webapp/src/components/NtpInfoView.vue b/webapp/src/components/NtpInfoView.vue
deleted file mode 100644
index 41f37c42d..000000000
--- a/webapp/src/components/NtpInfoView.vue
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
-
NTP Info
-
-
-
-
- Loading...
-
-
-
-
-
-
Configuration Summary
-
-
-
-
-
-
Server
-
{{ ntpDataList.ntp_server }}
-
-
-
Timezone
-
{{ ntpDataList.ntp_timezone }}
-
-
-
Timezone Description
-
{{ ntpDataList.ntp_timezone_descr }}
-
-
-
-
-
-
-
-
-
Current Time
-
-
-
-
-
-
Status
-
- synced
- not synced
-
-
-
-
Local Time
-
{{ ntpDataList.ntp_localtime }}
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/webapp/src/components/partials/RadioInfo.vue b/webapp/src/components/RadioInfo.vue
similarity index 50%
rename from webapp/src/components/partials/RadioInfo.vue
rename to webapp/src/components/RadioInfo.vue
index 8250f37b7..03774089a 100644
--- a/webapp/src/components/partials/RadioInfo.vue
+++ b/webapp/src/components/RadioInfo.vue
@@ -10,22 +10,24 @@
-
-
-
\ No newline at end of file
diff --git a/webapp/src/components/partials/VedirectView.vue b/webapp/src/components/VedirectView.vue
similarity index 100%
rename from webapp/src/components/partials/VedirectView.vue
rename to webapp/src/components/VedirectView.vue
diff --git a/webapp/src/components/partials/WifiApInfo.vue b/webapp/src/components/WifiApInfo.vue
similarity index 64%
rename from webapp/src/components/partials/WifiApInfo.vue
rename to webapp/src/components/WifiApInfo.vue
index bdf1eb98e..ee057e57d 100644
--- a/webapp/src/components/partials/WifiApInfo.vue
+++ b/webapp/src/components/WifiApInfo.vue
@@ -10,20 +10,20 @@
Status
- enabled
+ enableddisabled
SSID
-
{{ ap_ssid }}
+
{{ networkStatus.ap_ssid }}
# Stations
-
{{ ap_stationnum }}
+
{{ networkStatus.ap_stationnum }}
@@ -33,13 +33,12 @@
diff --git a/webapp/src/components/partials/WifiStationInfo.vue b/webapp/src/components/WifiStationInfo.vue
similarity index 69%
rename from webapp/src/components/partials/WifiStationInfo.vue
rename to webapp/src/components/WifiStationInfo.vue
index a3e3e0473..52fcf64ac 100644
--- a/webapp/src/components/partials/WifiStationInfo.vue
+++ b/webapp/src/components/WifiStationInfo.vue
@@ -10,24 +10,24 @@
Status
- enabled
+ enableddisabled
SSID
-
{{ sta_ssid }}
+
{{ networkStatus.sta_ssid }}
Quality
-
{{ getRSSIasQuality(sta_rssi) }} %
+
{{ getRSSIasQuality(networkStatus.sta_rssi) }} %
RSSI
-
{{ sta_rssi }}
+
{{ networkStatus.sta_rssi }}
@@ -37,13 +37,12 @@
\ No newline at end of file
diff --git a/webapp/src/components/partials/FirmwareInfo.vue b/webapp/src/components/partials/FirmwareInfo.vue
deleted file mode 100644
index 8667041ef..000000000
--- a/webapp/src/components/partials/FirmwareInfo.vue
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
diff --git a/webapp/src/main.ts b/webapp/src/main.ts
index e54f91b15..21996133c 100644
--- a/webapp/src/main.ts
+++ b/webapp/src/main.ts
@@ -5,4 +5,8 @@ import router from './router'
import "bootstrap/dist/css/bootstrap.min.css"
import "bootstrap"
-createApp(App).use(router).mount('#app')
+const app = createApp(App)
+
+app.use(router)
+
+app.mount('#app')
diff --git a/webapp/src/router/index.ts b/webapp/src/router/index.ts
index af84f783b..7e2ec6d30 100644
--- a/webapp/src/router/index.ts
+++ b/webapp/src/router/index.ts
@@ -1,22 +1,25 @@
-import { createWebHistory, createRouter, RouteRecordRaw } from 'vue-router';
-import HomeView from '@/components/HomeView.vue'
-import AboutView from '@/components/AboutView.vue'
-import NetworkInfoView from '@/components/NetworkInfoView.vue'
-import SystemInfoView from '@/components/SystemInfoView.vue'
-import NtpInfoView from '@/components/NtpInfoView.vue'
-import NetworkAdminView from '@/components/NetworkAdminView.vue'
-import NtpAdminView from '@/components/NtpAdminView.vue'
-import MqttAdminView from '@/components/MqttAdminView.vue'
-import MqttInfoView from '@/components/MqttInfoView.vue'
-import InverterAdminView from '@/components/InverterAdminView.vue'
-import DtuAdminView from '@/components/DtuAdminView.vue'
-import FirmwareUpgradeView from '@/components/FirmwareUpgradeView.vue'
-import ConfigAdminView from '@/components/ConfigAdminView.vue'
+import { createRouter, createWebHistory } from 'vue-router';
+import HomeView from '@/views/HomeView.vue'
+import AboutView from '@/views/AboutView.vue'
+import NetworkInfoView from '@/views/NetworkInfoView.vue'
+import SystemInfoView from '@/views/SystemInfoView.vue'
+import NtpInfoView from '@/views/NtpInfoView.vue'
+import NetworkAdminView from '@/views/NetworkAdminView.vue'
+import NtpAdminView from '@/views/NtpAdminView.vue'
+import MqttAdminView from '@/views/MqttAdminView.vue'
+import MqttInfoView from '@/views/MqttInfoView.vue'
+import InverterAdminView from '@/views/InverterAdminView.vue'
+import DtuAdminView from '@/views/DtuAdminView.vue'
+import FirmwareUpgradeView from '@/views/FirmwareUpgradeView.vue'
+import ConfigAdminView from '@/views/ConfigAdminView.vue'
import VedirectAdminView from '@/components/VedirectAdminView.vue'
import VedirectInfoView from '@/components/VedirectInfoView.vue'
-import SecurityAdminView from '@/components/SecurityAdminView.vue'
+import SecurityAdminView from '@/views/SecurityAdminView.vue'
-const routes: Array = [
+const router = createRouter({
+ history: createWebHistory(import.meta.env.BASE_URL),
+ linkActiveClass: "active",
+ routes: [
{
path: '/',
name: 'Home',
@@ -97,12 +100,7 @@ const routes: Array = [
name: 'Security',
component: SecurityAdminView
}
-];
-
-const router = createRouter({
- history: createWebHistory(),
- routes,
- linkActiveClass: "active",
-});
+]
+})
export default router;
\ No newline at end of file
diff --git a/webapp/src/shims-vue.d.ts b/webapp/src/shims-vue.d.ts
deleted file mode 100644
index 07ac9503b..000000000
--- a/webapp/src/shims-vue.d.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-/* eslint-disable */
-declare module '*.vue' {
- import type { DefineComponent } from 'vue'
- const component: DefineComponent<{}, {}, any>
- export default component
-}
diff --git a/webapp/src/types/DevInfoStatus.ts b/webapp/src/types/DevInfoStatus.ts
new file mode 100644
index 000000000..76f4cff28
--- /dev/null
+++ b/webapp/src/types/DevInfoStatus.ts
@@ -0,0 +1,9 @@
+export interface DevInfoStatus {
+ valid_data: boolean,
+ fw_bootloader_version: number,
+ fw_build_version: number,
+ fw_build_datetime: Date,
+ hw_part_number: number,
+ hw_version: number,
+ hw_model_name: string
+}
\ No newline at end of file
diff --git a/webapp/src/types/DtuConfig.ts b/webapp/src/types/DtuConfig.ts
new file mode 100644
index 000000000..5f05bf1f5
--- /dev/null
+++ b/webapp/src/types/DtuConfig.ts
@@ -0,0 +1,5 @@
+export interface DtuConfig {
+ dtu_serial: number,
+ dtu_pollinterval: number,
+ dtu_palevel: number
+}
\ No newline at end of file
diff --git a/webapp/src/types/EventlogStatus.ts b/webapp/src/types/EventlogStatus.ts
new file mode 100644
index 000000000..19f35bf7b
--- /dev/null
+++ b/webapp/src/types/EventlogStatus.ts
@@ -0,0 +1,11 @@
+export interface EventlogItem {
+ message_id: number,
+ message: string,
+ start_time: number,
+ end_time: number
+}
+
+export interface EventlogItems {
+ count: number,
+ events: Array,
+}
\ No newline at end of file
diff --git a/webapp/src/types/LiveDataStatus.ts b/webapp/src/types/LiveDataStatus.ts
new file mode 100644
index 000000000..a8b00f4c9
--- /dev/null
+++ b/webapp/src/types/LiveDataStatus.ts
@@ -0,0 +1,33 @@
+export interface ValueObject {
+ v: number, // value
+ u: string, // unit
+};
+
+export interface InverterStatistics {
+ Power?: ValueObject,
+ Voltage?: ValueObject,
+ Current?: ValueObject,
+ "Power DC"?: ValueObject,
+ YieldDay?: ValueObject,
+ YieldTotal?: ValueObject,
+ Frequency?: ValueObject,
+ Temperature?: ValueObject,
+ PowerFactor?: ValueObject,
+ ReactivePower?: ValueObject,
+ Efficiency?: ValueObject,
+ Irradiation?: ValueObject,
+}
+
+export interface Inverter {
+ serial: number,
+ name: string,
+ data_age: number,
+ reachable: boolean,
+ producing: boolean,
+ limit_relative: number,
+ limit_absolute: number,
+ events: number,
+ [key: number]: InverterStatistics,
+};
+
+export interface Inverters extends Array{};
\ No newline at end of file
diff --git a/webapp/src/types/MqttConfig.ts b/webapp/src/types/MqttConfig.ts
new file mode 100644
index 000000000..02619dd04
--- /dev/null
+++ b/webapp/src/types/MqttConfig.ts
@@ -0,0 +1,20 @@
+export interface MqttConfig {
+ mqtt_enabled: boolean,
+ mqtt_hostname: string,
+ mqtt_port: number,
+ mqtt_username: string,
+ mqtt_password: string,
+ mqtt_topic: string,
+ mqtt_publish_interval: number,
+ mqtt_retain: boolean,
+ mqtt_tls: boolean,
+ mqtt_root_ca_cert: string,
+ mqtt_lwt_topic: string,
+ mqtt_lwt_online: string,
+ mqtt_lwt_offline: string,
+ mqtt_hass_enabled: boolean,
+ mqtt_hass_expire: boolean,
+ mqtt_hass_retain: boolean,
+ mqtt_hass_topic: string,
+ mqtt_hass_individualpanels: boolean
+}
\ No newline at end of file
diff --git a/webapp/src/types/MqttStatus.ts b/webapp/src/types/MqttStatus.ts
new file mode 100644
index 000000000..f8bc2ce0f
--- /dev/null
+++ b/webapp/src/types/MqttStatus.ts
@@ -0,0 +1,17 @@
+export interface MqttStatus {
+ mqtt_enabled: boolean,
+ mqtt_hostname: string,
+ mqtt_port: number,
+ mqtt_username: string,
+ mqtt_topic: string,
+ mqtt_publish_interval: number,
+ mqtt_retain: boolean,
+ mqtt_tls: boolean,
+ mqtt_root_ca_cert_info: string,
+ mqtt_connected: boolean,
+ mqtt_hass_enabled: boolean,
+ mqtt_hass_expire: boolean,
+ mqtt_hass_retain: boolean,
+ mqtt_hass_topic: string,
+ mqtt_hass_individualpanels: boolean
+}
\ No newline at end of file
diff --git a/webapp/src/types/NetworkStatus.ts b/webapp/src/types/NetworkStatus.ts
new file mode 100644
index 000000000..01f7fe2df
--- /dev/null
+++ b/webapp/src/types/NetworkStatus.ts
@@ -0,0 +1,22 @@
+export interface NetworkStatus {
+ // WifiStationInfo
+ sta_status: boolean,
+ sta_ssid: string,
+ sta_rssi: number,
+ // WifiApInfo
+ ap_status: boolean,
+ ap_ssid: string,
+ ap_stationnum: number,
+ // InterfaceNetworkInfo
+ network_hostname: string,
+ network_ip: string,
+ network_netmask: string,
+ network_gateway: string,
+ network_dns1: string,
+ network_dns2: string,
+ network_mac: string,
+ network_mode: string,
+ // InterfaceApInfo
+ ap_ip: string,
+ ap_mac: string,
+}
\ No newline at end of file
diff --git a/webapp/src/types/NetworkkConfig.ts b/webapp/src/types/NetworkkConfig.ts
new file mode 100644
index 000000000..0c79d6a42
--- /dev/null
+++ b/webapp/src/types/NetworkkConfig.ts
@@ -0,0 +1,11 @@
+export interface NetworkConfig {
+ ssid: string,
+ password: string,
+ hostname: string,
+ dhcp: boolean,
+ ipaddress: string,
+ netmask: string,
+ gateway: string,
+ dns1: string,
+ dns2: string
+}
\ No newline at end of file
diff --git a/webapp/src/types/NtpConfig.ts b/webapp/src/types/NtpConfig.ts
new file mode 100644
index 000000000..24176cfcf
--- /dev/null
+++ b/webapp/src/types/NtpConfig.ts
@@ -0,0 +1,5 @@
+export interface NtpConfig {
+ ntp_server: string,
+ ntp_timezone: string,
+ ntp_timezone_descr: string
+}
\ No newline at end of file
diff --git a/webapp/src/types/NtpStatus.ts b/webapp/src/types/NtpStatus.ts
new file mode 100644
index 000000000..fd4c56f5d
--- /dev/null
+++ b/webapp/src/types/NtpStatus.ts
@@ -0,0 +1,7 @@
+export interface NtpStatus {
+ ntp_server: string,
+ ntp_timezone: string,
+ ntp_timezone_descr: string
+ ntp_status: boolean,
+ ntp_localtime: string
+}
\ No newline at end of file
diff --git a/webapp/src/types/SecurityConfig.ts b/webapp/src/types/SecurityConfig.ts
new file mode 100644
index 000000000..ca1f72114
--- /dev/null
+++ b/webapp/src/types/SecurityConfig.ts
@@ -0,0 +1,3 @@
+export interface SecurityConfig {
+ password: string
+}
\ No newline at end of file
diff --git a/webapp/src/types/SystemStatus.ts b/webapp/src/types/SystemStatus.ts
new file mode 100644
index 000000000..e31eff44e
--- /dev/null
+++ b/webapp/src/types/SystemStatus.ts
@@ -0,0 +1,29 @@
+export interface SystemStatus {
+ // HardwareInfo
+ chipmodel: string,
+ chiprevision: number,
+ chipcores: number,
+ cpufreq: number,
+ // FirmwareInfo
+ hostname: string,
+ sdkversion: string,
+ config_version: string,
+ git_hash: string,
+ resetreason_0: string,
+ resetreason_1: string,
+ cfgsavecount: number,
+ uptime: number,
+ update_text: string,
+ update_url: string,
+ update_status: string,
+ // MemoryInfo
+ heap_total: number,
+ heap_used: number,
+ littlefs_total: number,
+ littlefs_used: number,
+ sketch_total: number,
+ sketch_used: number,
+ // RadioInfo
+ radio_connected: boolean,
+ radio_pvariant: boolean,
+}
\ No newline at end of file
diff --git a/webapp/src/utils/index.ts b/webapp/src/utils/index.ts
new file mode 100644
index 000000000..0db17789f
--- /dev/null
+++ b/webapp/src/utils/index.ts
@@ -0,0 +1,9 @@
+import { timestampToString } from './time';
+
+export {
+ timestampToString,
+};
+
+export default {
+ timestampToString,
+}
\ No newline at end of file
diff --git a/webapp/src/utils/time.ts b/webapp/src/utils/time.ts
new file mode 100644
index 000000000..2c8779666
--- /dev/null
+++ b/webapp/src/utils/time.ts
@@ -0,0 +1,17 @@
+export const timestampToString = (value: number, includeDays = false): string => {
+ const days = Math.floor(value / (24 * 60 * 60));
+ const secAfterDays = value - days * (24 * 60 * 60);
+ const hours = Math.floor(secAfterDays / (60 * 60));
+ const secAfterHours = secAfterDays - hours * (60 * 60);
+ const minutes = Math.floor(secAfterHours / 60);
+ const seconds = secAfterHours - minutes * 60;
+
+ const dHours = hours > 9 ? hours : "0" + hours;
+ const dMins = minutes > 9 ? minutes : "0" + minutes;
+ const dSecs = seconds > 9 ? seconds : "0" + seconds;
+
+ if (includeDays) {
+ return days + " days " + dHours + ":" + dMins + ":" + dSecs;
+ }
+ return dHours + ":" + dMins + ":" + dSecs;
+}
\ No newline at end of file
diff --git a/webapp/src/components/AboutView.vue b/webapp/src/views/AboutView.vue
similarity index 97%
rename from webapp/src/components/AboutView.vue
rename to webapp/src/views/AboutView.vue
index 77f897b83..619aac010 100644
--- a/webapp/src/components/AboutView.vue
+++ b/webapp/src/views/AboutView.vue
@@ -1,10 +1,5 @@
-
-
-
About OpenDTU
-
-
-
+
@@ -96,12 +91,13 @@
-
+
\ No newline at end of file
diff --git a/webapp/src/views/DtuAdminView.vue b/webapp/src/views/DtuAdminView.vue
new file mode 100644
index 000000000..75883d13f
--- /dev/null
+++ b/webapp/src/views/DtuAdminView.vue
@@ -0,0 +1,116 @@
+
+
+
+ {{ alertMessage }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webapp/src/components/FirmwareUpgradeView.vue b/webapp/src/views/FirmwareUpgradeView.vue
similarity index 97%
rename from webapp/src/components/FirmwareUpgradeView.vue
rename to webapp/src/views/FirmwareUpgradeView.vue
index 2e120438c..e17d29b65 100644
--- a/webapp/src/components/FirmwareUpgradeView.vue
+++ b/webapp/src/views/FirmwareUpgradeView.vue
@@ -1,9 +1,5 @@
-
-
-
Firmware Upgrade
-
-
+
@@ -68,11 +64,12 @@
-
+
\ No newline at end of file
diff --git a/webapp/src/components/InverterAdminView.vue b/webapp/src/views/InverterAdminView.vue
similarity index 69%
rename from webapp/src/components/InverterAdminView.vue
rename to webapp/src/views/InverterAdminView.vue
index 3a00e9528..fce778473 100644
--- a/webapp/src/components/InverterAdminView.vue
+++ b/webapp/src/views/InverterAdminView.vue
@@ -1,9 +1,5 @@
-
-
-
Inverter Settings
-
-
+
{{ alertMessage }}
@@ -72,86 +68,85 @@
+
-
-
-
-
-
Edit Inverter
-
-
-
+
+
+
+
+
Edit Inverter
+
+
+
-
+
+
-
-
-
-
-
Delete Inverter
-
-
-
- Are you sure you want to delete the inverter "{{ deleteInverterData.name }}" with serial number
- {{ deleteInverterData.serial }}?
-
-
+
+
+
+
+
Delete Inverter
+
+
+
+ Are you sure you want to delete the inverter "{{ deleteInverterData.name }}" with serial number
+ {{ deleteInverterData.serial }}?
+