Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
export const PredefinedStrategies =
['everyChange', 'everyUpdate', 'restoreOnStartup', 'forecast']

export const CommonCronStrategies = [
{
name: 'everyMinute',
cronExpression: '0 * * ? * *'
},
{
name: 'everyHour',
cronExpression: '0 0 * * * ?'
},
{
name: 'everyDay',
cronExpression: '0 0 0 * * ?'
}
]

const filterInvertedParameter = {
advanced: false,
description: 'Whether to invert the above filter, i.e. persist values that do not equal the above values or are outside of the specified range',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@
"setupwizard.addons.waitMessage": "It may take a few minutes to install the add-ons you selected.",
"setupwizard.welcome.title": "Welcome to openHAB!",
"setupwizard.welcome.bindingsInstalled": "You have installed one or more bindings. Things provided by these bindings will appear in the Things Inbox. You can accept and further configure from there.",
"setupwizard.welcome.persistenceInstalled": "You have installed one or more persistence services. You will need to configure these services from the Settings/Persistence menu for them to be used.",
"setupwizard.welcome.getStarted": "Get Started"
}
13 changes: 13 additions & 0 deletions bundles/org.openhab.ui/web/src/js/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const ItemsAddFromTextualDefinition = () => import(/* webpackChunkName: "admin-c
const HealthOverviewPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/health/health-overview.vue')
const HealthOrphanLinksPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/health/health-orphanlinks.vue')
const HealthSemanticsPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/health/health-semantics.vue')
const HealthPersistencePage = () => import(/* webpackChunkName: "admin-config" */ '../pages/settings/health/health-persistence.vue')
const ThingsListPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/things/things-list.vue')
const ThingDetailsPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/things/thing-details.vue')
const AddThingChooseBindingPage = () => import(/* webpackChunkName: "admin-config" */ '@/pages/settings/things/add/choose-binding.vue')
Expand Down Expand Up @@ -275,6 +276,18 @@ export default [
}
]
},
{
path: 'health',
beforeEnter: [enforceAdminForRoute],
async: loadAsync(HealthOverviewPage),
routes: [
{
path: 'persistence',
beforeEnter: [enforceAdminForRoute],
async: loadAsync(HealthPersistencePage)
}
]
},
{
path: 'things/',
beforeEnter: [enforceAdminForRoute],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
</f7-col>

<f7-col v-else>
<f7-block-title> {{ orphanLinks.length }} orphan links found </f7-block-title>
<f7-block-title>
{{ orphanLinks.length }} orphan link{{ plural(orphanLinks.length) }} found
</f7-block-title>
<f7-list class="col" contacts-list>
<f7-list-item v-for="orphanLink in orphanLinks"
:key="orphanLink.itemChannelLink.channelUID"
Expand All @@ -61,7 +63,7 @@
<f7-col>
<f7-list>
<f7-list-button color="red" @click="purgeAllManaged()">
Purge all managed links (will purge {{ purgeableLinksCount }} managed links)
Purge all managed links (will purge {{ purgeableLinksCount }} managed link{{ plural(purgeableLinksCount) }})
</f7-list-button>
</f7-list>
</f7-col>
Expand Down Expand Up @@ -119,6 +121,9 @@ export default {
}).finally(() => {
this.load()
})
},
plural (count) {
return count === 1 ? '' : 's'
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</f7-col>
</f7-block>

<f7-block class="block-narrow">
<f7-block v-if="orphanLinksCount" class="block-narrow">
<f7-col>
<f7-list media-list>
<f7-list-item
Expand Down Expand Up @@ -47,6 +47,24 @@
</f7-list>
</f7-col>
</f7-block>
<f7-block v-if="persistenceProblemsCount" class="block-narrow">
<f7-col>
<f7-list media-list>
<f7-list-item
media-item
link="persistence/"
title="Persistence Problems"
:badge="persistenceProblemsCount > 0 ? persistenceProblemsCount : undefined"
:after="persistenceProblemsCount > 0 ? undefined : persistenceProblemsCount"
:badge-color="persistenceProblemsCount ? 'red' : 'blue'"
:footer="objectsSubtitles.persistenceProblems">
<template #media>
<f7-icon f7="link" color="gray" />
</template>
</f7-list-item>
</f7-list>
</f7-col>
</f7-block>
</f7-page>
</template>

Expand All @@ -61,10 +79,12 @@ export default {
return {
objectsSubtitles: {
orphanLinks: 'Items pointing to non-existent thing channels or vica versa',
semanticsProblems: 'Issues with semantic model configuration'
semanticsProblems: 'Issues with semantic model configuration',
persistenceProblems: 'Persistence configurations missing items or strategies'
},
orphanLinksCount: 0,
semanticsProblemCount: 0,
persistenceProblemsCount: 0,

expandedTypes: {
systemSettings: this.$f7dim.width >= 1450
Expand All @@ -83,6 +103,7 @@ export default {
},
methods: {
loadCounters () {
let self = this
if (!this.apiEndpoints) return
if (useRuntimeStore().apiEndpoint('links')) {
this.$oh.api.get('/rest/links/orphans').then((data) => {
Expand All @@ -94,6 +115,11 @@ export default {
this.semanticsProblemCount = data.length || 0
})
}
if (this.$store.getters.apiEndpoint('persistence')) {
this.$oh.api.get('/rest/persistence/persistencehealth').then((data) => {
self.persistenceProblemsCount = data.length || 0
})
}
},
onPageAfterIn () {
this.loadCounters()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<template>
<f7-page @page:afterin="onPageAfterIn">
<f7-navbar title="Persistence Configuration Issues"
back-link="Health Checks"
back-link-url="/settings/health/"
back-link-force>
<f7-nav-right>
<developer-dock-icon />
</f7-nav-right>
</f7-navbar>

<f7-block class="block-narrow">
<f7-col>
<f7-block-footer class="padding-horizontal">
Persistence services need to be configured with items to persist and strategies for persisting these.
<br>
<br>
Note that only the configuration of managed persistence service configurations can be changed through the UI,
not configurations in <code>.persist</code> files - these must be fixed manually in the corresponding file.
The latter are marked with <f7-icon f7="lock_fill" size="1rem" color="gray" />.
</f7-block-footer>
</f7-col>
</f7-block>

<f7-block class="block-narrow">
<!-- skeleton for not ready -->
<f7-col v-if="!ready">
<f7-block-title>&nbsp;Loading...</f7-block-title>
<f7-list contacts-list class="col">
<f7-list-group>
<f7-list-item media-item
v-for="n in 10"
:key="n"
:class="`skeleton-text skeleton-effect-blink`"
title="Type of problem"
subtitle="Persistence service"
footer="" />
</f7-list-group>
</f7-list>
</f7-col>

<f7-col v-else>
<f7-block-title>
{{ persistenceProblems.length }} persistence configuration problem{{ plural(persistenceProblems.length) }} found
</f7-block-title>
<f7-list class="col" contacts-list>
<f7-list-item v-for="persistenceProblem in persistenceProblems"
:key="problemKey(persistenceProblem)"
media-item
:link="getLinkForProblem(persistenceProblem)"
:title="'Problem: ' + explanation(persistenceProblem.reason)"
:subtitle="persistenceProblem.serviceId ? 'Persistence Service: ' + persistenceProblem.serviceId : ''"
:footer="persistenceProblem.items ? 'Items: ' + persistenceProblem.items.join(', ') : ''">
<template #after-title>
<f7-icon v-if="!persistenceProblem.editable"
f7="lock_fill"
size="1rem"
color="gray" />
</template>
</f7-list-item>
</f7-list>
</f7-col>
</f7-block>
</f7-page>
</template>

<script>
export default {
data () {
return {
ready: false,
loading: false,
persistenceProblems: [],

persistenceProblemExplanation: {
PERSISTENCE_NO_DEFAULT: 'No default persistence service defined',
PERSISTENCE_SERVICE_NO_CONFIG: 'No configuration for persistence service',
PERSISTENCE_SERVICE_NO_ITEMS: 'No persistence items defined for persistence service',
PERSISTENCE_SERVICE_ITEMS_NO_STRATEGY: 'No persistence strategy set for persistence items',
PERSISTENCE_SERVICE_ITEMS_NO_STORE_STRATEGY: 'Persistence strategy for persistence items only has a restore strategy'
}
}
},
methods: {
onPageAfterIn () {
this.load()
},
load () {
this.loading = true
this.$oh.api.get('/rest/persistence/persistencehealth').then((data) => {
this.persistenceProblems = data
this.loading = false
this.ready = true
})
},
problemKey (persistenceProblem) {
let key = persistenceProblem.reason
if (persistenceProblem.serviceId) key = key + '_' + persistenceProblem.serviceId
if (persistenceProblem.items) key = key + '_' + persistenceProblem.items.join('_')
},
getLinkForProblem (persistenceProblem) {
if (persistenceProblem.serviceId) {
return '/settings/persistence/' + persistenceProblem.serviceId
}
return '/settings/persistence'
},
explanation (reason) {
return this.persistenceProblemExplanation[reason] || reason
},
plural (count) {
return count === 1 ? '' : 's'
}
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ export default {

orphanLinkCount: 0,
semanticsProblemCount: 0,
persistenceProblemCount: 0,

advancedSystemServices: [
'org.openhab.storage.json',
Expand Down Expand Up @@ -316,7 +317,7 @@ export default {
})
},
healthCount () {
const problemCount = this.orphanLinkCount + this.semanticsProblemCount
const problemCount = this.orphanLinkCount + this.semanticsProblemCount + this.persistenceProblemCount
return problemCount.toString()
},
...mapStores(useComponentsStore, useRuntimeStore)
Expand Down Expand Up @@ -360,6 +361,8 @@ export default {
this.$oh.api.get('/rest/links/orphans').then((data) => { this.orphanLinkCount = data.length })
if (useRuntimeStore().apiEndpoint('items'))
this.$oh.api.get('/rest/items/semantics/health').then((data) => { this.semanticsProblemCount = data.length })
if (this.$store.getters.apiEndpoint('persistence'))
this.$oh.api.get('/rest/persistence/persistencehealth').then((data) => { this.persistenceProblemCount = data.length })
if (useRuntimeStore().apiEndpoint('inbox'))
this.$oh.api.get('/rest/inbox?includeIgnored=false').then((data) => { this.inboxCount = data.filter((e) => e.flag === 'NEW').length.toString() })
if (useRuntimeStore().apiEndpoint('things'))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
name="strategies"
:strategies="strategies"
:value="currentConfiguration.strategies"
:suggested="suggestedStrategies"
@strategies-selected="currentConfiguration.strategies = $event" />
</f7-col>
<f7-col>
Expand Down Expand Up @@ -115,16 +116,15 @@ export default {
props: {
configuration: Object,
strategies: Array,
filters: Array
filters: Array,
suggestedStrategies: Array
},
emits: ['configurationUpdate'],
data () {
return {
currentConfiguration: this.configuration || {
items: [],
strategies: [
'everyChange'
],
strategies: [],
filters: []
}
}
Expand Down
Loading