From f999e6b202813eb45978b5853fee1082a24f7f2e Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Fri, 17 May 2024 22:52:14 +0200 Subject: [PATCH 01/13] feat: add support for moonraker sensor history_fields Signed-off-by: Stefan Dej --- .../dialogs/HistoryDetailsDialog.vue | 170 ------------- .../dialogs/HistoryListPanelDetailsDialog.vue | 16 ++ .../panels/History/HistoryListEntryJob.vue | 5 + .../panels/History/HistoryListRow.vue | 226 ------------------ .../panels/History/HistoryListRowCell.vue | 61 ----- src/components/panels/HistoryListPanel.vue | 36 +++ src/store/server/history/types.ts | 9 + src/store/server/index.ts | 2 + src/store/server/sensor/actions.ts | 26 ++ src/store/server/sensor/getters.ts | 5 + src/store/server/sensor/index.ts | 23 ++ src/store/server/sensor/mutations.ts | 18 ++ src/store/server/sensor/types.ts | 14 ++ src/store/socket/actions.ts | 4 + src/store/variables.ts | 1 + 15 files changed, 159 insertions(+), 457 deletions(-) delete mode 100644 src/components/dialogs/HistoryDetailsDialog.vue delete mode 100644 src/components/panels/History/HistoryListRow.vue delete mode 100644 src/components/panels/History/HistoryListRowCell.vue create mode 100644 src/store/server/sensor/actions.ts create mode 100644 src/store/server/sensor/getters.ts create mode 100644 src/store/server/sensor/index.ts create mode 100644 src/store/server/sensor/mutations.ts create mode 100644 src/store/server/sensor/types.ts diff --git a/src/components/dialogs/HistoryDetailsDialog.vue b/src/components/dialogs/HistoryDetailsDialog.vue deleted file mode 100644 index dfa3c2c34..000000000 --- a/src/components/dialogs/HistoryDetailsDialog.vue +++ /dev/null @@ -1,170 +0,0 @@ - - - diff --git a/src/components/dialogs/HistoryListPanelDetailsDialog.vue b/src/components/dialogs/HistoryListPanelDetailsDialog.vue index 16f7f33f8..8236db9c8 100644 --- a/src/components/dialogs/HistoryListPanelDetailsDialog.vue +++ b/src/components/dialogs/HistoryListPanelDetailsDialog.vue @@ -106,6 +106,22 @@ export default class HistoryListPanelDetailsDialog extends Mixins(BaseMixin) { }, ] + if ('auxiliary_data' in this.job) { + this.job.auxiliary_data?.forEach((data) => { + let value = data.value.toString() + if (!Array.isArray(data.value)) { + value = `${Math.round(data.value * 1000) / 1000} ${data.units}` + } + if (value === '') value = '--' + + entries.push({ + name: data.description, + value, + exists: true, + }) + }) + } + return entries.filter((entry) => entry.exists) } diff --git a/src/components/panels/History/HistoryListEntryJob.vue b/src/components/panels/History/HistoryListEntryJob.vue index 29cd970b6..aa8da85d9 100644 --- a/src/components/panels/History/HistoryListEntryJob.vue +++ b/src/components/panels/History/HistoryListEntryJob.vue @@ -300,6 +300,11 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { //@ts-ignore let value = col.value in item ? item[col.value] : null if (value === null) value = col.value in item.metadata ? item.metadata[col.value] : null + if (col.value.startsWith('history_field_')) { + const fieldName = col.value.replace('history_field_', '') + const field = item.auxiliary_data?.find((field: any) => field.name === fieldName) + if (field && !Array.isArray(field.value)) return `${Math.round(field.value * 1000) / 1000} ${field.units}` + } if (value === null) return '--' if (col.value === 'slicer') value += '
' + item.metadata.slicer_version diff --git a/src/components/panels/History/HistoryListRow.vue b/src/components/panels/History/HistoryListRow.vue deleted file mode 100644 index 93214a4c6..000000000 --- a/src/components/panels/History/HistoryListRow.vue +++ /dev/null @@ -1,226 +0,0 @@ - - diff --git a/src/components/panels/History/HistoryListRowCell.vue b/src/components/panels/History/HistoryListRowCell.vue deleted file mode 100644 index c651b08a0..000000000 --- a/src/components/panels/History/HistoryListRowCell.vue +++ /dev/null @@ -1,61 +0,0 @@ - - diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 99aff2093..d65f352da 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -409,6 +409,16 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { }, ] + this.moonrakerSensors.forEach((sensor) => { + headers.push({ + text: sensor.desc, + value: sensor.name, + align: 'left', + configable: true, + visible: false, + }) + }) + headers.forEach((header) => { if (header.visible && this.hideColums.includes(header.value)) { header.visible = false @@ -420,6 +430,32 @@ 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/store/server/history/types.ts b/src/store/server/history/types.ts index 4d8cd56fc..f3f0350f9 100644 --- a/src/store/server/history/types.ts +++ b/src/store/server/history/types.ts @@ -50,6 +50,15 @@ export interface ServerHistoryStateJob { status: string start_time: number total_duration: number + auxiliary_data?: ServerHistoryStateJobAxiliaryData[] +} + +export interface ServerHistoryStateJobAxiliaryData { + description: string + name: string + provider: string + units: string + value: number | number[] } export interface HistoryListRowJob extends ServerHistoryStateJob { diff --git a/src/store/server/index.ts b/src/store/server/index.ts index 1fde111a3..5e90dc7dc 100644 --- a/src/store/server/index.ts +++ b/src/store/server/index.ts @@ -12,6 +12,7 @@ import { timelapse } from '@/store/server/timelapse' import { jobQueue } from '@/store/server/jobQueue' import { announcements } from '@/store/server/announcements' import { spoolman } from '@/store/server/spoolman' +import { sensor } from '@/store/server/sensor' // create getDefaultState export const getDefaultState = (): ServerState => { @@ -62,5 +63,6 @@ export const server: Module = { jobQueue, announcements, spoolman, + sensor, }, } diff --git a/src/store/server/sensor/actions.ts b/src/store/server/sensor/actions.ts new file mode 100644 index 000000000..28addc301 --- /dev/null +++ b/src/store/server/sensor/actions.ts @@ -0,0 +1,26 @@ +import Vue from 'vue' +import { ActionTree } from 'vuex' +import { ServerSensorState } from '@/store/server/sensor/types' +import { RootState } from '@/store/types' + +export const actions: ActionTree = { + reset({ commit }) { + commit('reset') + }, + + init() { + Vue.$socket.emit('server.sensors.list', {}, { action: 'server/sensor/getSensors' }) + }, + + getSensors({ commit, dispatch }, payload) { + commit('setSensors', payload.sensors) + + dispatch('socket/removeInitModule', 'server/sensor/init', { root: true }) + }, + + updateSensors({ commit }, payload) { + Object.keys(payload).forEach((key) => { + commit('updateSensor', { key, value: payload[key] }) + }) + }, +} diff --git a/src/store/server/sensor/getters.ts b/src/store/server/sensor/getters.ts new file mode 100644 index 000000000..b0b84ee3c --- /dev/null +++ b/src/store/server/sensor/getters.ts @@ -0,0 +1,5 @@ +import { GetterTree } from 'vuex' +import { ServerSensorState } from '@/store/server/sensor/types' + +// eslint-disable-next-line +export const getters: GetterTree = {} diff --git a/src/store/server/sensor/index.ts b/src/store/server/sensor/index.ts new file mode 100644 index 000000000..c60aea2c9 --- /dev/null +++ b/src/store/server/sensor/index.ts @@ -0,0 +1,23 @@ +import { Module } from 'vuex' +import { ServerSensorState } from '@/store/server/sensor/types' +import { actions } from '@/store/server/sensor/actions' +import { mutations } from '@/store/server/sensor/mutations' +import { getters } from '@/store/server/sensor/getters' + +export const getDefaultState = (): ServerSensorState => { + return { + sensors: {}, + } +} + +// initial state +const state = getDefaultState() + +// eslint-disable-next-line +export const sensor: Module = { + namespaced: true, + state, + getters, + actions, + mutations, +} diff --git a/src/store/server/sensor/mutations.ts b/src/store/server/sensor/mutations.ts new file mode 100644 index 000000000..5f4df98f4 --- /dev/null +++ b/src/store/server/sensor/mutations.ts @@ -0,0 +1,18 @@ +import Vue from 'vue' +import { getDefaultState } from './index' +import { MutationTree } from 'vuex' +import { ServerSensorState } from '@/store/server/sensor/types' + +export const mutations: MutationTree = { + reset(state) { + Object.assign(state, getDefaultState()) + }, + + setSensors(state, payload) { + Vue.set(state, 'sensors', payload) + }, + + updateSensor(state, payload) { + Vue.set(state.sensors, payload.key, payload.value) + }, +} diff --git a/src/store/server/sensor/types.ts b/src/store/server/sensor/types.ts new file mode 100644 index 000000000..e745b04d3 --- /dev/null +++ b/src/store/server/sensor/types.ts @@ -0,0 +1,14 @@ +export interface ServerSensorState { + sensors: { + [key: string]: ServerSensorStateSensor + } +} + +export interface ServerSensorStateSensor { + friendly_name: string + id: string + type: string + values: { + [key: string]: number + } +} diff --git a/src/store/socket/actions.ts b/src/store/socket/actions.ts index 50b66b16b..0a207d48b 100644 --- a/src/store/socket/actions.ts +++ b/src/store/socket/actions.ts @@ -135,6 +135,10 @@ export const actions: ActionTree = { dispatch('server/spoolman/getActiveSpoolId', payload.params[0], { root: true }) break + case 'notify_sensor_update': + dispatch('server/sensor/updateSensors', payload.params[0], { root: true }) + break + default: window.console.debug(payload) } diff --git a/src/store/variables.ts b/src/store/variables.ts index f3676d781..4db839504 100644 --- a/src/store/variables.ts +++ b/src/store/variables.ts @@ -35,6 +35,7 @@ export const initableServerComponents = [ 'jobQueue', 'announcements', 'spoolman', + 'sensor', ] /* From 149941a80892c7994058d7d00bccdc70bf98e0f5 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 18 May 2024 10:41:04 +0200 Subject: [PATCH 02/13] feat: add history_fields to CSV export Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 53 ++++++++++++++++------ 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index d65f352da..3525e19ea 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -580,6 +580,12 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { row.push('status') this.tableFields.forEach((col) => { + if (col.value.startsWith('history_field_')) { + const sensorName = col.value.replace('history_field_', '') + row.push(sensorName) + return + } + row.push(col.value) }) @@ -648,18 +654,9 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { row.push('job') row.push(job.status) - this.tableFields - .filter((header) => header.value !== 'slicer') - .forEach((col) => { - row.push(this.outputValue(col, job, csvSeperator)) - }) - - if (this.tableFields.find((header) => header.value === 'slicer')?.visible) { - let slicerString = 'slicer' in job.metadata && job.metadata.slicer ? job.metadata.slicer : '--' - if ('slicer_version' in job.metadata && job.metadata.slicer_version) - slicerString += ' ' + job.metadata.slicer_version - row.push(slicerString) - } + this.tableFields.forEach((col) => { + row.push(this.outputValue(col, job, csvSeperator)) + }) content.push(row) }) @@ -670,7 +667,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { const csvContent = 'data:text/csv;charset=utf-8,' + content.map((entry) => - entry.map((field) => (field.indexOf(csvSeperator) === -1 ? field : `"${field}"`)).join(csvSeperator) + entry.map((field) => (field?.indexOf(csvSeperator) === -1 ? field : `"${field}"`)).join(csvSeperator) ).join('\n') const link = document.createElement('a') @@ -687,6 +684,36 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { let value = col.value in job ? job[col.value] : null if (value === null) value = col.value in job.metadata ? job.metadata[col.value] : null + if (col.value === 'slicer') { + let slicerString = 'slicer' in job.metadata && job.metadata.slicer ? job.metadata.slicer : '--' + if ('slicer_version' in job.metadata && job.metadata.slicer_version) + slicerString += ' ' + job.metadata.slicer_version + + if (csvSeperator !== null && value.includes(csvSeperator)) return '"' + slicerString + '"' + + return slicerString + } + + if (col.value.startsWith('history_field_')) { + const sensorName = col.value.replace('history_field_', '') + const sensor = job.auxiliary_data?.find((sensor) => sensor.name === sensorName) + + let value = sensor?.value?.toString() + + // return value, when it is not an array + if (sensor && !Array.isArray(sensor.value)) { + value = `${Math.round(sensor.value * 1000) / 1000} ${sensor.units}` + } + + // return empty string, when value is null + if (!value) return '--' + + // escape fields with the csvSeperator in the content + if (csvSeperator !== null && value?.includes(csvSeperator)) return `"${value}"` + + return value + } + switch (col.outputType) { case 'date': return this.formatDateTime(value * 1000) From 99c76510b17ff68fbb0be28f589603852f08d135 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 18 May 2024 10:50:57 +0200 Subject: [PATCH 03/13] fix: fix csv output for history_fields Signed-off-by: Stefan Dej --- src/components/panels/HistoryListPanel.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/panels/HistoryListPanel.vue b/src/components/panels/HistoryListPanel.vue index 3525e19ea..10cd90fba 100644 --- a/src/components/panels/HistoryListPanel.vue +++ b/src/components/panels/HistoryListPanel.vue @@ -702,7 +702,7 @@ export default class HistoryListPanel extends Mixins(BaseMixin) { // return value, when it is not an array if (sensor && !Array.isArray(sensor.value)) { - value = `${Math.round(sensor.value * 1000) / 1000} ${sensor.units}` + value = sensor.value?.toLocaleString(this.browserLocale, { useGrouping: false }) ?? 0 } // return empty string, when value is null From ae8827019b1b5298db25d4d5a67f6291aca98692 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sat, 18 May 2024 17:38:11 +0200 Subject: [PATCH 04/13] feat(history): add moonraker sensors to total statistic Signed-off-by: Stefan Dej --- 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 | 12 +- 7 files changed, 167 insertions(+), 76 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 f3f0350f9..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 } @@ -50,10 +51,10 @@ export interface ServerHistoryStateJob { status: string start_time: number total_duration: number - auxiliary_data?: ServerHistoryStateJobAxiliaryData[] + auxiliary_data?: ServerHistoryStateJobAuxiliaryData[] } -export interface ServerHistoryStateJobAxiliaryData { +export interface ServerHistoryStateJobAuxiliaryData { description: string name: string provider: string @@ -61,6 +62,13 @@ export interface ServerHistoryStateJobAxiliaryData { value: number | number[] } +export interface ServerHistoryStateJobAuxiliaryTotal { + field: string + maximum: number + provider: string + total: number +} + export interface HistoryListRowJob extends ServerHistoryStateJob { type: 'job' select_id: string From 070780c5dac13d9633fa8be0aab009cba4ff6126 Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Sun, 19 May 2024 23:38:39 +0200 Subject: [PATCH 05/13] feat(dashboard): add support for moonraker sensor Signed-off-by: Stefan Dej --- .../panels/Miscellaneous/MoonrakerSensor.vue | 48 +++++++++++++++ .../Miscellaneous/MoonrakerSensorValue.vue | 58 +++++++++++++++++++ src/components/panels/MiscellaneousPanel.vue | 21 +++++-- src/store/server/sensor/getters.ts | 6 +- src/store/server/sensor/mutations.ts | 4 +- 5 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 src/components/panels/Miscellaneous/MoonrakerSensor.vue create mode 100644 src/components/panels/Miscellaneous/MoonrakerSensorValue.vue diff --git a/src/components/panels/Miscellaneous/MoonrakerSensor.vue b/src/components/panels/Miscellaneous/MoonrakerSensor.vue new file mode 100644 index 000000000..5e293b6a4 --- /dev/null +++ b/src/components/panels/Miscellaneous/MoonrakerSensor.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue new file mode 100644 index 000000000..0ca8e9789 --- /dev/null +++ b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue @@ -0,0 +1,58 @@ + + + diff --git a/src/components/panels/MiscellaneousPanel.vue b/src/components/panels/MiscellaneousPanel.vue index 9a671d075..976e4cf88 100644 --- a/src/components/panels/MiscellaneousPanel.vue +++ b/src/components/panels/MiscellaneousPanel.vue @@ -8,7 +8,7 @@ :collapsible="true" card-class="miscellaneous-panel">
- + + :multi="parseInt(object.scale)" />
- +
- + + :filament_detected="sensor.filament_detected" /> +
+
+ +
@@ -49,10 +53,11 @@ import BaseMixin from '@/components/mixins/base' import MiscellaneousSlider from '@/components/inputs/MiscellaneousSlider.vue' import MiscellaneousLight from '@/components/inputs/MiscellaneousLight.vue' import FilamentSensor from '@/components/inputs/FilamentSensor.vue' +import MoonrakerSensor from '@/components/panels/Miscellaneous/MoonrakerSensor.vue' import Panel from '@/components/ui/Panel.vue' import { mdiDipSwitch } from '@mdi/js' @Component({ - components: { Panel, FilamentSensor, MiscellaneousSlider, MiscellaneousLight }, + components: { Panel, FilamentSensor, MiscellaneousSlider, MiscellaneousLight, MoonrakerSensor }, }) export default class MiscellaneousPanel extends Mixins(BaseMixin) { mdiDipSwitch = mdiDipSwitch @@ -69,6 +74,10 @@ export default class MiscellaneousPanel extends Mixins(BaseMixin) { return this.$store.getters['printer/getLights'] ?? [] } + get moonrakerSensors() { + return this.$store.getters['server/sensor/getSensors'] ?? [] + } + get showMiscellaneousPanel() { return ( this.klipperReadyForGui && (this.miscellaneous.length || this.filamentSensors.length || this.lights.length) diff --git a/src/store/server/sensor/getters.ts b/src/store/server/sensor/getters.ts index b0b84ee3c..10028f160 100644 --- a/src/store/server/sensor/getters.ts +++ b/src/store/server/sensor/getters.ts @@ -2,4 +2,8 @@ import { GetterTree } from 'vuex' import { ServerSensorState } from '@/store/server/sensor/types' // eslint-disable-next-line -export const getters: GetterTree = {} +export const getters: GetterTree = { + getSensors: (state) => { + return Object.keys(state.sensors) + }, +} diff --git a/src/store/server/sensor/mutations.ts b/src/store/server/sensor/mutations.ts index 5f4df98f4..2e9a7b841 100644 --- a/src/store/server/sensor/mutations.ts +++ b/src/store/server/sensor/mutations.ts @@ -13,6 +13,8 @@ export const mutations: MutationTree = { }, updateSensor(state, payload) { - Vue.set(state.sensors, payload.key, payload.value) + if (!(payload.key in state.sensors)) return + + Vue.set(state.sensors[payload.key], 'values', payload.value) }, } From 71bfc52f57da1bacb1bd8a5a1edac2f6dc993e9f Mon Sep 17 00:00:00 2001 From: Stefan Dej Date: Wed, 22 May 2024 00:03:02 +0200 Subject: [PATCH 06/13] refactor: list values in a table Signed-off-by: Stefan Dej --- .../panels/Miscellaneous/MoonrakerSensor.vue | 14 +++++++++----- .../panels/Miscellaneous/MoonrakerSensorValue.vue | 13 +++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/components/panels/Miscellaneous/MoonrakerSensor.vue b/src/components/panels/Miscellaneous/MoonrakerSensor.vue index 5e293b6a4..7f220577b 100644 --- a/src/components/panels/Miscellaneous/MoonrakerSensor.vue +++ b/src/components/panels/Miscellaneous/MoonrakerSensor.vue @@ -6,11 +6,15 @@ {{ convertName(name) }}
- + + + + +
diff --git a/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue index 0ca8e9789..cf23cefa2 100644 --- a/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue +++ b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue @@ -1,5 +1,9 @@ From 6d9082805a656cb03fc43bdadc3f98d2a1f735f9 Mon Sep 17 00:00:00 2001 From: Patrick Stainbrook Date: Sat, 25 May 2024 23:15:28 +0200 Subject: [PATCH 07/13] wip --- .../panels/Miscellaneous/MoonrakerSensor.vue | 19 ++++++---- .../Miscellaneous/MoonrakerSensorValue.vue | 35 ++++++++++++++++++- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/src/components/panels/Miscellaneous/MoonrakerSensor.vue b/src/components/panels/Miscellaneous/MoonrakerSensor.vue index 7f220577b..1030c2d3b 100644 --- a/src/components/panels/Miscellaneous/MoonrakerSensor.vue +++ b/src/components/panels/Miscellaneous/MoonrakerSensor.vue @@ -2,11 +2,9 @@ - - {{ convertName(name) }} - -
- +
{{ convertName(name) }}
+ +
-
-
+
@@ -27,6 +24,9 @@ import { convertName } from '@/plugins/helpers' import { Component, Mixins, Prop } from 'vue-property-decorator' import BaseMixin from '@/components/mixins/base' import MoonrakerSensorValue from '@/components/panels/Miscellaneous/MoonrakerSensorValue.vue' +import { + +} from '@mdi/js' @Component({ components: { MoonrakerSensorValue }, @@ -48,5 +48,10 @@ export default class MoonrakerSensor extends Mixins(BaseMixin) { diff --git a/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue index cf23cefa2..4cf4c81ea 100644 --- a/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue +++ b/src/components/panels/Miscellaneous/MoonrakerSensorValue.vue @@ -1,6 +1,6 @@