From 4cf160735bf0feeca8a435708e576d25d88255bd Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 25 May 2024 21:01:22 +0200 Subject: [PATCH] feat(history): add moonraker sensors to total statistic (#1886) --- src/components/mixins/history.ts | 31 ++++ src/components/panels/HistoryListPanel.vue | 31 +--- .../panels/HistoryStatisticsPanel.vue | 159 +++++++++++++----- src/store/server/history/actions.ts | 5 + src/store/server/history/index.ts | 1 + src/store/server/history/mutations.ts | 4 + src/store/server/history/types.ts | 8 + 7 files changed, 165 insertions(+), 74 deletions(-) create mode 100644 src/components/mixins/history.ts diff --git a/src/components/mixins/history.ts b/src/components/mixins/history.ts new file mode 100644 index 000000000..80b763aac --- /dev/null +++ b/src/components/mixins/history.ts @@ -0,0 +1,31 @@ +import Vue from 'vue' +import Component from 'vue-class-component' + +@Component +export default class HistoryMixin extends Vue { + get moonrakerHistoryFields() { + const config = this.$store.state.server.config?.config ?? {} + const sensors = Object.keys(config).filter((key) => key.startsWith('sensor ')) + const historyFields: { desc: string; unit: string; provider: string; name: string; parameter: string }[] = [] + + sensors.forEach((configName) => { + const sensor = config[configName] ?? {} + + Object.keys(sensor) + .filter((key) => key.startsWith('history_field_')) + .forEach((key) => { + const historyField = sensor[key] + + historyFields.push({ + desc: historyField.desc, + unit: historyField.units, + provider: configName, + parameter: historyField.parameter, + name: key, + }) + }) + }) + + return historyFields + } +} diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 10cd90fba..85b2b404f 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -178,6 +178,7 @@ import HistoryListPanelAddMaintenance from '@/components/dialogs/HistoryListPane import { GuiMaintenanceStateEntry, HistoryListRowMaintenance } from '@/store/gui/maintenance/types' import HistoryListEntryMaintenance from '@/components/panels/History/HistoryListEntryMaintenance.vue' import HistoryListPanelDeleteSelectedDialog from '@/components/dialogs/HistoryListPanelDeleteSelectedDialog.vue' +import HistoryMixin from '@/components/mixins/history' export type HistoryListPanelRow = HistoryListRowJob | HistoryListRowMaintenance @@ -201,7 +202,7 @@ export interface HistoryListPanelCol { Panel, }, }) -export default class HistoryListPanel extends Mixins(BaseMixin) { +export default class HistoryListPanel extends Mixins(BaseMixin, HistoryMixin) { mdiCloseThick = mdiCloseThick mdiCog = mdiCog mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline @@ -409,7 +410,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { }, ] - this.moonrakerSensors.forEach((sensor) => { + this.moonrakerHistoryFields.forEach((sensor) => { headers.push({ text: sensor.desc, value: sensor.name, @@ -430,32 +431,6 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { return headers } - get moonrakerSensors() { - const config = this.$store.state.server.config?.config ?? {} - const sensors = Object.keys(config).filter((key) => key.startsWith('sensor ')) - const historyFields: { desc: string; unit: string; provider: string; name: string; parameter: string }[] = [] - - sensors.forEach((configName) => { - const sensor = config[configName] ?? {} - - Object.keys(sensor) - .filter((key) => key.startsWith('history_field_')) - .forEach((key) => { - const historyField = sensor[key] - - historyFields.push({ - desc: historyField.desc, - unit: historyField.units, - provider: configName, - parameter: historyField.parameter, - name: key, - }) - }) - }) - - return historyFields - } - get tableFields() { return this.filteredHeaders.filter( (col: any) => !['filename', 'status'].includes(col.value) && col.value !== '' diff --git a/src/components/panels/HistoryStatisticsPanel.vue b/src/components/panels/HistoryStatisticsPanel.vue index 628bb12c6..a2099cca2 100644 --- a/src/components/panels/HistoryStatisticsPanel.vue +++ b/src/components/panels/HistoryStatisticsPanel.vue @@ -9,50 +9,10 @@ - - + + {{ total.title }} + {{ total.value }} + @@ -104,13 +64,14 @@ import Panel from '@/components/ui/Panel.vue' import HistoryFilamentUsage from '@/components/charts/HistoryFilamentUsage.vue' import HistoryPrinttimeAvg from '@/components/charts/HistoryPrinttimeAvg.vue' import HistoryAllPrintStatusChart from '@/components/charts/HistoryAllPrintStatusChart.vue' -import { ServerHistoryStateJob } from '@/store/server/history/types' +import { ServerHistoryStateJob, ServerHistoryStateJobAuxiliaryTotal } from '@/store/server/history/types' import { mdiChartAreaspline, mdiDatabaseArrowDownOutline } from '@mdi/js' import { formatPrintTime } from '@/plugins/helpers' +import HistoryMixin from '@/components/mixins/history' @Component({ components: { Panel, HistoryFilamentUsage, HistoryPrinttimeAvg, HistoryAllPrintStatusChart }, }) -export default class HistoryStatisticsPanel extends Mixins(BaseMixin) { +export default class HistoryStatisticsPanel extends Mixins(BaseMixin, HistoryMixin) { mdiChartAreaspline = mdiChartAreaspline mdiDatabaseArrowDownOutline = mdiDatabaseArrowDownOutline formatPrintTime = formatPrintTime @@ -215,6 +176,112 @@ export default class HistoryStatisticsPanel extends Mixins(BaseMixin) { return this.$store.state.server.history.all_loaded ?? false } + get selectedTotals() { + const output: { title: string; value: string }[] = [ + { + title: this.$t('History.SelectedPrinttime') as string, + value: this.formatPrintTime(this.selectedPrintTime, false), + }, + { + title: this.$t('History.LongestPrinttime') as string, + value: this.formatPrintTime(this.selectedLongestPrintTime, false), + }, + { + title: this.$t('History.AvgPrinttime') as string, + value: this.formatPrintTime(this.selectedAvgPrintTime, false), + }, + { + title: this.$t('History.SelectedFilamentUsed') as string, + value: this.selectedFilamentUsedFormat, + }, + { + title: this.$t('History.SelectedJobs') as string, + value: this.selectedJobs.length.toString(), + }, + ] + + output.push(...this.auxiliarySelectedTotals) + + return output + } + + get auxiliarySelectedTotals() { + const output: { title: string; value: string }[] = [] + this.moonrakerHistoryFields.forEach((historyField) => { + const value = this.selectedJobs.reduce((acc: number, job: ServerHistoryStateJob) => { + const historyFieldName = historyField.name.replace('history_field_', '') + const auxiliary_data = job.auxiliary_data?.find( + (auxiliary) => auxiliary.provider === historyField.provider && auxiliary.name === historyFieldName + ) + + if (!auxiliary_data || typeof auxiliary_data.value !== 'number') return acc + + return acc + auxiliary_data.value + }, 0) + + output.push({ + title: historyField.desc, + value: `${Math.round(value * 1000) / 1000} ${historyField.unit}`, + }) + }) + + return output + } + + get genericTotals() { + const output: { title: string; value: string }[] = [ + { + title: this.$t('History.TotalPrinttime') as string, + value: this.formatPrintTime(this.totalPrintTime, false), + }, + { + title: this.$t('History.LongestPrinttime') as string, + value: this.formatPrintTime(this.longestPrintTime, false), + }, + { + title: this.$t('History.AvgPrinttime') as string, + value: this.formatPrintTime(this.avgPrintTime, false), + }, + { + title: this.$t('History.TotalFilamentUsed') as string, + value: this.totalFilamentUsedFormat, + }, + { + title: this.$t('History.TotalJobs') as string, + value: this.totalJobsCount.toString(), + }, + ] + + // Add auxiliary totals + output.push(...this.auxiliaryTotals) + + return output + } + + get auxiliaryTotals() { + const auxiliaries = this.$store.state.server.history.auxiliary_totals ?? [] + const output: { title: string; value: string }[] = [] + + auxiliaries.forEach((auxiliary: ServerHistoryStateJobAuxiliaryTotal) => { + const historyFieldName = `history_field_${auxiliary.field}` + const historyField = this.moonrakerHistoryFields.find( + (historyField) => historyField.provider === auxiliary.provider && historyField.name === historyFieldName + ) + const value = Math.round((auxiliary.total ?? 0) * 1000) / 1000 + + output.push({ + title: historyField?.desc ?? auxiliary.field, + value: `${value} ${historyField?.unit}`, + }) + }) + + return output + } + + get totals() { + return this.existsSelectedJobs ? this.selectedTotals : this.genericTotals + } + refreshHistory() { this.$store.dispatch('socket/addLoading', { name: 'historyLoadAll' }) diff --git a/src/store/server/history/actions.ts b/src/store/server/history/actions.ts index 455fc8c4c..3a2eda0cf 100644 --- a/src/store/server/history/actions.ts +++ b/src/store/server/history/actions.ts @@ -19,6 +19,11 @@ export const actions: ActionTree = { getTotals({ commit }, payload) { commit('setTotals', payload.job_totals) + + const auxiliary_totals = payload.auxiliary_totals ?? [] + if (auxiliary_totals.length) { + commit('setAuxiliaryTotals', auxiliary_totals) + } }, async getHistory({ commit, dispatch, state }, payload) { diff --git a/src/store/server/history/index.ts b/src/store/server/history/index.ts index 8e1acead3..c16abbfd5 100644 --- a/src/store/server/history/index.ts +++ b/src/store/server/history/index.ts @@ -15,6 +15,7 @@ export const getDefaultState = (): ServerHistoryState => { longest_job: 0, longest_print: 0, }, + auxiliary_totals: [], all_loaded: false, } } diff --git a/src/store/server/history/mutations.ts b/src/store/server/history/mutations.ts index 9ee7a3129..d4df8fded 100644 --- a/src/store/server/history/mutations.ts +++ b/src/store/server/history/mutations.ts @@ -16,6 +16,10 @@ export const mutations: MutationTree = { Vue.set(state, 'job_totals', payload) }, + setAuxiliaryTotals(state, payload) { + Vue.set(state, 'auxiliary_totals', payload) + }, + setHistoryNotes(state, payload) { const job = state.jobs.find((job) => job.job_id === payload.job_id) if (job) Vue.set(job, 'note', payload.text) diff --git a/src/store/server/history/types.ts b/src/store/server/history/types.ts index 4cebfb17a..d9e69e5fa 100644 --- a/src/store/server/history/types.ts +++ b/src/store/server/history/types.ts @@ -10,6 +10,7 @@ export interface ServerHistoryState { longest_job: number longest_print: number } + auxiliary_totals: ServerHistoryStateJobAuxiliaryTotal[] all_loaded: boolean } @@ -61,6 +62,13 @@ export interface ServerHistoryStateJobAuxiliaryData { value: number | number[] } +export interface ServerHistoryStateJobAuxiliaryTotal { + field: string + maximum: number + provider: string + total: number +} + export interface HistoryListRowJob extends ServerHistoryStateJob { type: 'job' select_id: string